aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Kazior <michal@plume.com>2019-01-16 12:35:19 (GMT)
committerJouni Malinen <j@w1.fi>2019-01-26 15:52:04 (GMT)
commitec5c39a5574d4fbee983ae659ea0834bf48ea14d (patch)
treea5b112820ea0d9be6f439a82b498301bd76103ec
parentb08c9ad0c78d2c767d62e1d169560debe8db0ce6 (diff)
downloadhostap-ec5c39a5574d4fbee983ae659ea0834bf48ea14d.zip
hostap-ec5c39a5574d4fbee983ae659ea0834bf48ea14d.tar.gz
hostap-ec5c39a5574d4fbee983ae659ea0834bf48ea14d.tar.bz2
AP: Allow identifying which passphrase station used with wpa_psk_file
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 the control interface: $ hostapd_cli all_sta Selected interface 'ap0' 00:36:76:21:dc:7b ... keyid=something New hostapd is able to read old wpa_psk_file. However, old hostapd will not be able to read the new wpa_psk_file if it includes keyids. Signed-off-by: Michal Kazior <michal@plume.com>
-rw-r--r--hostapd/hostapd.wpa_psk3
-rw-r--r--src/ap/ap_config.c53
-rw-r--r--src/ap/ap_config.h2
-rw-r--r--src/ap/ctrl_iface_ap.c8
-rw-r--r--src/ap/sta_info.c44
-rw-r--r--src/ap/sta_info.h2
6 files changed, 103 insertions, 9 deletions
diff --git a/hostapd/hostapd.wpa_psk b/hostapd/hostapd.wpa_psk
index 0a9499a..834d441 100644
--- a/hostapd/hostapd.wpa_psk
+++ b/hostapd/hostapd.wpa_psk
@@ -3,7 +3,10 @@
# Special MAC address 00:00:00:00:00:00 can be used to configure PSKs that
# anyone can use. PSK can be configured as an ASCII passphrase of 8..63
# characters or as a 256-bit hex PSK (64 hex digits).
+# An optional key identifier can be added by prefixing the line with
+# keyid=<keyid_string>
00:00:00:00:00:00 secret passphrase
00:11:22:33:44:55 another passphrase
00:22:33:44:55:66 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
+keyid=example_id 00:11:22:33:44:77 passphrase with keyid
00:00:00:00:00:00 another passphrase for all STAs
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 0cb302b..9611dc0 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -259,6 +259,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;
@@ -288,9 +294,35 @@ 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 (!value)
+ value = "";
+ if (!os_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 (!token)
+ token = "";
+ 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;
}
@@ -306,15 +338,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);
@@ -333,6 +364,18 @@ static int hostapd_config_read_wpa_psk(const char *fname,
break;
}
+ if (keyid) {
+ len = os_strlcpy(psk->keyid, keyid, sizeof(psk->keyid));
+ if ((size_t) 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 16a4d06..8ca80d3 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -134,6 +134,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 {
@@ -147,6 +148,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 21b813e..3128aed 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,13 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
len += ret;
}
+ keyid = ap_sta_wpa_get_keyid(hapd, sta);
+ if (keyid) {
+ ret = os_snprintf(buf + len, buflen - len, "keyid=%s\n", keyid);
+ if (!os_snprintf_error(buflen - len, ret))
+ len += ret;
+ }
+
return len;
}
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index 06f9afc..8858a34 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -1163,6 +1163,32 @@ 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 || pmk_len != PMK_LEN)
+ return NULL;
+
+ for (psk = ssid->wpa_psk; psk; psk = psk->next)
+ if (os_memcmp(pmk, psk->psk, PMK_LEN) == 0)
+ break;
+ if (!psk)
+ return NULL;
+ if (!psk || !psk->keyid[0])
+ return NULL;
+
+ return psk->keyid;
+}
+
+
void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta,
int authorized)
{
@@ -1201,7 +1227,11 @@ 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) {
@@ -1212,14 +1242,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 fe68369..ee3f628 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -324,6 +324,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);