From: Michal Kazior <michal@xxxxxxxxx> This allows identifying which passphrase a station used to connect. When station connects a new event is emitted after AP-STA-CONNECTED: wlan0: AP-STA-CONNECTED 00:36:76:21:dc:7b wlan0: AP-STA-CONNECTED-PMK 00:36:76:21:dc:7b 51ff78eb647fb7bafd9cd09a49dd264010d2cfe7b88ab8f107ecb06549e8f8d3 It's also possible to retrieve it through cli: $ hostapd_cli all_sta Selected interface 'ap0' 00:36:76:21:dc:7b ... hostapdWPAPMK=51ff78eb647fb7bafd9cd09a49dd264010d2cfe7b88ab8f107ecb06549e8f8d3 The PMK can be already generated easily with wpa_passphrase tool: $ wpa_passphrase ssid secretpassword network={ ssid="ssid" #psk="secretpassword" psk=6ef4903f55512d167e4f1df7e16856563a99c7a4df299d6e877b3f5b9887c3dc } This isn't interesting on its own but can be useful, e.g. to firewall clients based on passphrases. Signed-off-by: Michal Kazior <michal@xxxxxxxxx> --- src/ap/sta_info.c | 28 ++++++++++++++++++++++++++++ src/ap/wpa_auth.c | 18 ++++++++++++++++++ src/ap/wpa_auth.h | 1 + src/ap/wpa_auth_ft.c | 2 ++ src/common/wpa_ctrl.h | 1 + 5 files changed, 50 insertions(+) diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c index 179cf43b6..99e045e3f 100644 --- a/src/ap/sta_info.c +++ b/src/ap/sta_info.c @@ -1165,6 +1165,33 @@ void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta) #endif /* CONFIG_IEEE80211W */ +static void ap_sta_wpa_msg_pmk(struct hostapd_data *hapd, + struct sta_info *sta) +{ + const u8 *pmk; + char *hex; + int pmk_len; + int hex_len; + + pmk = wpa_auth_get_pmk(sta->wpa_sm, &pmk_len); + if (!pmk) + return; + hex_len = pmk_len * 2 + 1; + hex = os_malloc(hex_len); + if (!hex) + return; + + wpa_snprintf_hex(hex, hex_len, pmk, pmk_len); + wpa_msg((hapd->msg_ctx_parent && + hapd->msg_ctx_parent != hapd->msg_ctx) + ? hapd->msg_ctx_parent + : hapd->msg_ctx, + MSG_INFO, AP_STA_CONNECTED_PWD MACSTR " %s", + MAC2STR(sta->addr), hex); + os_free(hex); +} + + void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta, int authorized) { @@ -1222,6 +1249,7 @@ void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta, wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO, AP_STA_CONNECTED "%s%s", buf, ip_addr); + ap_sta_wpa_msg_pmk(hapd, sta); } else { wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED "%s", buf); diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 34969e79e..bdef1edfe 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -860,6 +860,8 @@ static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data, if (wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK, data, data_len) == 0) { + os_memcpy(sm->PMK, pmk, pmk_len); + sm->pmk_len = pmk_len; ok = 1; break; } @@ -2675,6 +2677,8 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK, sm->last_rx_eapol_key, sm->last_rx_eapol_key_len) == 0) { + os_memcpy(sm->PMK, pmk, pmk_len); + sm->pmk_len = pmk_len; ok = 1; break; } @@ -3940,6 +3944,13 @@ int wpa_get_mib_sta(struct wpa_state_machine *sm, char *buf, size_t buflen) return len; len += ret; + if (sm->pmk_len) { + len += os_snprintf(buf + len, buflen - len, "hostapdWPAPMK="); + len += wpa_snprintf_hex(buf + len, buflen - len, + sm->PMK, sm->pmk_len); + len += os_snprintf(buf + len, buflen - len, "\n"); + } + return len; } @@ -3963,6 +3974,13 @@ int wpa_auth_get_pairwise(struct wpa_state_machine *sm) } +const u8 *wpa_auth_get_pmk(struct wpa_state_machine *sm, int *len) +{ + *len = sm->pmk_len; + return sm->PMK; +} + + int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm) { if (sm == NULL) diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index fad5536f7..7e82068e3 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -339,6 +339,7 @@ int wpa_get_mib_sta(struct wpa_state_machine *sm, char *buf, size_t buflen); void wpa_auth_countermeasures_start(struct wpa_authenticator *wpa_auth); int wpa_auth_pairwise_set(struct wpa_state_machine *sm); int wpa_auth_get_pairwise(struct wpa_state_machine *sm); +const u8 *wpa_auth_get_pmk(struct wpa_state_machine *sm, int *len); int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm); int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm); int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm); diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index e8d46ab0d..391fe465a 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -2596,6 +2596,8 @@ static int wpa_ft_psk_pmk_r1(struct wpa_state_machine *sm, os_memcpy(out_pmk_r1, pmk_r1, PMK_LEN); if (out_pairwise) *out_pairwise = pairwise; + os_memcpy(sm->PMK, pmk, PMK_LEN); + sm->pmk_len = PMK_LEN; if (out_vlan && wpa_ft_get_vlan(sm->wpa_auth, sm->addr, out_vlan) < 0) { wpa_printf(MSG_DEBUG, "FT: vlan not available for STA " diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h index f65077e04..73ad24402 100644 --- a/src/common/wpa_ctrl.h +++ b/src/common/wpa_ctrl.h @@ -297,6 +297,7 @@ extern "C" { #define WPS_EVENT_AP_PIN_ENABLED "WPS-AP-PIN-ENABLED " #define WPS_EVENT_AP_PIN_DISABLED "WPS-AP-PIN-DISABLED " #define AP_STA_CONNECTED "AP-STA-CONNECTED " +#define AP_STA_CONNECTED_PWD "AP-STA-CONNECTED-PWD " #define AP_STA_DISCONNECTED "AP-STA-DISCONNECTED " #define AP_STA_POSSIBLE_PSK_MISMATCH "AP-STA-POSSIBLE-PSK-MISMATCH " #define AP_STA_POLL_OK "AP-STA-POLL-OK " -- 2.19.1 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap