From fd7895c8ddcea473b398cad289b9f26e9612fc48 Mon Sep 17 00:00:00 2001 From: Sam Leffler Date: Mon, 13 Jun 2005 17:00:32 +0000 Subject: [PATCH] stripped down import of hostapd 0.3.9 Approved by: re (dwhite) --- contrib/hostapd/ChangeLog | 14 +++++++++++ contrib/hostapd/Makefile | 2 +- contrib/hostapd/common.h | 4 ++++ contrib/hostapd/config.c | 3 ++- contrib/hostapd/ctrl_iface.c | 4 +++- contrib/hostapd/eapol_sm.c | 20 +++++++++++----- contrib/hostapd/eapol_sm.h | 2 ++ contrib/hostapd/ieee802_1x.c | 42 +++++++++++++++++++++++++++++---- contrib/hostapd/ieee802_1x.h | 2 ++ contrib/hostapd/ms_funcs.c | 4 +++- contrib/hostapd/radius_client.c | 2 +- contrib/hostapd/radius_server.c | 12 ++++++++++ contrib/hostapd/tls_openssl.c | 9 ++++--- contrib/hostapd/version.h | 2 +- contrib/hostapd/wpa.c | 22 +++++++---------- 15 files changed, 110 insertions(+), 34 deletions(-) diff --git a/contrib/hostapd/ChangeLog b/contrib/hostapd/ChangeLog index e4b73ec7e6e7..9d15f75b2ef6 100644 --- a/contrib/hostapd/ChangeLog +++ b/contrib/hostapd/ChangeLog @@ -1,5 +1,19 @@ ChangeLog for hostapd +2005-06-10 - v0.3.9 + * fixed a bug which caused some RSN pre-authentication cases to use + freed memory and potentially crash hostapd + * fixed private key loading for cases where passphrase is not set + * fixed WPA2 to add PMKSA cache entry when using integrated EAP + authenticator + * driver_madwifi: fixed pairwise key removal to allow WPA reauth + without disassociation + * fixed RADIUS attribute Class processing to only use Access-Accept + packets to update Class; previously, other RADIUS authentication + packets could have cleared Class attribute + * fixed PMKSA caching (EAP authentication was not skipped correctly + with the new state machine changes from IEEE 802.1X draft) + 2005-02-12 - v0.3.7 (beginning of 0.3.x stable releases) 2005-01-23 - v0.3.5 diff --git a/contrib/hostapd/Makefile b/contrib/hostapd/Makefile index 4c9c49edea8c..0ea99c923359 100644 --- a/contrib/hostapd/Makefile +++ b/contrib/hostapd/Makefile @@ -228,6 +228,6 @@ hostapd_cli: hostapd_cli.o hostapd_ctrl.o $(CC) -o hostapd_cli hostapd_cli.o hostapd_ctrl.o clean: - rm -f core *~ *.o hostapd *.d driver_conf.c + rm -f core *~ *.o hostapd hostapd_cli *.d driver_conf.c -include $(OBJS:%.o=%.d) diff --git a/contrib/hostapd/common.h b/contrib/hostapd/common.h index aa6429c76b96..0f154e901bff 100644 --- a/contrib/hostapd/common.h +++ b/contrib/hostapd/common.h @@ -8,8 +8,12 @@ #ifdef __FreeBSD__ #include #include +#define __BYTE_ORDER _BYTE_ORDER +#define __LITTLE_ENDIAN _LITTLE_ENDIAN +#define __BIG_ENDIAN _BIG_ENDIAN #define bswap_16 bswap16 #define bswap_32 bswap32 +#define bswap_64 bswap64 #endif #ifdef CONFIG_NATIVE_WINDOWS diff --git a/contrib/hostapd/config.c b/contrib/hostapd/config.c index ede009aef925..02ecd7966cdd 100644 --- a/contrib/hostapd/config.c +++ b/contrib/hostapd/config.c @@ -597,7 +597,8 @@ static int hostapd_config_check(struct hostapd_config *conf) } if (conf->wpa && (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) && - conf->wpa_psk == NULL && conf->wpa_passphrase == NULL) { + conf->wpa_psk == NULL && conf->wpa_passphrase == NULL && + conf->wpa_psk_file == NULL) { printf("WPA-PSK enabled, but PSK or passphrase is not " "configured.\n"); return -1; diff --git a/contrib/hostapd/ctrl_iface.c b/contrib/hostapd/ctrl_iface.c index 8cf356cb460f..9ed109bd5814 100644 --- a/contrib/hostapd/ctrl_iface.c +++ b/contrib/hostapd/ctrl_iface.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -383,7 +384,8 @@ void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd) unlink(fname); free(fname); - if (rmdir(hapd->conf->ctrl_interface) < 0) { + if (hapd->conf->ctrl_interface && + rmdir(hapd->conf->ctrl_interface) < 0) { if (errno == ENOTEMPTY) { wpa_printf(MSG_DEBUG, "Control interface " "directory not empty - leaving it " diff --git a/contrib/hostapd/eapol_sm.c b/contrib/hostapd/eapol_sm.c index fce7c6d3391a..fe710a6304a0 100644 --- a/contrib/hostapd/eapol_sm.c +++ b/contrib/hostapd/eapol_sm.c @@ -124,6 +124,8 @@ SM_STATE(AUTH_PAE, DISCONNECTED) if (!from_initialize) { if (sm->flags & EAPOL_SM_PREAUTH) rsn_preauth_finished(sm->hapd, sm->sta, 0); + else + ieee802_1x_finished(sm->hapd, sm->sta, 0); } } @@ -174,6 +176,8 @@ SM_STATE(AUTH_PAE, HELD) HOSTAPD_LEVEL_WARNING, "authentication failed"); if (sm->flags & EAPOL_SM_PREAUTH) rsn_preauth_finished(sm->hapd, sm->sta, 0); + else + ieee802_1x_finished(sm->hapd, sm->sta, 0); } @@ -191,6 +195,8 @@ SM_STATE(AUTH_PAE, AUTHENTICATED) HOSTAPD_LEVEL_INFO, "authenticated"); if (sm->flags & EAPOL_SM_PREAUTH) rsn_preauth_finished(sm->hapd, sm->sta, 1); + else + ieee802_1x_finished(sm->hapd, sm->sta, 1); } @@ -759,22 +765,22 @@ restart: prev_ctrl_dir = sm->ctrl_dir.state; SM_STEP_RUN(AUTH_PAE); - if (!eapol_sm_sta_entry_alive(hapd, addr)) + if (!sm->initializing && !eapol_sm_sta_entry_alive(hapd, addr)) break; SM_STEP_RUN(BE_AUTH); - if (!eapol_sm_sta_entry_alive(hapd, addr)) + if (!sm->initializing && !eapol_sm_sta_entry_alive(hapd, addr)) break; SM_STEP_RUN(REAUTH_TIMER); - if (!eapol_sm_sta_entry_alive(hapd, addr)) + if (!sm->initializing && !eapol_sm_sta_entry_alive(hapd, addr)) break; SM_STEP_RUN(AUTH_KEY_TX); - if (!eapol_sm_sta_entry_alive(hapd, addr)) + if (!sm->initializing && !eapol_sm_sta_entry_alive(hapd, addr)) break; SM_STEP_RUN(KEY_RX); - if (!eapol_sm_sta_entry_alive(hapd, addr)) + if (!sm->initializing && !eapol_sm_sta_entry_alive(hapd, addr)) break; SM_STEP_RUN(CTRL_DIR); - if (!eapol_sm_sta_entry_alive(hapd, addr)) + if (!sm->initializing && !eapol_sm_sta_entry_alive(hapd, addr)) break; } while (prev_auth_pae != sm->auth_pae.state || prev_be_auth != sm->be_auth.state || @@ -795,12 +801,14 @@ restart: void eapol_sm_initialize(struct eapol_state_machine *sm) { + sm->initializing = TRUE; /* Initialize the state machines by asserting initialize and then * deasserting it after one step */ sm->initialize = TRUE; eapol_sm_step(sm); sm->initialize = FALSE; eapol_sm_step(sm); + sm->initializing = FALSE; /* Start one second tick for port timers state machine */ eloop_cancel_timeout(eapol_port_timers_tick, sm->hapd, sm); diff --git a/contrib/hostapd/eapol_sm.h b/contrib/hostapd/eapol_sm.h index 7b74ed1c607a..c89dd021473f 100644 --- a/contrib/hostapd/eapol_sm.h +++ b/contrib/hostapd/eapol_sm.h @@ -195,6 +195,8 @@ struct eapol_state_machine { */ u8 currentId; + Boolean initializing; /* in process of initializing state machines */ + /* Somewhat nasty pointers to global hostapd and STA data to avoid * passing these to every function */ struct hostapd_data *hapd; diff --git a/contrib/hostapd/ieee802_1x.c b/contrib/hostapd/ieee802_1x.c index 870d52ab5cac..7f3fe0c56fe2 100644 --- a/contrib/hostapd/ieee802_1x.c +++ b/contrib/hostapd/ieee802_1x.c @@ -755,7 +755,6 @@ void ieee802_1x_receive(hostapd *hapd, u8 *sa, u8 *buf, size_t len) sta->eapol_sm->auth_pae.eapolStart = TRUE; sta->eapol_sm->dot1xAuthEapolStartFramesRx++; wpa_sm_event(hapd, sta, WPA_REAUTH_EAPOL); - eapol_sm_step(sta->eapol_sm); break; case IEEE802_1X_TYPE_EAPOL_LOGOFF: @@ -766,7 +765,6 @@ void ieee802_1x_receive(hostapd *hapd, u8 *sa, u8 *buf, size_t len) RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; sta->eapol_sm->auth_pae.eapolLogoff = TRUE; sta->eapol_sm->dot1xAuthEapolLogoffFramesRx++; - eapol_sm_step(sta->eapol_sm); break; case IEEE802_1X_TYPE_EAPOL_KEY: @@ -809,8 +807,27 @@ void ieee802_1x_new_station(hostapd *hapd, struct sta_info *sta) hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, HOSTAPD_LEVEL_DEBUG, "start authentication"); sta->eapol_sm = eapol_sm_alloc(hapd, sta); - if (sta->eapol_sm) - sta->eapol_sm->portEnabled = TRUE; + if (sta->eapol_sm == NULL) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, + HOSTAPD_LEVEL_INFO, "failed to allocate " + "state machine"); + return; + } + + sta->eapol_sm->portEnabled = TRUE; + + if (sta->pmksa) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, + HOSTAPD_LEVEL_DEBUG, + "PMK from PMKSA cache - skip IEEE 802.1X/EAP"); + /* Setup EAPOL state machines to already authenticated state + * because of existing PMKSA information in the cache. */ + sta->eapol_sm->keyRun = TRUE; + sta->eapol_sm->keyAvailable = TRUE; + sta->eapol_sm->auth_pae.state = AUTH_PAE_AUTHENTICATING; + sta->eapol_sm->be_auth.state = BE_AUTH_SUCCESS; + sta->eapol_sm->authSuccess = TRUE; + } } @@ -1136,6 +1153,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req, session_timeout_set ? session_timeout : -1); } + ieee802_1x_store_radius_class(hapd, sta, msg); break; case RADIUS_CODE_ACCESS_REJECT: sm->eapFail = TRUE; @@ -1159,7 +1177,6 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req, break; } - ieee802_1x_store_radius_class(hapd, sta, msg); ieee802_1x_decapsulate_radius(hapd, sta); if (override_eapReq) sm->be_auth.eapReq = FALSE; @@ -1647,3 +1664,18 @@ int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta, return len; } + + +void ieee802_1x_finished(struct hostapd_data *hapd, struct sta_info *sta, + int success) +{ + u8 *key; + size_t len; + /* TODO: get PMKLifetime from WPA parameters */ + static const int dot11RSNAConfigPMKLifetime = 43200; + + key = ieee802_1x_get_key_crypt(sta->eapol_sm, &len); + if (success && key) { + pmksa_cache_add(hapd, sta, key, dot11RSNAConfigPMKLifetime); + } +} diff --git a/contrib/hostapd/ieee802_1x.h b/contrib/hostapd/ieee802_1x.h index 3916138c0b41..c52d7bb64333 100644 --- a/contrib/hostapd/ieee802_1x.h +++ b/contrib/hostapd/ieee802_1x.h @@ -80,5 +80,7 @@ int ieee802_1x_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen); int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta, char *buf, size_t buflen); void hostapd_get_ntp_timestamp(u8 *buf); +void ieee802_1x_finished(struct hostapd_data *hapd, struct sta_info *sta, + int success); #endif /* IEEE802_1X_H */ diff --git a/contrib/hostapd/ms_funcs.c b/contrib/hostapd/ms_funcs.c index 9c50185ca1d9..590b58949d74 100644 --- a/contrib/hostapd/ms_funcs.c +++ b/contrib/hostapd/ms_funcs.c @@ -158,12 +158,14 @@ void get_master_key(const u8 *password_hash_hash, const u8 *nt_response, }; const unsigned char *addr[3]; const size_t len[3] = { 16, 24, sizeof(magic1) }; + u8 hash[SHA1_MAC_LEN]; addr[0] = password_hash_hash; addr[1] = nt_response; addr[2] = magic1; - sha1_vector(3, addr, len, master_key); + sha1_vector(3, addr, len, hash); + memcpy(master_key, hash, 16); } diff --git a/contrib/hostapd/radius_client.c b/contrib/hostapd/radius_client.c index e17377549168..dc69ca927397 100644 --- a/contrib/hostapd/radius_client.c +++ b/contrib/hostapd/radius_client.c @@ -506,7 +506,7 @@ static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx) rconf = hapd->conf->auth_server; } - len = recv(sock, buf, sizeof(buf), 0); + len = recv(sock, buf, sizeof(buf), MSG_DONTWAIT); if (len < 0) { perror("recv[RADIUS]"); return; diff --git a/contrib/hostapd/radius_server.c b/contrib/hostapd/radius_server.c index bfc784f4759a..d62648f896b1 100644 --- a/contrib/hostapd/radius_server.c +++ b/contrib/hostapd/radius_server.c @@ -325,6 +325,7 @@ static int radius_server_reject(struct radius_server_data *data, { struct radius_msg *msg; int ret = 0; + struct eap_hdr eapfail; RADIUS_DEBUG("Reject invalid request from %s:%d", inet_ntoa(from->sin_addr), ntohs(from->sin_port)); @@ -335,6 +336,16 @@ static int radius_server_reject(struct radius_server_data *data, return -1; } + memset(&eapfail, 0, sizeof(eapfail)); + eapfail.code = EAP_CODE_FAILURE; + eapfail.identifier = 0; + eapfail.length = htons(sizeof(eapfail)); + + if (!radius_msg_add_eap(msg, (u8 *) &eapfail, sizeof(eapfail))) { + RADIUS_DEBUG("Failed to add EAP-Message attribute"); + } + + if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret, client->shared_secret_len, request->hdr->authenticator) < 0) { @@ -395,6 +406,7 @@ static int radius_server_request(struct radius_server_data *data, sess = radius_server_get_new_session(data, client, msg); if (sess == NULL) { RADIUS_DEBUG("Could not create a new session"); + radius_server_reject(data, client, msg, from); return -1; } } diff --git a/contrib/hostapd/tls_openssl.c b/contrib/hostapd/tls_openssl.c index 097b1c876e34..4e6ea539209f 100644 --- a/contrib/hostapd/tls_openssl.c +++ b/contrib/hostapd/tls_openssl.c @@ -489,9 +489,12 @@ int tls_global_private_key(void *_ssl_ctx, const char *private_key, if (private_key == NULL) return 0; - passwd = strdup(private_key_passwd); - if (passwd == NULL) - return -1; + if (private_key_passwd) { + passwd = strdup(private_key_passwd); + if (passwd == NULL) + return -1; + } else + passwd = NULL; SSL_CTX_set_default_passwd_cb(ssl_ctx, tls_passwd_cb); SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, passwd); diff --git a/contrib/hostapd/version.h b/contrib/hostapd/version.h index 074fd52bfba9..b030f34b94f9 100644 --- a/contrib/hostapd/version.h +++ b/contrib/hostapd/version.h @@ -1,6 +1,6 @@ #ifndef VERSION_H #define VERSION_H -#define VERSION_STR "0.3.7" +#define VERSION_STR "0.3.9" #endif /* VERSION_H */ diff --git a/contrib/hostapd/wpa.c b/contrib/hostapd/wpa.c index 8beab8deaadc..b0e42c23bf26 100644 --- a/contrib/hostapd/wpa.c +++ b/contrib/hostapd/wpa.c @@ -1414,6 +1414,14 @@ void wpa_receive(struct hostapd_data *hapd, struct sta_info *sta, key = (struct wpa_eapol_key *) (hdr + 1); key_info = ntohs(key->key_info); key_data_length = ntohs(key->key_data_length); + if (key_data_length > data_len - sizeof(*hdr) - sizeof(*key)) { + wpa_printf(MSG_INFO, "WPA: Invalid EAPOL-Key frame - " + "key_data overflow (%d > %lu)", + key_data_length, + (unsigned long) (data_len - sizeof(*hdr) - + sizeof(*key))); + return; + } /* FIX: verify that the EAPOL-Key frame was encrypted if pairwise keys * are set */ @@ -1945,20 +1953,6 @@ void wpa_sm_event(struct hostapd_data *hapd, struct sta_info *sta, break; } - if ((event == WPA_ASSOC || event == WPA_REAUTH) && - sta->eapol_sm && sta->pmksa) { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, - HOSTAPD_LEVEL_DEBUG, - "PMK from PMKSA cache - skip IEEE 802.1X/EAP"); - /* Setup EAPOL state machines to already authenticated state - * because of existing PMKSA information in the cache. */ - sta->eapol_sm->keyRun = TRUE; - sta->eapol_sm->keyAvailable = TRUE; - sta->eapol_sm->auth_pae.state = AUTH_PAE_AUTHENTICATING; - sta->eapol_sm->be_auth.state = BE_AUTH_SUCCESS; - sta->eapol_sm->authSuccess = TRUE; - } - sm->PTK_valid = FALSE; memset(&sm->PTK, 0, sizeof(sm->PTK));