From: Michal Kazior <michal@xxxxxxxxx> It is now possible to optionally specify keyid for each wpa_psk_file entry: keyid=something 00:00:00:00:00:00 secretpassphrase When station connects and the passphrase it used has an associated keyid it will be appended to the AP-STA-CONNECTED event string: wlan0: AP-STA-CONNECTED 00:36:76:21:dc:7b keyid=something It's also possible to retrieve it through cli: $ hostapd_cli all_sta Selected interface 'ap0' 00:36:76:21:dc:7b ... keyid=something New hostap is able to read old wpa_psk_file. However old hostap will not be able to read new wpa_psk_file if it includes keyids. Signed-off-by: Michal Kazior <michal@xxxxxxxxx> --- Notes: v1: - add keyid=xx parsing to wpa_psk_file - use keyid instead of PMK - re-use AP-STA-CONNECTED event by appending keyid=xx (similar to p2p's ip_addr=) instead of introducing a new event string - split out the pmk part to a separate patch since it's independentaly re-usable by this patch and the reload_wpa_psk patch src/ap/ap_config.c | 49 +++++++++++++++++++++++++++++++++++++----- src/ap/ap_config.h | 2 ++ src/ap/ctrl_iface_ap.c | 5 +++++ src/ap/sta_info.c | 45 ++++++++++++++++++++++++++++++++++---- src/ap/sta_info.h | 2 ++ 5 files changed, 94 insertions(+), 9 deletions(-) diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index f9b6f2959..46169a786 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -248,6 +248,12 @@ static int hostapd_config_read_wpa_psk(const char *fname, { FILE *f; char buf[128], *pos; + const char *keyid; + char *context; + char *context2; + char *token; + char *name; + char *value; int line = 0, ret = 0, len, ok; u8 addr[ETH_ALEN]; struct hostapd_wpa_psk *psk; @@ -277,9 +283,31 @@ static int hostapd_config_read_wpa_psk(const char *fname, if (buf[0] == '\0') continue; - if (hwaddr_aton(buf, addr)) { + context = NULL; + keyid = NULL; + while ((token = str_token(buf, " ", &context))) { + if (!os_strchr(token, '=')) + break; + context2 = NULL; + name = str_token(token, "=", &context2); + value = str_token(token, "", &context2) ?: ""; + if (!strcmp(name, "keyid")) { + keyid = value; + } else { + wpa_printf(MSG_ERROR, + "Unrecognized '%s=%s' on line %d in '%s'", + name, value, line, fname); + ret = -1; + break; + } + } + + if (ret == -1) + break; + + if (hwaddr_aton(token ?: "", addr)) { wpa_printf(MSG_ERROR, "Invalid MAC address '%s' on " - "line %d in '%s'", buf, line, fname); + "line %d in '%s'", token, line, fname); ret = -1; break; } @@ -295,15 +323,14 @@ static int hostapd_config_read_wpa_psk(const char *fname, else os_memcpy(psk->addr, addr, ETH_ALEN); - pos = buf + 17; - if (*pos == '\0') { + pos = str_token(buf, "", &context); + if (!pos) { wpa_printf(MSG_ERROR, "No PSK on line %d in '%s'", line, fname); os_free(psk); ret = -1; break; } - pos++; ok = 0; len = os_strlen(pos); @@ -322,6 +349,18 @@ static int hostapd_config_read_wpa_psk(const char *fname, break; } + if (keyid) { + len = os_strlcpy(psk->keyid, keyid, sizeof(psk->keyid)); + if (len >= sizeof(psk->keyid)) { + wpa_printf(MSG_ERROR, + "PSK keyid too long on line %d in '%s'", + line, fname); + os_free(psk); + ret = -1; + break; + } + } + psk->next = ssid->wpa_psk; ssid->wpa_psk = psk; } diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 778366d49..2cbb66201 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -132,6 +132,7 @@ struct hostapd_vlan { }; #define PMK_LEN 32 +#define KEYID_LEN 32 #define MIN_PASSPHRASE_LEN 8 #define MAX_PASSPHRASE_LEN 63 struct hostapd_sta_wpa_psk_short { @@ -145,6 +146,7 @@ struct hostapd_sta_wpa_psk_short { struct hostapd_wpa_psk { struct hostapd_wpa_psk *next; int group; + char keyid[KEYID_LEN]; u8 psk[PMK_LEN]; u8 addr[ETH_ALEN]; u8 p2p_dev_addr[ETH_ALEN]; diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c index 21b813ee1..ee417d01e 100644 --- a/src/ap/ctrl_iface_ap.c +++ b/src/ap/ctrl_iface_ap.c @@ -207,6 +207,7 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd, char *buf, size_t buflen) { int len, res, ret, i; + const char *keyid; if (!sta) return 0; @@ -341,6 +342,10 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd, len += ret; } + keyid = ap_sta_wpa_get_keyid(hapd, sta); + if (keyid) + len += os_snprintf(buf + len, buflen - len, "keyid=%s\n", keyid); + return len; } diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c index 179cf43b6..0b9273e5e 100644 --- a/src/ap/sta_info.c +++ b/src/ap/sta_info.c @@ -1165,6 +1165,34 @@ void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta) #endif /* CONFIG_IEEE80211W */ +const char *ap_sta_wpa_get_keyid(struct hostapd_data *hapd, + struct sta_info *sta) +{ + struct hostapd_wpa_psk *psk; + struct hostapd_ssid *ssid; + const u8 *pmk; + int pmk_len; + + ssid = &hapd->conf->ssid; + + pmk = wpa_auth_get_pmk(sta->wpa_sm, &pmk_len); + if (!pmk) + return NULL; + if (pmk_len != PMK_LEN) + return NULL; + + for (psk = ssid->wpa_psk; psk; psk = psk->next) + if (!os_memcmp(pmk, psk->psk, PMK_LEN)) + break; + if (!psk) + return NULL; + if (!strlen(psk->keyid)) + return NULL; + + return psk->keyid; +} + + void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta, int authorized) { @@ -1203,7 +1231,10 @@ void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta, sta->addr, authorized, dev_addr); if (authorized) { + const char *keyid; + char keyid_buf[100]; char ip_addr[100]; + keyid_buf[0] = '\0'; ip_addr[0] = '\0'; #ifdef CONFIG_P2P if (wpa_auth_get_ip_addr(sta->wpa_sm, ip_addr_buf) == 0) { @@ -1214,14 +1245,20 @@ void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta, } #endif /* CONFIG_P2P */ - wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s", - buf, ip_addr); + keyid = ap_sta_wpa_get_keyid(hapd, sta); + if (keyid) { + os_snprintf(keyid_buf, sizeof(keyid_buf), + " keyid=%s", keyid); + } + + wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s%s", + buf, ip_addr, keyid_buf); if (hapd->msg_ctx_parent && hapd->msg_ctx_parent != hapd->msg_ctx) wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO, - AP_STA_CONNECTED "%s%s", - buf, ip_addr); + AP_STA_CONNECTED "%s%s%s", + buf, ip_addr, keyid_buf); } else { wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED "%s", buf); diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h index 9cac6f157..b7fd60809 100644 --- a/src/ap/sta_info.h +++ b/src/ap/sta_info.h @@ -320,6 +320,8 @@ int ap_sta_set_vlan(struct hostapd_data *hapd, struct sta_info *sta, void ap_sta_start_sa_query(struct hostapd_data *hapd, struct sta_info *sta); void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta); int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta); +const char *ap_sta_wpa_get_keyid(struct hostapd_data *hapd, + struct sta_info *sta); void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta, const u8 *addr, u16 reason); -- 2.20.1 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap