ieee802_1x.c

Go to the documentation of this file.
00001 
00016 #include "includes.h"
00017 
00018 #include "hostapd.h"
00019 #include "ieee802_1x.h"
00020 #include "accounting.h"
00021 #include "radius/radius.h"
00022 #include "radius/radius_client.h"
00023 #include "eapol_sm.h"
00024 #include "md5.h"
00025 #include "crypto.h"
00026 #include "eloop.h"
00027 #include "sta_info.h"
00028 #include "wpa.h"
00029 #include "preauth.h"
00030 #include "pmksa_cache.h"
00031 #include "driver_i.h"
00032 #include "hw_features.h"
00033 #include "eap_server/eap.h"
00034 #include "ieee802_11_defs.h"
00035 #include "wpa_ctrl.h"
00036 
00037 
00038 static void ieee802_1x_finished(struct hostapd_data *hapd,
00039                                 struct sta_info *sta, int success);
00040 
00041 
00042 static void ieee802_1x_send(struct hostapd_data *hapd, struct sta_info *sta,
00043                             u8 type, const u8 *data, size_t datalen)
00044 {
00045         u8 *buf;
00046         struct ieee802_1x_hdr *xhdr;
00047         size_t len;
00048         int encrypt = 0;
00049 
00050         len = sizeof(*xhdr) + datalen;
00051         buf = os_zalloc(len);
00052         if (buf == NULL) {
00053                 wpa_printf(MSG_ERROR, "malloc() failed for "
00054                            "ieee802_1x_send(len=%lu)",
00055                            (unsigned long) len);
00056                 return;
00057         }
00058 
00059         xhdr = (struct ieee802_1x_hdr *) buf;
00060         xhdr->version = hapd->conf->eapol_version;
00061         xhdr->type = type;
00062         xhdr->length = host_to_be16(datalen);
00063 
00064         if (datalen > 0 && data != NULL)
00065                 os_memcpy(xhdr + 1, data, datalen);
00066 
00067         if (wpa_auth_pairwise_set(sta->wpa_sm))
00068                 encrypt = 1;
00069         if (sta->flags & WLAN_STA_PREAUTH) {
00070                 rsn_preauth_send(hapd, sta, buf, len);
00071         } else {
00072                 hostapd_send_eapol(hapd, sta->addr, buf, len, encrypt);
00073         }
00074 
00075         os_free(buf);
00076 }
00077 
00078 
00079 void ieee802_1x_set_sta_authorized(struct hostapd_data *hapd,
00080                                    struct sta_info *sta, int authorized)
00081 {
00082         int res;
00083 
00084         if (sta->flags & WLAN_STA_PREAUTH)
00085                 return;
00086 
00087         if (authorized) {
00088                 if (!(sta->flags & WLAN_STA_AUTHORIZED))
00089                         wpa_msg(hapd->msg_ctx, MSG_INFO,
00090                                 AP_STA_CONNECTED MACSTR, MAC2STR(sta->addr));
00091                 sta->flags |= WLAN_STA_AUTHORIZED;
00092                 res = hostapd_sta_set_flags(hapd, sta->addr, sta->flags,
00093                                             WLAN_STA_AUTHORIZED, ~0);
00094                 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
00095                                HOSTAPD_LEVEL_DEBUG, "authorizing port");
00096         } else {
00097                 if ((sta->flags & (WLAN_STA_AUTHORIZED | WLAN_STA_ASSOC)) ==
00098                     (WLAN_STA_AUTHORIZED | WLAN_STA_ASSOC))
00099                         wpa_msg(hapd->msg_ctx, MSG_INFO,
00100                                 AP_STA_DISCONNECTED MACSTR,
00101                                 MAC2STR(sta->addr));
00102                 sta->flags &= ~WLAN_STA_AUTHORIZED;
00103                 res = hostapd_sta_set_flags(hapd, sta->addr, sta->flags,
00104                                             0, ~WLAN_STA_AUTHORIZED);
00105                 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
00106                                HOSTAPD_LEVEL_DEBUG, "unauthorizing port");
00107         }
00108 
00109         if (res && errno != ENOENT) {
00110                 printf("Could not set station " MACSTR " flags for kernel "
00111                        "driver (errno=%d).\n", MAC2STR(sta->addr), errno);
00112         }
00113 
00114         if (authorized)
00115                 accounting_sta_start(hapd, sta);
00116 }
00117 
00118 
00119 static void ieee802_1x_tx_key_one(struct hostapd_data *hapd,
00120                                   struct sta_info *sta,
00121                                   int idx, int broadcast,
00122                                   u8 *key_data, size_t key_len)
00123 {
00124         u8 *buf, *ekey;
00125         struct ieee802_1x_hdr *hdr;
00126         struct ieee802_1x_eapol_key *key;
00127         size_t len, ekey_len;
00128         struct eapol_state_machine *sm = sta->eapol_sm;
00129 
00130         if (sm == NULL)
00131                 return;
00132 
00133         len = sizeof(*key) + key_len;
00134         buf = os_zalloc(sizeof(*hdr) + len);
00135         if (buf == NULL)
00136                 return;
00137 
00138         hdr = (struct ieee802_1x_hdr *) buf;
00139         key = (struct ieee802_1x_eapol_key *) (hdr + 1);
00140         key->type = EAPOL_KEY_TYPE_RC4;
00141         key->key_length = htons(key_len);
00142         wpa_get_ntp_timestamp(key->replay_counter);
00143 
00144         if (os_get_random(key->key_iv, sizeof(key->key_iv))) {
00145                 wpa_printf(MSG_ERROR, "Could not get random numbers");
00146                 os_free(buf);
00147                 return;
00148         }
00149 
00150         key->key_index = idx | (broadcast ? 0 : BIT(7));
00151         if (hapd->conf->eapol_key_index_workaround) {
00152                 /* According to some information, WinXP Supplicant seems to
00153                  * interpret bit7 as an indication whether the key is to be
00154                  * activated, so make it possible to enable workaround that
00155                  * sets this bit for all keys. */
00156                 key->key_index |= BIT(7);
00157         }
00158 
00159         /* Key is encrypted using "Key-IV + MSK[0..31]" as the RC4-key and
00160          * MSK[32..63] is used to sign the message. */
00161         if (sm->eap_if->eapKeyData == NULL || sm->eap_if->eapKeyDataLen < 64) {
00162                 wpa_printf(MSG_ERROR, "No eapKeyData available for encrypting "
00163                            "and signing EAPOL-Key");
00164                 os_free(buf);
00165                 return;
00166         }
00167         os_memcpy((u8 *) (key + 1), key_data, key_len);
00168         ekey_len = sizeof(key->key_iv) + 32;
00169         ekey = os_malloc(ekey_len);
00170         if (ekey == NULL) {
00171                 wpa_printf(MSG_ERROR, "Could not encrypt key");
00172                 os_free(buf);
00173                 return;
00174         }
00175         os_memcpy(ekey, key->key_iv, sizeof(key->key_iv));
00176         os_memcpy(ekey + sizeof(key->key_iv), sm->eap_if->eapKeyData, 32);
00177         rc4_skip(ekey, ekey_len, 0, (u8 *) (key + 1), key_len);
00178         os_free(ekey);
00179 
00180         /* This header is needed here for HMAC-MD5, but it will be regenerated
00181          * in ieee802_1x_send() */
00182         hdr->version = hapd->conf->eapol_version;
00183         hdr->type = IEEE802_1X_TYPE_EAPOL_KEY;
00184         hdr->length = host_to_be16(len);
00185         hmac_md5(sm->eap_if->eapKeyData + 32, 32, buf, sizeof(*hdr) + len,
00186                  key->key_signature);
00187 
00188         wpa_printf(MSG_DEBUG, "IEEE 802.1X: Sending EAPOL-Key to " MACSTR
00189                    " (%s index=%d)", MAC2STR(sm->addr),
00190                    broadcast ? "broadcast" : "unicast", idx);
00191         ieee802_1x_send(hapd, sta, IEEE802_1X_TYPE_EAPOL_KEY, (u8 *) key, len);
00192         if (sta->eapol_sm)
00193                 sta->eapol_sm->dot1xAuthEapolFramesTx++;
00194         os_free(buf);
00195 }
00196 
00197 
00198 #ifndef CONFIG_NO_VLAN
00199 static struct hostapd_wep_keys *
00200 ieee802_1x_group_alloc(struct hostapd_data *hapd, const char *ifname)
00201 {
00202         struct hostapd_wep_keys *key;
00203 
00204         key = os_zalloc(sizeof(*key));
00205         if (key == NULL)
00206                 return NULL;
00207 
00208         key->default_len = hapd->conf->default_wep_key_len;
00209 
00210         if (key->idx >= hapd->conf->broadcast_key_idx_max ||
00211             key->idx < hapd->conf->broadcast_key_idx_min)
00212                 key->idx = hapd->conf->broadcast_key_idx_min;
00213         else
00214                 key->idx++;
00215 
00216         if (!key->key[key->idx])
00217                 key->key[key->idx] = os_malloc(key->default_len);
00218         if (key->key[key->idx] == NULL ||
00219             os_get_random(key->key[key->idx], key->default_len)) {
00220                 printf("Could not generate random WEP key (dynamic VLAN).\n");
00221                 os_free(key->key[key->idx]);
00222                 key->key[key->idx] = NULL;
00223                 os_free(key);
00224                 return NULL;
00225         }
00226         key->len[key->idx] = key->default_len;
00227 
00228         wpa_printf(MSG_DEBUG, "%s: Default WEP idx %d for dynamic VLAN\n",
00229                    ifname, key->idx);
00230         wpa_hexdump_key(MSG_DEBUG, "Default WEP key (dynamic VLAN)",
00231                         key->key[key->idx], key->len[key->idx]);
00232 
00233         if (hostapd_set_key(ifname, hapd, WPA_ALG_WEP, NULL, key->idx, 1,
00234                             NULL, 0, key->key[key->idx], key->len[key->idx]))
00235                 printf("Could not set dynamic VLAN WEP encryption key.\n");
00236 
00237         hostapd_set_ieee8021x(ifname, hapd, 1);
00238 
00239         return key;
00240 }
00241 
00242 
00243 static struct hostapd_wep_keys *
00244 ieee802_1x_get_group(struct hostapd_data *hapd, struct hostapd_ssid *ssid,
00245                      size_t vlan_id)
00246 {
00247         const char *ifname;
00248 
00249         if (vlan_id == 0)
00250                 return &ssid->wep;
00251 
00252         if (vlan_id <= ssid->max_dyn_vlan_keys && ssid->dyn_vlan_keys &&
00253             ssid->dyn_vlan_keys[vlan_id])
00254                 return ssid->dyn_vlan_keys[vlan_id];
00255 
00256         wpa_printf(MSG_DEBUG, "IEEE 802.1X: Creating new group "
00257                    "state machine for VLAN ID %lu",
00258                    (unsigned long) vlan_id);
00259 
00260         ifname = hostapd_get_vlan_id_ifname(hapd->conf->vlan, vlan_id);
00261         if (ifname == NULL) {
00262                 wpa_printf(MSG_DEBUG, "IEEE 802.1X: Unknown VLAN ID %lu - "
00263                            "cannot create group key state machine",
00264                            (unsigned long) vlan_id);
00265                 return NULL;
00266         }
00267 
00268         if (ssid->dyn_vlan_keys == NULL) {
00269                 int size = (vlan_id + 1) * sizeof(ssid->dyn_vlan_keys[0]);
00270                 ssid->dyn_vlan_keys = os_zalloc(size);
00271                 if (ssid->dyn_vlan_keys == NULL)
00272                         return NULL;
00273                 ssid->max_dyn_vlan_keys = vlan_id;
00274         }
00275 
00276         if (ssid->max_dyn_vlan_keys < vlan_id) {
00277                 struct hostapd_wep_keys **na;
00278                 int size = (vlan_id + 1) * sizeof(ssid->dyn_vlan_keys[0]);
00279                 na = os_realloc(ssid->dyn_vlan_keys, size);
00280                 if (na == NULL)
00281                         return NULL;
00282                 ssid->dyn_vlan_keys = na;
00283                 os_memset(&ssid->dyn_vlan_keys[ssid->max_dyn_vlan_keys + 1], 0,
00284                           (vlan_id - ssid->max_dyn_vlan_keys) *
00285                           sizeof(ssid->dyn_vlan_keys[0]));
00286                 ssid->max_dyn_vlan_keys = vlan_id;
00287         }
00288 
00289         ssid->dyn_vlan_keys[vlan_id] = ieee802_1x_group_alloc(hapd, ifname);
00290 
00291         return ssid->dyn_vlan_keys[vlan_id];
00292 }
00293 #endif /* CONFIG_NO_VLAN */
00294 
00295 
00296 void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta)
00297 {
00298         struct eapol_authenticator *eapol = hapd->eapol_auth;
00299         struct eapol_state_machine *sm = sta->eapol_sm;
00300 #ifndef CONFIG_NO_VLAN
00301         struct hostapd_wep_keys *key = NULL;
00302         int vlan_id;
00303 #endif /* CONFIG_NO_VLAN */
00304 
00305         if (sm == NULL || !sm->eap_if->eapKeyData)
00306                 return;
00307 
00308         wpa_printf(MSG_DEBUG, "IEEE 802.1X: Sending EAPOL-Key(s) to " MACSTR,
00309                    MAC2STR(sta->addr));
00310 
00311 #ifndef CONFIG_NO_VLAN
00312         vlan_id = sta->vlan_id;
00313         if (vlan_id < 0 || vlan_id > MAX_VLAN_ID)
00314                 vlan_id = 0;
00315 
00316         if (vlan_id) {
00317                 key = ieee802_1x_get_group(hapd, sta->ssid, vlan_id);
00318                 if (key && key->key[key->idx])
00319                         ieee802_1x_tx_key_one(hapd, sta, key->idx, 1,
00320                                               key->key[key->idx],
00321                                               key->len[key->idx]);
00322         } else
00323 #endif /* CONFIG_NO_VLAN */
00324         if (eapol->default_wep_key) {
00325                 ieee802_1x_tx_key_one(hapd, sta, eapol->default_wep_key_idx, 1,
00326                                       eapol->default_wep_key,
00327                                       hapd->conf->default_wep_key_len);
00328         }
00329 
00330         if (hapd->conf->individual_wep_key_len > 0) {
00331                 u8 *ikey;
00332                 ikey = os_malloc(hapd->conf->individual_wep_key_len);
00333                 if (ikey == NULL ||
00334                     os_get_random(ikey, hapd->conf->individual_wep_key_len)) {
00335                         wpa_printf(MSG_ERROR, "Could not generate random "
00336                                    "individual WEP key.");
00337                         os_free(ikey);
00338                         return;
00339                 }
00340 
00341                 wpa_hexdump_key(MSG_DEBUG, "Individual WEP key",
00342                                 ikey, hapd->conf->individual_wep_key_len);
00343 
00344                 ieee802_1x_tx_key_one(hapd, sta, 0, 0, ikey,
00345                                       hapd->conf->individual_wep_key_len);
00346 
00347                 /* TODO: set encryption in TX callback, i.e., only after STA
00348                  * has ACKed EAPOL-Key frame */
00349                 if (hostapd_set_key(hapd->conf->iface, hapd, WPA_ALG_WEP,
00350                                     sta->addr, 0, 1, NULL, 0, ikey,
00351                                     hapd->conf->individual_wep_key_len)) {
00352                         wpa_printf(MSG_ERROR, "Could not set individual WEP "
00353                                    "encryption.");
00354                 }
00355 
00356                 os_free(ikey);
00357         }
00358 }
00359 
00360 
00361 const char *radius_mode_txt(struct hostapd_data *hapd)
00362 {
00363         if (hapd->iface->current_mode == NULL)
00364                 return "802.11";
00365 
00366         switch (hapd->iface->current_mode->mode) {
00367         case HOSTAPD_MODE_IEEE80211A:
00368                 return "802.11a";
00369         case HOSTAPD_MODE_IEEE80211G:
00370                 return "802.11g";
00371         case HOSTAPD_MODE_IEEE80211B:
00372         default:
00373                 return "802.11b";
00374         }
00375 }
00376 
00377 
00378 int radius_sta_rate(struct hostapd_data *hapd, struct sta_info *sta)
00379 {
00380         int i;
00381         u8 rate = 0;
00382 
00383         for (i = 0; i < sta->supported_rates_len; i++)
00384                 if ((sta->supported_rates[i] & 0x7f) > rate)
00385                         rate = sta->supported_rates[i] & 0x7f;
00386 
00387         return rate;
00388 }
00389 
00390 
00391 #ifndef CONFIG_NO_RADIUS
00392 static void ieee802_1x_learn_identity(struct hostapd_data *hapd,
00393                                       struct eapol_state_machine *sm,
00394                                       const u8 *eap, size_t len)
00395 {
00396         const u8 *identity;
00397         size_t identity_len;
00398 
00399         if (len <= sizeof(struct eap_hdr) ||
00400             eap[sizeof(struct eap_hdr)] != EAP_TYPE_IDENTITY)
00401                 return;
00402 
00403         identity = eap_get_identity(sm->eap, &identity_len);
00404         if (identity == NULL)
00405                 return;
00406 
00407         /* Save station identity for future RADIUS packets */
00408         os_free(sm->identity);
00409         sm->identity = os_malloc(identity_len + 1);
00410         if (sm->identity == NULL) {
00411                 sm->identity_len = 0;
00412                 return;
00413         }
00414 
00415         os_memcpy(sm->identity, identity, identity_len);
00416         sm->identity_len = identity_len;
00417         sm->identity[identity_len] = '\0';
00418         hostapd_logger(hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X,
00419                        HOSTAPD_LEVEL_DEBUG, "STA identity '%s'", sm->identity);
00420         sm->dot1xAuthEapolRespIdFramesRx++;
00421 }
00422 
00423 
00424 static void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd,
00425                                           struct sta_info *sta,
00426                                           const u8 *eap, size_t len)
00427 {
00428         struct radius_msg *msg;
00429         char buf[128];
00430         struct eapol_state_machine *sm = sta->eapol_sm;
00431 
00432         if (sm == NULL)
00433                 return;
00434 
00435         ieee802_1x_learn_identity(hapd, sm, eap, len);
00436 
00437         wpa_printf(MSG_DEBUG, "Encapsulating EAP message into a RADIUS "
00438                    "packet");
00439 
00440         sm->radius_identifier = radius_client_get_id(hapd->radius);
00441         msg = radius_msg_new(RADIUS_CODE_ACCESS_REQUEST,
00442                              sm->radius_identifier);
00443         if (msg == NULL) {
00444                 printf("Could not create net RADIUS packet\n");
00445                 return;
00446         }
00447 
00448         radius_msg_make_authenticator(msg, (u8 *) sta, sizeof(*sta));
00449 
00450         if (sm->identity &&
00451             !radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME,
00452                                  sm->identity, sm->identity_len)) {
00453                 printf("Could not add User-Name\n");
00454                 goto fail;
00455         }
00456 
00457         if (hapd->conf->own_ip_addr.af == AF_INET &&
00458             !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS,
00459                                  (u8 *) &hapd->conf->own_ip_addr.u.v4, 4)) {
00460                 printf("Could not add NAS-IP-Address\n");
00461                 goto fail;
00462         }
00463 
00464 #ifdef CONFIG_IPV6
00465         if (hapd->conf->own_ip_addr.af == AF_INET6 &&
00466             !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS,
00467                                  (u8 *) &hapd->conf->own_ip_addr.u.v6, 16)) {
00468                 printf("Could not add NAS-IPv6-Address\n");
00469                 goto fail;
00470         }
00471 #endif /* CONFIG_IPV6 */
00472 
00473         if (hapd->conf->nas_identifier &&
00474             !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER,
00475                                  (u8 *) hapd->conf->nas_identifier,
00476                                  os_strlen(hapd->conf->nas_identifier))) {
00477                 printf("Could not add NAS-Identifier\n");
00478                 goto fail;
00479         }
00480 
00481         if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT, sta->aid)) {
00482                 printf("Could not add NAS-Port\n");
00483                 goto fail;
00484         }
00485 
00486         os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s",
00487                     MAC2STR(hapd->own_addr), hapd->conf->ssid.ssid);
00488         buf[sizeof(buf) - 1] = '\0';
00489         if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID,
00490                                  (u8 *) buf, os_strlen(buf))) {
00491                 printf("Could not add Called-Station-Id\n");
00492                 goto fail;
00493         }
00494 
00495         os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT,
00496                     MAC2STR(sta->addr));
00497         buf[sizeof(buf) - 1] = '\0';
00498         if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID,
00499                                  (u8 *) buf, os_strlen(buf))) {
00500                 printf("Could not add Calling-Station-Id\n");
00501                 goto fail;
00502         }
00503 
00504         /* TODO: should probably check MTU from driver config; 2304 is max for
00505          * IEEE 802.11, but use 1400 to avoid problems with too large packets
00506          */
00507         if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_FRAMED_MTU, 1400)) {
00508                 printf("Could not add Framed-MTU\n");
00509                 goto fail;
00510         }
00511 
00512         if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE,
00513                                        RADIUS_NAS_PORT_TYPE_IEEE_802_11)) {
00514                 printf("Could not add NAS-Port-Type\n");
00515                 goto fail;
00516         }
00517 
00518         if (sta->flags & WLAN_STA_PREAUTH) {
00519                 os_strlcpy(buf, "IEEE 802.11i Pre-Authentication",
00520                            sizeof(buf));
00521         } else {
00522                 os_snprintf(buf, sizeof(buf), "CONNECT %d%sMbps %s",
00523                             radius_sta_rate(hapd, sta) / 2,
00524                             (radius_sta_rate(hapd, sta) & 1) ? ".5" : "",
00525                             radius_mode_txt(hapd));
00526                 buf[sizeof(buf) - 1] = '\0';
00527         }
00528         if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO,
00529                                  (u8 *) buf, os_strlen(buf))) {
00530                 printf("Could not add Connect-Info\n");
00531                 goto fail;
00532         }
00533 
00534         if (eap && !radius_msg_add_eap(msg, eap, len)) {
00535                 printf("Could not add EAP-Message\n");
00536                 goto fail;
00537         }
00538 
00539         /* State attribute must be copied if and only if this packet is
00540          * Access-Request reply to the previous Access-Challenge */
00541         if (sm->last_recv_radius && sm->last_recv_radius->hdr->code ==
00542             RADIUS_CODE_ACCESS_CHALLENGE) {
00543                 int res = radius_msg_copy_attr(msg, sm->last_recv_radius,
00544                                                RADIUS_ATTR_STATE);
00545                 if (res < 0) {
00546                         printf("Could not copy State attribute from previous "
00547                                "Access-Challenge\n");
00548                         goto fail;
00549                 }
00550                 if (res > 0) {
00551                         wpa_printf(MSG_DEBUG, "Copied RADIUS State Attribute");
00552                 }
00553         }
00554 
00555         radius_client_send(hapd->radius, msg, RADIUS_AUTH, sta->addr);
00556         return;
00557 
00558  fail:
00559         radius_msg_free(msg);
00560         os_free(msg);
00561 }
00562 #endif /* CONFIG_NO_RADIUS */
00563 
00564 
00565 char *eap_type_text(u8 type)
00566 {
00567         switch (type) {
00568         case EAP_TYPE_IDENTITY: return "Identity";
00569         case EAP_TYPE_NOTIFICATION: return "Notification";
00570         case EAP_TYPE_NAK: return "Nak";
00571         case EAP_TYPE_MD5: return "MD5-Challenge";
00572         case EAP_TYPE_OTP: return "One-Time Password";
00573         case EAP_TYPE_GTC: return "Generic Token Card";
00574         case EAP_TYPE_TLS: return "TLS";
00575         case EAP_TYPE_TTLS: return "TTLS";
00576         case EAP_TYPE_PEAP: return "PEAP";
00577         case EAP_TYPE_SIM: return "SIM";
00578         case EAP_TYPE_FAST: return "FAST";
00579         case EAP_TYPE_SAKE: return "SAKE";
00580         case EAP_TYPE_PSK: return "PSK";
00581         case EAP_TYPE_PAX: return "PAX";
00582         default: return "Unknown";
00583         }
00584 }
00585 
00586 
00587 static void handle_eap_response(struct hostapd_data *hapd,
00588                                 struct sta_info *sta, struct eap_hdr *eap,
00589                                 size_t len)
00590 {
00591         u8 type, *data;
00592         struct eapol_state_machine *sm = sta->eapol_sm;
00593         if (sm == NULL)
00594                 return;
00595 
00596         data = (u8 *) (eap + 1);
00597 
00598         if (len < sizeof(*eap) + 1) {
00599                 printf("handle_eap_response: too short response data\n");
00600                 return;
00601         }
00602 
00603         sm->eap_type_supp = type = data[0];
00604 
00605         hostapd_logger(hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X,
00606                        HOSTAPD_LEVEL_DEBUG, "received EAP packet (code=%d "
00607                        "id=%d len=%d) from STA: EAP Response-%s (%d)",
00608                        eap->code, eap->identifier, be_to_host16(eap->length),
00609                        eap_type_text(type), type);
00610 
00611         sm->dot1xAuthEapolRespFramesRx++;
00612 
00613         wpabuf_free(sm->eap_if->eapRespData);
00614         sm->eap_if->eapRespData = wpabuf_alloc_copy(eap, len);
00615         sm->eapolEap = TRUE;
00616 }
00617 
00618 
00619 /* Process incoming EAP packet from Supplicant */
00620 static void handle_eap(struct hostapd_data *hapd, struct sta_info *sta,
00621                        u8 *buf, size_t len)
00622 {
00623         struct eap_hdr *eap;
00624         u16 eap_len;
00625 
00626         if (len < sizeof(*eap)) {
00627                 printf("   too short EAP packet\n");
00628                 return;
00629         }
00630 
00631         eap = (struct eap_hdr *) buf;
00632 
00633         eap_len = be_to_host16(eap->length);
00634         wpa_printf(MSG_DEBUG, "EAP: code=%d identifier=%d length=%d",
00635                    eap->code, eap->identifier, eap_len);
00636         if (eap_len < sizeof(*eap)) {
00637                 wpa_printf(MSG_DEBUG, "   Invalid EAP length");
00638                 return;
00639         } else if (eap_len > len) {
00640                 wpa_printf(MSG_DEBUG, "   Too short frame to contain this EAP "
00641                            "packet");
00642                 return;
00643         } else if (eap_len < len) {
00644                 wpa_printf(MSG_DEBUG, "   Ignoring %lu extra bytes after EAP "
00645                            "packet", (unsigned long) len - eap_len);
00646         }
00647 
00648         switch (eap->code) {
00649         case EAP_CODE_REQUEST:
00650                 wpa_printf(MSG_DEBUG, " (request)");
00651                 return;
00652         case EAP_CODE_RESPONSE:
00653                 wpa_printf(MSG_DEBUG, " (response)");
00654                 handle_eap_response(hapd, sta, eap, eap_len);
00655                 break;
00656         case EAP_CODE_SUCCESS:
00657                 wpa_printf(MSG_DEBUG, " (success)");
00658                 return;
00659         case EAP_CODE_FAILURE:
00660                 wpa_printf(MSG_DEBUG, " (failure)");
00661                 return;
00662         default:
00663                 wpa_printf(MSG_DEBUG, " (unknown code)");
00664                 return;
00665         }
00666 }
00667 
00668 
00679 void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
00680                         size_t len)
00681 {
00682         struct sta_info *sta;
00683         struct ieee802_1x_hdr *hdr;
00684         struct ieee802_1x_eapol_key *key;
00685         u16 datalen;
00686         struct rsn_pmksa_cache_entry *pmksa;
00687 
00688         if (!hapd->conf->ieee802_1x && !hapd->conf->wpa &&
00689             !hapd->conf->wps_state)
00690                 return;
00691 
00692         wpa_printf(MSG_DEBUG, "IEEE 802.1X: %lu bytes from " MACSTR,
00693                    (unsigned long) len, MAC2STR(sa));
00694         sta = ap_get_sta(hapd, sa);
00695         if (!sta || !(sta->flags & WLAN_STA_ASSOC)) {
00696                 wpa_printf(MSG_DEBUG, "IEEE 802.1X data frame from not "
00697                            "associated STA");
00698                 return;
00699         }
00700 
00701         if (len < sizeof(*hdr)) {
00702                 printf("   too short IEEE 802.1X packet\n");
00703                 return;
00704         }
00705 
00706         hdr = (struct ieee802_1x_hdr *) buf;
00707         datalen = be_to_host16(hdr->length);
00708         wpa_printf(MSG_DEBUG, "   IEEE 802.1X: version=%d type=%d length=%d",
00709                    hdr->version, hdr->type, datalen);
00710 
00711         if (len - sizeof(*hdr) < datalen) {
00712                 printf("   frame too short for this IEEE 802.1X packet\n");
00713                 if (sta->eapol_sm)
00714                         sta->eapol_sm->dot1xAuthEapLengthErrorFramesRx++;
00715                 return;
00716         }
00717         if (len - sizeof(*hdr) > datalen) {
00718                 wpa_printf(MSG_DEBUG, "   ignoring %lu extra octets after "
00719                            "IEEE 802.1X packet",
00720                            (unsigned long) len - sizeof(*hdr) - datalen);
00721         }
00722 
00723         if (sta->eapol_sm) {
00724                 sta->eapol_sm->dot1xAuthLastEapolFrameVersion = hdr->version;
00725                 sta->eapol_sm->dot1xAuthEapolFramesRx++;
00726         }
00727 
00728         key = (struct ieee802_1x_eapol_key *) (hdr + 1);
00729         if (datalen >= sizeof(struct ieee802_1x_eapol_key) &&
00730             hdr->type == IEEE802_1X_TYPE_EAPOL_KEY &&
00731             (key->type == EAPOL_KEY_TYPE_WPA ||
00732              key->type == EAPOL_KEY_TYPE_RSN)) {
00733                 wpa_receive(hapd->wpa_auth, sta->wpa_sm, (u8 *) hdr,
00734                             sizeof(*hdr) + datalen);
00735                 return;
00736         }
00737 
00738         if ((!hapd->conf->ieee802_1x &&
00739              !(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) ||
00740             wpa_key_mgmt_wpa_psk(wpa_auth_sta_key_mgmt(sta->wpa_sm)))
00741                 return;
00742 
00743         if (!sta->eapol_sm) {
00744                 sta->eapol_sm = eapol_auth_alloc(hapd->eapol_auth, sta->addr,
00745                                                  sta->flags & WLAN_STA_PREAUTH,
00746                                                  sta);
00747                 if (!sta->eapol_sm)
00748                         return;
00749 
00750 #ifdef CONFIG_WPS
00751                 if (!hapd->conf->ieee802_1x &&
00752                     ((sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)) ==
00753                      WLAN_STA_MAYBE_WPS)) {
00754                         /*
00755                          * Delay EAPOL frame transmission until a possible WPS
00756                          * STA initiates the handshake with EAPOL-Start.
00757                          */
00758                         sta->eapol_sm->flags |= EAPOL_SM_WAIT_START;
00759                 }
00760 #endif /* CONFIG_WPS */
00761 
00762                 sta->eapol_sm->eap_if->portEnabled = TRUE;
00763         }
00764 
00765         /* since we support version 1, we can ignore version field and proceed
00766          * as specified in version 1 standard [IEEE Std 802.1X-2001, 7.5.5] */
00767         /* TODO: actually, we are not version 1 anymore.. However, Version 2
00768          * does not change frame contents, so should be ok to process frames
00769          * more or less identically. Some changes might be needed for
00770          * verification of fields. */
00771 
00772         switch (hdr->type) {
00773         case IEEE802_1X_TYPE_EAP_PACKET:
00774                 handle_eap(hapd, sta, (u8 *) (hdr + 1), datalen);
00775                 break;
00776 
00777         case IEEE802_1X_TYPE_EAPOL_START:
00778                 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
00779                                HOSTAPD_LEVEL_DEBUG, "received EAPOL-Start "
00780                                "from STA");
00781                 sta->eapol_sm->flags &= ~EAPOL_SM_WAIT_START;
00782                 pmksa = wpa_auth_sta_get_pmksa(sta->wpa_sm);
00783                 if (pmksa) {
00784                         hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,
00785                                        HOSTAPD_LEVEL_DEBUG, "cached PMKSA "
00786                                        "available - ignore it since "
00787                                        "STA sent EAPOL-Start");
00788                         wpa_auth_sta_clear_pmksa(sta->wpa_sm, pmksa);
00789                 }
00790                 sta->eapol_sm->eapolStart = TRUE;
00791                 sta->eapol_sm->dot1xAuthEapolStartFramesRx++;
00792                 wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH_EAPOL);
00793                 break;
00794 
00795         case IEEE802_1X_TYPE_EAPOL_LOGOFF:
00796                 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
00797                                HOSTAPD_LEVEL_DEBUG, "received EAPOL-Logoff "
00798                                "from STA");
00799                 sta->acct_terminate_cause =
00800                         RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
00801                 accounting_sta_stop(hapd, sta);
00802                 sta->eapol_sm->eapolLogoff = TRUE;
00803                 sta->eapol_sm->dot1xAuthEapolLogoffFramesRx++;
00804                 break;
00805 
00806         case IEEE802_1X_TYPE_EAPOL_KEY:
00807                 wpa_printf(MSG_DEBUG, "   EAPOL-Key");
00808                 if (!(sta->flags & WLAN_STA_AUTHORIZED)) {
00809                         wpa_printf(MSG_DEBUG, "   Dropped key data from "
00810                                    "unauthorized Supplicant");
00811                         break;
00812                 }
00813                 break;
00814 
00815         case IEEE802_1X_TYPE_EAPOL_ENCAPSULATED_ASF_ALERT:
00816                 wpa_printf(MSG_DEBUG, "   EAPOL-Encapsulated-ASF-Alert");
00817                 /* TODO: implement support for this; show data */
00818                 break;
00819 
00820         default:
00821                 wpa_printf(MSG_DEBUG, "   unknown IEEE 802.1X packet type");
00822                 sta->eapol_sm->dot1xAuthInvalidEapolFramesRx++;
00823                 break;
00824         }
00825 
00826         eapol_auth_step(sta->eapol_sm);
00827 }
00828 
00829 
00839 void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
00840 {
00841         struct rsn_pmksa_cache_entry *pmksa;
00842         int reassoc = 1;
00843         int force_1x = 0;
00844 
00845 #ifdef CONFIG_WPS
00846         if (hapd->conf->wps_state && hapd->conf->wpa &&
00847             (sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) {
00848                 /*
00849                  * Need to enable IEEE 802.1X/EAPOL state machines for possible
00850                  * WPS handshake even if IEEE 802.1X/EAPOL is not used for
00851                  * authentication in this BSS.
00852                  */
00853                 force_1x = 1;
00854         }
00855 #endif /* CONFIG_WPS */
00856 
00857         if ((!force_1x && !hapd->conf->ieee802_1x) ||
00858             wpa_key_mgmt_wpa_psk(wpa_auth_sta_key_mgmt(sta->wpa_sm)))
00859                 return;
00860 
00861         if (sta->eapol_sm == NULL) {
00862                 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
00863                                HOSTAPD_LEVEL_DEBUG, "start authentication");
00864                 sta->eapol_sm = eapol_auth_alloc(hapd->eapol_auth, sta->addr,
00865                                                  sta->flags & WLAN_STA_PREAUTH,
00866                                                  sta);
00867                 if (sta->eapol_sm == NULL) {
00868                         hostapd_logger(hapd, sta->addr,
00869                                        HOSTAPD_MODULE_IEEE8021X,
00870                                        HOSTAPD_LEVEL_INFO,
00871                                        "failed to allocate state machine");
00872                         return;
00873                 }
00874                 reassoc = 0;
00875         }
00876 
00877 #ifdef CONFIG_WPS
00878         sta->eapol_sm->flags &= ~EAPOL_SM_WAIT_START;
00879         if (!hapd->conf->ieee802_1x && !(sta->flags & WLAN_STA_WPS)) {
00880                 /*
00881                  * Delay EAPOL frame transmission until a possible WPS
00882                  * initiates the handshake with EAPOL-Start.
00883                  */
00884                 sta->eapol_sm->flags |= EAPOL_SM_WAIT_START;
00885         }
00886 #endif /* CONFIG_WPS */
00887 
00888         sta->eapol_sm->eap_if->portEnabled = TRUE;
00889 
00890         pmksa = wpa_auth_sta_get_pmksa(sta->wpa_sm);
00891         if (pmksa) {
00892                 int old_vlanid;
00893 
00894                 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
00895                                HOSTAPD_LEVEL_DEBUG,
00896                                "PMK from PMKSA cache - skip IEEE 802.1X/EAP");
00897                 /* Setup EAPOL state machines to already authenticated state
00898                  * because of existing PMKSA information in the cache. */
00899                 sta->eapol_sm->keyRun = TRUE;
00900                 sta->eapol_sm->eap_if->eapKeyAvailable = TRUE;
00901                 sta->eapol_sm->auth_pae_state = AUTH_PAE_AUTHENTICATING;
00902                 sta->eapol_sm->be_auth_state = BE_AUTH_SUCCESS;
00903                 sta->eapol_sm->authSuccess = TRUE;
00904                 if (sta->eapol_sm->eap)
00905                         eap_sm_notify_cached(sta->eapol_sm->eap);
00906                 old_vlanid = sta->vlan_id;
00907                 pmksa_cache_to_eapol_data(pmksa, sta->eapol_sm);
00908                 if (sta->ssid->dynamic_vlan == DYNAMIC_VLAN_DISABLED)
00909                         sta->vlan_id = 0;
00910                 ap_sta_bind_vlan(hapd, sta, old_vlanid);
00911         } else {
00912                 if (reassoc) {
00913                         /*
00914                          * Force EAPOL state machines to start
00915                          * re-authentication without having to wait for the
00916                          * Supplicant to send EAPOL-Start.
00917                          */
00918                         sta->eapol_sm->reAuthenticate = TRUE;
00919                 }
00920                 eapol_auth_step(sta->eapol_sm);
00921         }
00922 }
00923 
00924 
00925 void ieee802_1x_free_station(struct sta_info *sta)
00926 {
00927         struct eapol_state_machine *sm = sta->eapol_sm;
00928 
00929         if (sm == NULL)
00930                 return;
00931 
00932         sta->eapol_sm = NULL;
00933 
00934 #ifndef CONFIG_NO_RADIUS
00935         if (sm->last_recv_radius) {
00936                 radius_msg_free(sm->last_recv_radius);
00937                 os_free(sm->last_recv_radius);
00938         }
00939         radius_free_class(&sm->radius_class);
00940 #endif /* CONFIG_NO_RADIUS */
00941 
00942         os_free(sm->identity);
00943         eapol_auth_free(sm);
00944 }
00945 
00946 
00947 #ifndef CONFIG_NO_RADIUS
00948 static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd,
00949                                           struct sta_info *sta)
00950 {
00951         u8 *eap;
00952         size_t len;
00953         struct eap_hdr *hdr;
00954         int eap_type = -1;
00955         char buf[64];
00956         struct radius_msg *msg;
00957         struct eapol_state_machine *sm = sta->eapol_sm;
00958 
00959         if (sm == NULL || sm->last_recv_radius == NULL) {
00960                 if (sm)
00961                         sm->eap_if->aaaEapNoReq = TRUE;
00962                 return;
00963         }
00964 
00965         msg = sm->last_recv_radius;
00966 
00967         eap = radius_msg_get_eap(msg, &len);
00968         if (eap == NULL) {
00969                 /* RFC 3579, Chap. 2.6.3:
00970                  * RADIUS server SHOULD NOT send Access-Reject/no EAP-Message
00971                  * attribute */
00972                 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
00973                                HOSTAPD_LEVEL_WARNING, "could not extract "
00974                                "EAP-Message from RADIUS message");
00975                 sm->eap_if->aaaEapNoReq = TRUE;
00976                 return;
00977         }
00978 
00979         if (len < sizeof(*hdr)) {
00980                 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
00981                                HOSTAPD_LEVEL_WARNING, "too short EAP packet "
00982                                "received from authentication server");
00983                 os_free(eap);
00984                 sm->eap_if->aaaEapNoReq = TRUE;
00985                 return;
00986         }
00987 
00988         if (len > sizeof(*hdr))
00989                 eap_type = eap[sizeof(*hdr)];
00990 
00991         hdr = (struct eap_hdr *) eap;
00992         switch (hdr->code) {
00993         case EAP_CODE_REQUEST:
00994                 if (eap_type >= 0)
00995                         sm->eap_type_authsrv = eap_type;
00996                 os_snprintf(buf, sizeof(buf), "EAP-Request-%s (%d)",
00997                             eap_type >= 0 ? eap_type_text(eap_type) : "??",
00998                             eap_type);
00999                 break;
01000         case EAP_CODE_RESPONSE:
01001                 os_snprintf(buf, sizeof(buf), "EAP Response-%s (%d)",
01002                             eap_type >= 0 ? eap_type_text(eap_type) : "??",
01003                             eap_type);
01004                 break;
01005         case EAP_CODE_SUCCESS:
01006                 os_strlcpy(buf, "EAP Success", sizeof(buf));
01007                 break;
01008         case EAP_CODE_FAILURE:
01009                 os_strlcpy(buf, "EAP Failure", sizeof(buf));
01010                 break;
01011         default:
01012                 os_strlcpy(buf, "unknown EAP code", sizeof(buf));
01013                 break;
01014         }
01015         buf[sizeof(buf) - 1] = '\0';
01016         hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
01017                        HOSTAPD_LEVEL_DEBUG, "decapsulated EAP packet (code=%d "
01018                        "id=%d len=%d) from RADIUS server: %s",
01019                        hdr->code, hdr->identifier, be_to_host16(hdr->length),
01020                        buf);
01021         sm->eap_if->aaaEapReq = TRUE;
01022 
01023         wpabuf_free(sm->eap_if->aaaEapReqData);
01024         sm->eap_if->aaaEapReqData = wpabuf_alloc_ext_data(eap, len);
01025 }
01026 
01027 
01028 static void ieee802_1x_get_keys(struct hostapd_data *hapd,
01029                                 struct sta_info *sta, struct radius_msg *msg,
01030                                 struct radius_msg *req,
01031                                 const u8 *shared_secret,
01032                                 size_t shared_secret_len)
01033 {
01034         struct radius_ms_mppe_keys *keys;
01035         struct eapol_state_machine *sm = sta->eapol_sm;
01036         if (sm == NULL)
01037                 return;
01038 
01039         keys = radius_msg_get_ms_keys(msg, req, shared_secret,
01040                                       shared_secret_len);
01041 
01042         if (keys && keys->send && keys->recv) {
01043                 size_t len = keys->send_len + keys->recv_len;
01044                 wpa_hexdump_key(MSG_DEBUG, "MS-MPPE-Send-Key",
01045                                 keys->send, keys->send_len);
01046                 wpa_hexdump_key(MSG_DEBUG, "MS-MPPE-Recv-Key",
01047                                 keys->recv, keys->recv_len);
01048 
01049                 os_free(sm->eap_if->aaaEapKeyData);
01050                 sm->eap_if->aaaEapKeyData = os_malloc(len);
01051                 if (sm->eap_if->aaaEapKeyData) {
01052                         os_memcpy(sm->eap_if->aaaEapKeyData, keys->recv,
01053                                   keys->recv_len);
01054                         os_memcpy(sm->eap_if->aaaEapKeyData + keys->recv_len,
01055                                   keys->send, keys->send_len);
01056                         sm->eap_if->aaaEapKeyDataLen = len;
01057                         sm->eap_if->aaaEapKeyAvailable = TRUE;
01058                 }
01059         }
01060 
01061         if (keys) {
01062                 os_free(keys->send);
01063                 os_free(keys->recv);
01064                 os_free(keys);
01065         }
01066 }
01067 
01068 
01069 static void ieee802_1x_store_radius_class(struct hostapd_data *hapd,
01070                                           struct sta_info *sta,
01071                                           struct radius_msg *msg)
01072 {
01073         u8 *class;
01074         size_t class_len;
01075         struct eapol_state_machine *sm = sta->eapol_sm;
01076         int count, i;
01077         struct radius_attr_data *nclass;
01078         size_t nclass_count;
01079 
01080         if (!hapd->conf->radius->acct_server || hapd->radius == NULL ||
01081             sm == NULL)
01082                 return;
01083 
01084         radius_free_class(&sm->radius_class);
01085         count = radius_msg_count_attr(msg, RADIUS_ATTR_CLASS, 1);
01086         if (count <= 0)
01087                 return;
01088 
01089         nclass = os_zalloc(count * sizeof(struct radius_attr_data));
01090         if (nclass == NULL)
01091                 return;
01092 
01093         nclass_count = 0;
01094 
01095         class = NULL;
01096         for (i = 0; i < count; i++) {
01097                 do {
01098                         if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_CLASS,
01099                                                     &class, &class_len,
01100                                                     class) < 0) {
01101                                 i = count;
01102                                 break;
01103                         }
01104                 } while (class_len < 1);
01105 
01106                 nclass[nclass_count].data = os_malloc(class_len);
01107                 if (nclass[nclass_count].data == NULL)
01108                         break;
01109 
01110                 os_memcpy(nclass[nclass_count].data, class, class_len);
01111                 nclass[nclass_count].len = class_len;
01112                 nclass_count++;
01113         }
01114 
01115         sm->radius_class.attr = nclass;
01116         sm->radius_class.count = nclass_count;
01117         wpa_printf(MSG_DEBUG, "IEEE 802.1X: Stored %lu RADIUS Class "
01118                    "attributes for " MACSTR,
01119                    (unsigned long) sm->radius_class.count,
01120                    MAC2STR(sta->addr));
01121 }
01122 
01123 
01124 /* Update sta->identity based on User-Name attribute in Access-Accept */
01125 static void ieee802_1x_update_sta_identity(struct hostapd_data *hapd,
01126                                            struct sta_info *sta,
01127                                            struct radius_msg *msg)
01128 {
01129         u8 *buf, *identity;
01130         size_t len;
01131         struct eapol_state_machine *sm = sta->eapol_sm;
01132 
01133         if (sm == NULL)
01134                 return;
01135 
01136         if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_USER_NAME, &buf, &len,
01137                                     NULL) < 0)
01138                 return;
01139 
01140         identity = os_malloc(len + 1);
01141         if (identity == NULL)
01142                 return;
01143 
01144         os_memcpy(identity, buf, len);
01145         identity[len] = '\0';
01146 
01147         hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
01148                        HOSTAPD_LEVEL_DEBUG, "old identity '%s' updated with "
01149                        "User-Name from Access-Accept '%s'",
01150                        sm->identity ? (char *) sm->identity : "N/A",
01151                        (char *) identity);
01152 
01153         os_free(sm->identity);
01154         sm->identity = identity;
01155         sm->identity_len = len;
01156 }
01157 
01158 
01159 struct sta_id_search {
01160         u8 identifier;
01161         struct eapol_state_machine *sm;
01162 };
01163 
01164 
01165 static int ieee802_1x_select_radius_identifier(struct hostapd_data *hapd,
01166                                                struct sta_info *sta,
01167                                                void *ctx)
01168 {
01169         struct sta_id_search *id_search = ctx;
01170         struct eapol_state_machine *sm = sta->eapol_sm;
01171 
01172         if (sm && sm->radius_identifier >= 0 &&
01173             sm->radius_identifier == id_search->identifier) {
01174                 id_search->sm = sm;
01175                 return 1;
01176         }
01177         return 0;
01178 }
01179 
01180 
01181 static struct eapol_state_machine *
01182 ieee802_1x_search_radius_identifier(struct hostapd_data *hapd, u8 identifier)
01183 {
01184         struct sta_id_search id_search;
01185         id_search.identifier = identifier;
01186         id_search.sm = NULL;
01187         ap_for_each_sta(hapd, ieee802_1x_select_radius_identifier, &id_search);
01188         return id_search.sm;
01189 }
01190 
01191 
01202 static RadiusRxResult
01203 ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
01204                         const u8 *shared_secret, size_t shared_secret_len,
01205                         void *data)
01206 {
01207         struct hostapd_data *hapd = data;
01208         struct sta_info *sta;
01209         u32 session_timeout = 0, termination_action, acct_interim_interval;
01210         int session_timeout_set, old_vlanid = 0;
01211         struct eapol_state_machine *sm;
01212         int override_eapReq = 0;
01213 
01214         sm = ieee802_1x_search_radius_identifier(hapd, msg->hdr->identifier);
01215         if (sm == NULL) {
01216                 wpa_printf(MSG_DEBUG, "IEEE 802.1X: Could not find matching "
01217                            "station for this RADIUS message");
01218                 return RADIUS_RX_UNKNOWN;
01219         }
01220         sta = sm->sta;
01221 
01222         /* RFC 2869, Ch. 5.13: valid Message-Authenticator attribute MUST be
01223          * present when packet contains an EAP-Message attribute */
01224         if (msg->hdr->code == RADIUS_CODE_ACCESS_REJECT &&
01225             radius_msg_get_attr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR, NULL,
01226                                 0) < 0 &&
01227             radius_msg_get_attr(msg, RADIUS_ATTR_EAP_MESSAGE, NULL, 0) < 0) {
01228                 wpa_printf(MSG_DEBUG, "Allowing RADIUS Access-Reject without "
01229                            "Message-Authenticator since it does not include "
01230                            "EAP-Message");
01231         } else if (radius_msg_verify(msg, shared_secret, shared_secret_len,
01232                                      req, 1)) {
01233                 printf("Incoming RADIUS packet did not have correct "
01234                        "Message-Authenticator - dropped\n");
01235                 return RADIUS_RX_INVALID_AUTHENTICATOR;
01236         }
01237 
01238         if (msg->hdr->code != RADIUS_CODE_ACCESS_ACCEPT &&
01239             msg->hdr->code != RADIUS_CODE_ACCESS_REJECT &&
01240             msg->hdr->code != RADIUS_CODE_ACCESS_CHALLENGE) {
01241                 printf("Unknown RADIUS message code\n");
01242                 return RADIUS_RX_UNKNOWN;
01243         }
01244 
01245         sm->radius_identifier = -1;
01246         wpa_printf(MSG_DEBUG, "RADIUS packet matching with station " MACSTR,
01247                    MAC2STR(sta->addr));
01248 
01249         if (sm->last_recv_radius) {
01250                 radius_msg_free(sm->last_recv_radius);
01251                 os_free(sm->last_recv_radius);
01252         }
01253 
01254         sm->last_recv_radius = msg;
01255 
01256         session_timeout_set =
01257                 !radius_msg_get_attr_int32(msg, RADIUS_ATTR_SESSION_TIMEOUT,
01258                                            &session_timeout);
01259         if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_TERMINATION_ACTION,
01260                                       &termination_action))
01261                 termination_action = RADIUS_TERMINATION_ACTION_DEFAULT;
01262 
01263         if (hapd->conf->radius->acct_interim_interval == 0 &&
01264             msg->hdr->code == RADIUS_CODE_ACCESS_ACCEPT &&
01265             radius_msg_get_attr_int32(msg, RADIUS_ATTR_ACCT_INTERIM_INTERVAL,
01266                                       &acct_interim_interval) == 0) {
01267                 if (acct_interim_interval < 60) {
01268                         hostapd_logger(hapd, sta->addr,
01269                                        HOSTAPD_MODULE_IEEE8021X,
01270                                        HOSTAPD_LEVEL_INFO,
01271                                        "ignored too small "
01272                                        "Acct-Interim-Interval %d",
01273                                        acct_interim_interval);
01274                 } else
01275                         sta->acct_interim_interval = acct_interim_interval;
01276         }
01277 
01278 
01279         switch (msg->hdr->code) {
01280         case RADIUS_CODE_ACCESS_ACCEPT:
01281                 if (sta->ssid->dynamic_vlan == DYNAMIC_VLAN_DISABLED)
01282                         sta->vlan_id = 0;
01283 #ifndef CONFIG_NO_VLAN
01284                 else {
01285                         old_vlanid = sta->vlan_id;
01286                         sta->vlan_id = radius_msg_get_vlanid(msg);
01287                 }
01288                 if (sta->vlan_id > 0 &&
01289                     hostapd_get_vlan_id_ifname(hapd->conf->vlan,
01290                                                sta->vlan_id)) {
01291                         hostapd_logger(hapd, sta->addr,
01292                                        HOSTAPD_MODULE_RADIUS,
01293                                        HOSTAPD_LEVEL_INFO,
01294                                        "VLAN ID %d", sta->vlan_id);
01295                 } else if (sta->ssid->dynamic_vlan == DYNAMIC_VLAN_REQUIRED) {
01296                         sta->eapol_sm->authFail = TRUE;
01297                         hostapd_logger(hapd, sta->addr,
01298                                        HOSTAPD_MODULE_IEEE8021X,
01299                                        HOSTAPD_LEVEL_INFO, "authentication "
01300                                        "server did not include required VLAN "
01301                                        "ID in Access-Accept");
01302                         break;
01303                 }
01304 #endif /* CONFIG_NO_VLAN */
01305 
01306                 ap_sta_bind_vlan(hapd, sta, old_vlanid);
01307 
01308                 /* RFC 3580, Ch. 3.17 */
01309                 if (session_timeout_set && termination_action ==
01310                     RADIUS_TERMINATION_ACTION_RADIUS_REQUEST) {
01311                         sm->reAuthPeriod = session_timeout;
01312                 } else if (session_timeout_set)
01313                         ap_sta_session_timeout(hapd, sta, session_timeout);
01314 
01315                 sm->eap_if->aaaSuccess = TRUE;
01316                 override_eapReq = 1;
01317                 ieee802_1x_get_keys(hapd, sta, msg, req, shared_secret,
01318                                     shared_secret_len);
01319                 ieee802_1x_store_radius_class(hapd, sta, msg);
01320                 ieee802_1x_update_sta_identity(hapd, sta, msg);
01321                 if (sm->eap_if->eapKeyAvailable &&
01322                     wpa_auth_pmksa_add(sta->wpa_sm, sm->eapol_key_crypt,
01323                                        session_timeout_set ?
01324                                        (int) session_timeout : -1, sm) == 0) {
01325                         hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,
01326                                        HOSTAPD_LEVEL_DEBUG,
01327                                        "Added PMKSA cache entry");
01328                 }
01329                 break;
01330         case RADIUS_CODE_ACCESS_REJECT:
01331                 sm->eap_if->aaaFail = TRUE;
01332                 override_eapReq = 1;
01333                 break;
01334         case RADIUS_CODE_ACCESS_CHALLENGE:
01335                 sm->eap_if->aaaEapReq = TRUE;
01336                 if (session_timeout_set) {
01337                         /* RFC 2869, Ch. 2.3.2; RFC 3580, Ch. 3.17 */
01338                         sm->eap_if->aaaMethodTimeout = session_timeout;
01339                         hostapd_logger(hapd, sm->addr,
01340                                        HOSTAPD_MODULE_IEEE8021X,
01341                                        HOSTAPD_LEVEL_DEBUG,
01342                                        "using EAP timeout of %d seconds (from "
01343                                        "RADIUS)",
01344                                        sm->eap_if->aaaMethodTimeout);
01345                 } else {
01346                         /*
01347                          * Use dynamic retransmission behavior per EAP
01348                          * specification.
01349                          */
01350                         sm->eap_if->aaaMethodTimeout = 0;
01351                 }
01352                 break;
01353         }
01354 
01355         ieee802_1x_decapsulate_radius(hapd, sta);
01356         if (override_eapReq)
01357                 sm->eap_if->aaaEapReq = FALSE;
01358 
01359         eapol_auth_step(sm);
01360 
01361         return RADIUS_RX_QUEUED;
01362 }
01363 #endif /* CONFIG_NO_RADIUS */
01364 
01365 
01366 void ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta)
01367 {
01368         struct eapol_state_machine *sm = sta->eapol_sm;
01369         if (sm == NULL)
01370                 return;
01371 
01372         hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
01373                        HOSTAPD_LEVEL_DEBUG, "aborting authentication");
01374 
01375 #ifndef CONFIG_NO_RADIUS
01376         if (sm->last_recv_radius) {
01377                 radius_msg_free(sm->last_recv_radius);
01378                 os_free(sm->last_recv_radius);
01379                 sm->last_recv_radius = NULL;
01380         }
01381 #endif /* CONFIG_NO_RADIUS */
01382 
01383         if (sm->eap_if->eapTimeout) {
01384                 /*
01385                  * Disconnect the STA since it did not reply to the last EAP
01386                  * request and we cannot continue EAP processing (EAP-Failure
01387                  * could only be sent if the EAP peer actually replied).
01388                  */
01389                 sm->eap_if->portEnabled = FALSE;
01390                 hostapd_sta_deauth(hapd, sta->addr,
01391                                    WLAN_REASON_PREV_AUTH_NOT_VALID);
01392                 sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC |
01393                                 WLAN_STA_AUTHORIZED);
01394                 eloop_cancel_timeout(ap_handle_timer, hapd, sta);
01395                 eloop_register_timeout(0, 0, ap_handle_timer, hapd, sta);
01396                 sta->timeout_next = STA_REMOVE;
01397         }
01398 }
01399 
01400 
01401 #ifdef HOSTAPD_DUMP_STATE
01402 static void fprint_char(FILE *f, char c)
01403 {
01404         if (c >= 32 && c < 127)
01405                 fprintf(f, "%c", c);
01406         else
01407                 fprintf(f, "<%02x>", c);
01408 }
01409 
01410 
01411 void ieee802_1x_dump_state(FILE *f, const char *prefix, struct sta_info *sta)
01412 {
01413         struct eapol_state_machine *sm = sta->eapol_sm;
01414         if (sm == NULL)
01415                 return;
01416 
01417         fprintf(f, "%sIEEE 802.1X:\n", prefix);
01418 
01419         if (sm->identity) {
01420                 size_t i;
01421                 fprintf(f, "%sidentity=", prefix);
01422                 for (i = 0; i < sm->identity_len; i++)
01423                         fprint_char(f, sm->identity[i]);
01424                 fprintf(f, "\n");
01425         }
01426 
01427         fprintf(f, "%slast EAP type: Authentication Server: %d (%s) "
01428                 "Supplicant: %d (%s)\n", prefix,
01429                 sm->eap_type_authsrv, eap_type_text(sm->eap_type_authsrv),
01430                 sm->eap_type_supp, eap_type_text(sm->eap_type_supp));
01431 
01432         fprintf(f, "%scached_packets=%s\n", prefix,
01433                 sm->last_recv_radius ? "[RX RADIUS]" : "");
01434 
01435         eapol_auth_dump_state(f, prefix, sm);
01436 }
01437 #endif /* HOSTAPD_DUMP_STATE */
01438 
01439 
01440 static int ieee802_1x_rekey_broadcast(struct hostapd_data *hapd)
01441 {
01442         struct eapol_authenticator *eapol = hapd->eapol_auth;
01443 
01444         if (hapd->conf->default_wep_key_len < 1)
01445                 return 0;
01446 
01447         os_free(eapol->default_wep_key);
01448         eapol->default_wep_key = os_malloc(hapd->conf->default_wep_key_len);
01449         if (eapol->default_wep_key == NULL ||
01450             os_get_random(eapol->default_wep_key,
01451                           hapd->conf->default_wep_key_len)) {
01452                 printf("Could not generate random WEP key.\n");
01453                 os_free(eapol->default_wep_key);
01454                 eapol->default_wep_key = NULL;
01455                 return -1;
01456         }
01457 
01458         wpa_hexdump_key(MSG_DEBUG, "IEEE 802.1X: New default WEP key",
01459                         eapol->default_wep_key,
01460                         hapd->conf->default_wep_key_len);
01461 
01462         return 0;
01463 }
01464 
01465 
01466 static int ieee802_1x_sta_key_available(struct hostapd_data *hapd,
01467                                         struct sta_info *sta, void *ctx)
01468 {
01469         if (sta->eapol_sm) {
01470                 sta->eapol_sm->eap_if->eapKeyAvailable = TRUE;
01471                 eapol_auth_step(sta->eapol_sm);
01472         }
01473         return 0;
01474 }
01475 
01476 
01477 static void ieee802_1x_rekey(void *eloop_ctx, void *timeout_ctx)
01478 {
01479         struct hostapd_data *hapd = eloop_ctx;
01480         struct eapol_authenticator *eapol = hapd->eapol_auth;
01481 
01482         if (eapol->default_wep_key_idx >= 3)
01483                 eapol->default_wep_key_idx =
01484                         hapd->conf->individual_wep_key_len > 0 ? 1 : 0;
01485         else
01486                 eapol->default_wep_key_idx++;
01487 
01488         wpa_printf(MSG_DEBUG, "IEEE 802.1X: New default WEP key index %d",
01489                    eapol->default_wep_key_idx);
01490                       
01491         if (ieee802_1x_rekey_broadcast(hapd)) {
01492                 hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE8021X,
01493                                HOSTAPD_LEVEL_WARNING, "failed to generate a "
01494                                "new broadcast key");
01495                 os_free(eapol->default_wep_key);
01496                 eapol->default_wep_key = NULL;
01497                 return;
01498         }
01499 
01500         /* TODO: Could setup key for RX here, but change default TX keyid only
01501          * after new broadcast key has been sent to all stations. */
01502         if (hostapd_set_key(hapd->conf->iface, hapd, WPA_ALG_WEP, NULL,
01503                             eapol->default_wep_key_idx, 1, NULL, 0,
01504                             eapol->default_wep_key,
01505                             hapd->conf->default_wep_key_len)) {
01506                 hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE8021X,
01507                                HOSTAPD_LEVEL_WARNING, "failed to configure a "
01508                                "new broadcast key");
01509                 os_free(eapol->default_wep_key);
01510                 eapol->default_wep_key = NULL;
01511                 return;
01512         }
01513 
01514         ap_for_each_sta(hapd, ieee802_1x_sta_key_available, NULL);
01515 
01516         if (hapd->conf->wep_rekeying_period > 0) {
01517                 eloop_register_timeout(hapd->conf->wep_rekeying_period, 0,
01518                                        ieee802_1x_rekey, hapd, NULL);
01519         }
01520 }
01521 
01522 
01523 static void ieee802_1x_eapol_send(void *ctx, void *sta_ctx, u8 type,
01524                                   const u8 *data, size_t datalen)
01525 {
01526         ieee802_1x_send(ctx, sta_ctx, type, data, datalen);
01527 }
01528 
01529 
01530 static void ieee802_1x_aaa_send(void *ctx, void *sta_ctx,
01531                                 const u8 *data, size_t datalen)
01532 {
01533 #ifndef CONFIG_NO_RADIUS
01534         struct hostapd_data *hapd = ctx;
01535         struct sta_info *sta = sta_ctx;
01536 
01537         ieee802_1x_encapsulate_radius(hapd, sta, data, datalen);
01538 #endif /* CONFIG_NO_RADIUS */
01539 }
01540 
01541 
01542 static void _ieee802_1x_finished(void *ctx, void *sta_ctx, int success,
01543                                  int preauth)
01544 {
01545         struct hostapd_data *hapd = ctx;
01546         struct sta_info *sta = sta_ctx;
01547         if (preauth)
01548                 rsn_preauth_finished(hapd, sta, success);
01549         else
01550                 ieee802_1x_finished(hapd, sta, success);
01551 }
01552 
01553 
01554 static int ieee802_1x_get_eap_user(void *ctx, const u8 *identity,
01555                                    size_t identity_len, int phase2,
01556                                    struct eap_user *user)
01557 {
01558         struct hostapd_data *hapd = ctx;
01559         const struct hostapd_eap_user *eap_user;
01560         int i, count;
01561 
01562         eap_user = hostapd_get_eap_user(hapd->conf, identity,
01563                                         identity_len, phase2);
01564         if (eap_user == NULL)
01565                 return -1;
01566 
01567         os_memset(user, 0, sizeof(*user));
01568         user->phase2 = phase2;
01569         count = EAP_USER_MAX_METHODS;
01570         if (count > EAP_MAX_METHODS)
01571                 count = EAP_MAX_METHODS;
01572         for (i = 0; i < count; i++) {
01573                 user->methods[i].vendor = eap_user->methods[i].vendor;
01574                 user->methods[i].method = eap_user->methods[i].method;
01575         }
01576 
01577         if (eap_user->password) {
01578                 user->password = os_malloc(eap_user->password_len);
01579                 if (user->password == NULL)
01580                         return -1;
01581                 os_memcpy(user->password, eap_user->password,
01582                           eap_user->password_len);
01583                 user->password_len = eap_user->password_len;
01584         }
01585         user->force_version = eap_user->force_version;
01586         user->ttls_auth = eap_user->ttls_auth;
01587 
01588         return 0;
01589 }
01590 
01591 
01592 static int ieee802_1x_sta_entry_alive(void *ctx, const u8 *addr)
01593 {
01594         struct hostapd_data *hapd = ctx;
01595         struct sta_info *sta;
01596         sta = ap_get_sta(hapd, addr);
01597         if (sta == NULL || sta->eapol_sm == NULL)
01598                 return 0;
01599         return 1;
01600 }
01601 
01602 
01603 static void ieee802_1x_logger(void *ctx, const u8 *addr,
01604                               eapol_logger_level level, const char *txt)
01605 {
01606 #ifndef CONFIG_NO_HOSTAPD_LOGGER
01607         struct hostapd_data *hapd = ctx;
01608         int hlevel;
01609 
01610         switch (level) {
01611         case EAPOL_LOGGER_WARNING:
01612                 hlevel = HOSTAPD_LEVEL_WARNING;
01613                 break;
01614         case EAPOL_LOGGER_INFO:
01615                 hlevel = HOSTAPD_LEVEL_INFO;
01616                 break;
01617         case EAPOL_LOGGER_DEBUG:
01618         default:
01619                 hlevel = HOSTAPD_LEVEL_DEBUG;
01620                 break;
01621         }
01622 
01623         hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE8021X, hlevel, "%s",
01624                        txt);
01625 #endif /* CONFIG_NO_HOSTAPD_LOGGER */
01626 }
01627 
01628 
01629 static void ieee802_1x_set_port_authorized(void *ctx, void *sta_ctx,
01630                                            int authorized)
01631 {
01632         struct hostapd_data *hapd = ctx;
01633         struct sta_info *sta = sta_ctx;
01634         ieee802_1x_set_sta_authorized(hapd, sta, authorized);
01635 }
01636 
01637 
01638 static void _ieee802_1x_abort_auth(void *ctx, void *sta_ctx)
01639 {
01640         struct hostapd_data *hapd = ctx;
01641         struct sta_info *sta = sta_ctx;
01642         ieee802_1x_abort_auth(hapd, sta);
01643 }
01644 
01645 
01646 static void _ieee802_1x_tx_key(void *ctx, void *sta_ctx)
01647 {
01648         struct hostapd_data *hapd = ctx;
01649         struct sta_info *sta = sta_ctx;
01650         ieee802_1x_tx_key(hapd, sta);
01651 }
01652 
01653 
01654 int ieee802_1x_init(struct hostapd_data *hapd)
01655 {
01656         int i;
01657         struct eapol_auth_config conf;
01658         struct eapol_auth_cb cb;
01659 
01660         os_memset(&conf, 0, sizeof(conf));
01661         conf.hapd = hapd;
01662         conf.eap_reauth_period = hapd->conf->eap_reauth_period;
01663         conf.wpa = hapd->conf->wpa;
01664         conf.individual_wep_key_len = hapd->conf->individual_wep_key_len;
01665         conf.eap_server = hapd->conf->eap_server;
01666         conf.ssl_ctx = hapd->ssl_ctx;
01667         conf.eap_sim_db_priv = hapd->eap_sim_db_priv;
01668         conf.eap_req_id_text = hapd->conf->eap_req_id_text;
01669         conf.eap_req_id_text_len = hapd->conf->eap_req_id_text_len;
01670         conf.pac_opaque_encr_key = hapd->conf->pac_opaque_encr_key;
01671         conf.eap_fast_a_id = hapd->conf->eap_fast_a_id;
01672         conf.eap_fast_a_id_len = hapd->conf->eap_fast_a_id_len;
01673         conf.eap_fast_a_id_info = hapd->conf->eap_fast_a_id_info;
01674         conf.eap_fast_prov = hapd->conf->eap_fast_prov;
01675         conf.pac_key_lifetime = hapd->conf->pac_key_lifetime;
01676         conf.pac_key_refresh_time = hapd->conf->pac_key_refresh_time;
01677         conf.eap_sim_aka_result_ind = hapd->conf->eap_sim_aka_result_ind;
01678         conf.tnc = hapd->conf->tnc;
01679         conf.wps = hapd->wps;
01680 
01681         os_memset(&cb, 0, sizeof(cb));
01682         cb.eapol_send = ieee802_1x_eapol_send;
01683         cb.aaa_send = ieee802_1x_aaa_send;
01684         cb.finished = _ieee802_1x_finished;
01685         cb.get_eap_user = ieee802_1x_get_eap_user;
01686         cb.sta_entry_alive = ieee802_1x_sta_entry_alive;
01687         cb.logger = ieee802_1x_logger;
01688         cb.set_port_authorized = ieee802_1x_set_port_authorized;
01689         cb.abort_auth = _ieee802_1x_abort_auth;
01690         cb.tx_key = _ieee802_1x_tx_key;
01691 
01692         hapd->eapol_auth = eapol_auth_init(&conf, &cb);
01693         if (hapd->eapol_auth == NULL)
01694                 return -1;
01695 
01696         if ((hapd->conf->ieee802_1x || hapd->conf->wpa) &&
01697             hostapd_set_ieee8021x(hapd->conf->iface, hapd, 1))
01698                 return -1;
01699 
01700 #ifndef CONFIG_NO_RADIUS
01701         if (radius_client_register(hapd->radius, RADIUS_AUTH,
01702                                    ieee802_1x_receive_auth, hapd))
01703                 return -1;
01704 #endif /* CONFIG_NO_RADIUS */
01705 
01706         if (hapd->conf->default_wep_key_len) {
01707                 hostapd_set_privacy(hapd, 1);
01708 
01709                 for (i = 0; i < 4; i++)
01710                         hostapd_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE,
01711                                         NULL, i, 0, NULL, 0, NULL, 0);
01712 
01713                 ieee802_1x_rekey(hapd, NULL);
01714 
01715                 if (hapd->eapol_auth->default_wep_key == NULL)
01716                         return -1;
01717         }
01718 
01719         return 0;
01720 }
01721 
01722 
01723 void ieee802_1x_deinit(struct hostapd_data *hapd)
01724 {
01725         eloop_cancel_timeout(ieee802_1x_rekey, hapd, NULL);
01726 
01727         if (hapd->driver != NULL &&
01728             (hapd->conf->ieee802_1x || hapd->conf->wpa))
01729                 hostapd_set_ieee8021x(hapd->conf->iface, hapd, 0);
01730 
01731         eapol_auth_deinit(hapd->eapol_auth);
01732         hapd->eapol_auth = NULL;
01733 }
01734 
01735 
01736 int ieee802_1x_reconfig(struct hostapd_data *hapd, 
01737                         struct hostapd_config *oldconf,
01738                         struct hostapd_bss_config *oldbss)
01739 {
01740         ieee802_1x_deinit(hapd);
01741         return ieee802_1x_init(hapd);
01742 }
01743 
01744 
01745 int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
01746                          const u8 *buf, size_t len, int ack)
01747 {
01748         struct ieee80211_hdr *hdr;
01749         struct ieee802_1x_hdr *xhdr;
01750         struct ieee802_1x_eapol_key *key;
01751         u8 *pos;
01752         const unsigned char rfc1042_hdr[ETH_ALEN] =
01753                 { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
01754 
01755         if (sta == NULL)
01756                 return -1;
01757         if (len < sizeof(*hdr) + sizeof(rfc1042_hdr) + 2 + sizeof(*xhdr))
01758                 return 0;
01759 
01760         hdr = (struct ieee80211_hdr *) buf;
01761         pos = (u8 *) (hdr + 1);
01762         if (os_memcmp(pos, rfc1042_hdr, sizeof(rfc1042_hdr)) != 0)
01763                 return 0;
01764         pos += sizeof(rfc1042_hdr);
01765         if (WPA_GET_BE16(pos) != ETH_P_PAE)
01766                 return 0;
01767         pos += 2;
01768 
01769         xhdr = (struct ieee802_1x_hdr *) pos;
01770         pos += sizeof(*xhdr);
01771 
01772         wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR " TX status - version=%d "
01773                    "type=%d length=%d - ack=%d",
01774                    MAC2STR(sta->addr), xhdr->version, xhdr->type,
01775                    be_to_host16(xhdr->length), ack);
01776 
01777         /* EAPOL EAP-Packet packets are eventually re-sent by either Supplicant
01778          * or Authenticator state machines, but EAPOL-Key packets are not
01779          * retransmitted in case of failure. Try to re-sent failed EAPOL-Key
01780          * packets couple of times because otherwise STA keys become
01781          * unsynchronized with AP. */
01782         if (xhdr->type == IEEE802_1X_TYPE_EAPOL_KEY && !ack &&
01783             pos + sizeof(*key) <= buf + len) {
01784                 key = (struct ieee802_1x_eapol_key *) pos;
01785                 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
01786                                HOSTAPD_LEVEL_DEBUG, "did not Ack EAPOL-Key "
01787                                "frame (%scast index=%d)",
01788                                key->key_index & BIT(7) ? "uni" : "broad",
01789                                key->key_index & ~BIT(7));
01790                 /* TODO: re-send EAPOL-Key couple of times (with short delay
01791                  * between them?). If all attempt fail, report error and
01792                  * deauthenticate STA so that it will get new keys when
01793                  * authenticating again (e.g., after returning in range).
01794                  * Separate limit/transmit state needed both for unicast and
01795                  * broadcast keys(?) */
01796         }
01797         /* TODO: could move unicast key configuration from ieee802_1x_tx_key()
01798          * to here and change the key only if the EAPOL-Key packet was Acked.
01799          */
01800 
01801         return 1;
01802 }
01803 
01804 
01805 u8 * ieee802_1x_get_identity(struct eapol_state_machine *sm, size_t *len)
01806 {
01807         if (sm == NULL || sm->identity == NULL)
01808                 return NULL;
01809 
01810         *len = sm->identity_len;
01811         return sm->identity;
01812 }
01813 
01814 
01815 u8 * ieee802_1x_get_radius_class(struct eapol_state_machine *sm, size_t *len,
01816                                  int idx)
01817 {
01818         if (sm == NULL || sm->radius_class.attr == NULL ||
01819             idx >= (int) sm->radius_class.count)
01820                 return NULL;
01821 
01822         *len = sm->radius_class.attr[idx].len;
01823         return sm->radius_class.attr[idx].data;
01824 }
01825 
01826 
01827 const u8 * ieee802_1x_get_key(struct eapol_state_machine *sm, size_t *len)
01828 {
01829         if (sm == NULL)
01830                 return NULL;
01831 
01832         *len = sm->eap_if->eapKeyDataLen;
01833         return sm->eap_if->eapKeyData;
01834 }
01835 
01836 
01837 void ieee802_1x_notify_port_enabled(struct eapol_state_machine *sm,
01838                                     int enabled)
01839 {
01840         if (sm == NULL)
01841                 return;
01842         sm->eap_if->portEnabled = enabled ? TRUE : FALSE;
01843         eapol_auth_step(sm);
01844 }
01845 
01846 
01847 void ieee802_1x_notify_port_valid(struct eapol_state_machine *sm,
01848                                   int valid)
01849 {
01850         if (sm == NULL)
01851                 return;
01852         sm->portValid = valid ? TRUE : FALSE;
01853         eapol_auth_step(sm);
01854 }
01855 
01856 
01857 void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, int pre_auth)
01858 {
01859         if (sm == NULL)
01860                 return;
01861         if (pre_auth)
01862                 sm->flags |= EAPOL_SM_PREAUTH;
01863         else
01864                 sm->flags &= ~EAPOL_SM_PREAUTH;
01865 }
01866 
01867 
01868 static const char * bool_txt(Boolean bool)
01869 {
01870         return bool ? "TRUE" : "FALSE";
01871 }
01872 
01873 
01874 int ieee802_1x_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen)
01875 {
01876         /* TODO */
01877         return 0;
01878 }
01879 
01880 
01881 int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
01882                            char *buf, size_t buflen)
01883 {
01884         int len = 0, ret;
01885         struct eapol_state_machine *sm = sta->eapol_sm;
01886 
01887         if (sm == NULL)
01888                 return 0;
01889 
01890         ret = os_snprintf(buf + len, buflen - len,
01891                           "dot1xPaePortNumber=%d\n"
01892                           "dot1xPaePortProtocolVersion=%d\n"
01893                           "dot1xPaePortCapabilities=1\n"
01894                           "dot1xPaePortInitialize=%d\n"
01895                           "dot1xPaePortReauthenticate=FALSE\n",
01896                           sta->aid,
01897                           EAPOL_VERSION,
01898                           sm->initialize);
01899         if (ret < 0 || (size_t) ret >= buflen - len)
01900                 return len;
01901         len += ret;
01902 
01903         /* dot1xAuthConfigTable */
01904         ret = os_snprintf(buf + len, buflen - len,
01905                           "dot1xAuthPaeState=%d\n"
01906                           "dot1xAuthBackendAuthState=%d\n"
01907                           "dot1xAuthAdminControlledDirections=%d\n"
01908                           "dot1xAuthOperControlledDirections=%d\n"
01909                           "dot1xAuthAuthControlledPortStatus=%d\n"
01910                           "dot1xAuthAuthControlledPortControl=%d\n"
01911                           "dot1xAuthQuietPeriod=%u\n"
01912                           "dot1xAuthServerTimeout=%u\n"
01913                           "dot1xAuthReAuthPeriod=%u\n"
01914                           "dot1xAuthReAuthEnabled=%s\n"
01915                           "dot1xAuthKeyTxEnabled=%s\n",
01916                           sm->auth_pae_state + 1,
01917                           sm->be_auth_state + 1,
01918                           sm->adminControlledDirections,
01919                           sm->operControlledDirections,
01920                           sm->authPortStatus,
01921                           sm->portControl,
01922                           sm->quietPeriod,
01923                           sm->serverTimeout,
01924                           sm->reAuthPeriod,
01925                           bool_txt(sm->reAuthEnabled),
01926                           bool_txt(sm->keyTxEnabled));
01927         if (ret < 0 || (size_t) ret >= buflen - len)
01928                 return len;
01929         len += ret;
01930 
01931         /* dot1xAuthStatsTable */
01932         ret = os_snprintf(buf + len, buflen - len,
01933                           "dot1xAuthEapolFramesRx=%u\n"
01934                           "dot1xAuthEapolFramesTx=%u\n"
01935                           "dot1xAuthEapolStartFramesRx=%u\n"
01936                           "dot1xAuthEapolLogoffFramesRx=%u\n"
01937                           "dot1xAuthEapolRespIdFramesRx=%u\n"
01938                           "dot1xAuthEapolRespFramesRx=%u\n"
01939                           "dot1xAuthEapolReqIdFramesTx=%u\n"
01940                           "dot1xAuthEapolReqFramesTx=%u\n"
01941                           "dot1xAuthInvalidEapolFramesRx=%u\n"
01942                           "dot1xAuthEapLengthErrorFramesRx=%u\n"
01943                           "dot1xAuthLastEapolFrameVersion=%u\n"
01944                           "dot1xAuthLastEapolFrameSource=" MACSTR "\n",
01945                           sm->dot1xAuthEapolFramesRx,
01946                           sm->dot1xAuthEapolFramesTx,
01947                           sm->dot1xAuthEapolStartFramesRx,
01948                           sm->dot1xAuthEapolLogoffFramesRx,
01949                           sm->dot1xAuthEapolRespIdFramesRx,
01950                           sm->dot1xAuthEapolRespFramesRx,
01951                           sm->dot1xAuthEapolReqIdFramesTx,
01952                           sm->dot1xAuthEapolReqFramesTx,
01953                           sm->dot1xAuthInvalidEapolFramesRx,
01954                           sm->dot1xAuthEapLengthErrorFramesRx,
01955                           sm->dot1xAuthLastEapolFrameVersion,
01956                           MAC2STR(sm->addr));
01957         if (ret < 0 || (size_t) ret >= buflen - len)
01958                 return len;
01959         len += ret;
01960 
01961         /* dot1xAuthDiagTable */
01962         ret = os_snprintf(buf + len, buflen - len,
01963                           "dot1xAuthEntersConnecting=%u\n"
01964                           "dot1xAuthEapLogoffsWhileConnecting=%u\n"
01965                           "dot1xAuthEntersAuthenticating=%u\n"
01966                           "dot1xAuthAuthSuccessesWhileAuthenticating=%u\n"
01967                           "dot1xAuthAuthTimeoutsWhileAuthenticating=%u\n"
01968                           "dot1xAuthAuthFailWhileAuthenticating=%u\n"
01969                           "dot1xAuthAuthEapStartsWhileAuthenticating=%u\n"
01970                           "dot1xAuthAuthEapLogoffWhileAuthenticating=%u\n"
01971                           "dot1xAuthAuthReauthsWhileAuthenticated=%u\n"
01972                           "dot1xAuthAuthEapStartsWhileAuthenticated=%u\n"
01973                           "dot1xAuthAuthEapLogoffWhileAuthenticated=%u\n"
01974                           "dot1xAuthBackendResponses=%u\n"
01975                           "dot1xAuthBackendAccessChallenges=%u\n"
01976                           "dot1xAuthBackendOtherRequestsToSupplicant=%u\n"
01977                           "dot1xAuthBackendAuthSuccesses=%u\n"
01978                           "dot1xAuthBackendAuthFails=%u\n",
01979                           sm->authEntersConnecting,
01980                           sm->authEapLogoffsWhileConnecting,
01981                           sm->authEntersAuthenticating,
01982                           sm->authAuthSuccessesWhileAuthenticating,
01983                           sm->authAuthTimeoutsWhileAuthenticating,
01984                           sm->authAuthFailWhileAuthenticating,
01985                           sm->authAuthEapStartsWhileAuthenticating,
01986                           sm->authAuthEapLogoffWhileAuthenticating,
01987                           sm->authAuthReauthsWhileAuthenticated,
01988                           sm->authAuthEapStartsWhileAuthenticated,
01989                           sm->authAuthEapLogoffWhileAuthenticated,
01990                           sm->backendResponses,
01991                           sm->backendAccessChallenges,
01992                           sm->backendOtherRequestsToSupplicant,
01993                           sm->backendAuthSuccesses,
01994                           sm->backendAuthFails);
01995         if (ret < 0 || (size_t) ret >= buflen - len)
01996                 return len;
01997         len += ret;
01998 
01999         /* dot1xAuthSessionStatsTable */
02000         ret = os_snprintf(buf + len, buflen - len,
02001                           /* TODO: dot1xAuthSessionOctetsRx */
02002                           /* TODO: dot1xAuthSessionOctetsTx */
02003                           /* TODO: dot1xAuthSessionFramesRx */
02004                           /* TODO: dot1xAuthSessionFramesTx */
02005                           "dot1xAuthSessionId=%08X-%08X\n"
02006                           "dot1xAuthSessionAuthenticMethod=%d\n"
02007                           "dot1xAuthSessionTime=%u\n"
02008                           "dot1xAuthSessionTerminateCause=999\n"
02009                           "dot1xAuthSessionUserName=%s\n",
02010                           sta->acct_session_id_hi, sta->acct_session_id_lo,
02011                           (wpa_key_mgmt_wpa_ieee8021x(
02012                                    wpa_auth_sta_key_mgmt(sta->wpa_sm))) ?
02013                           1 : 2,
02014                           (unsigned int) (time(NULL) -
02015                                           sta->acct_session_start),
02016                           sm->identity);
02017         if (ret < 0 || (size_t) ret >= buflen - len)
02018                 return len;
02019         len += ret;
02020 
02021         return len;
02022 }
02023 
02024 
02025 static void ieee802_1x_finished(struct hostapd_data *hapd,
02026                                 struct sta_info *sta, int success)
02027 {
02028         const u8 *key;
02029         size_t len;
02030         /* TODO: get PMKLifetime from WPA parameters */
02031         static const int dot11RSNAConfigPMKLifetime = 43200;
02032 
02033         key = ieee802_1x_get_key(sta->eapol_sm, &len);
02034         if (success && key && len >= PMK_LEN &&
02035             wpa_auth_pmksa_add(sta->wpa_sm, key, dot11RSNAConfigPMKLifetime,
02036                                sta->eapol_sm) == 0) {
02037                 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,
02038                                HOSTAPD_LEVEL_DEBUG,
02039                                "Added PMKSA cache entry (IEEE 802.1X)");
02040         }
02041 }
02042 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines

Generated on Sat Nov 21 23:16:48 2009 for hostapd by  doxygen 1.6.1