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>
This commit is contained in:
parent
b08c9ad0c7
commit
ec5c39a557
6 changed files with 103 additions and 9 deletions
|
@ -3,7 +3,10 @@
|
||||||
# Special MAC address 00:00:00:00:00:00 can be used to configure PSKs that
|
# 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
|
# 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).
|
# 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:00:00:00:00:00 secret passphrase
|
||||||
00:11:22:33:44:55 another passphrase
|
00:11:22:33:44:55 another passphrase
|
||||||
00:22:33:44:55:66 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
|
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
|
00:00:00:00:00:00 another passphrase for all STAs
|
||||||
|
|
|
@ -259,6 +259,12 @@ static int hostapd_config_read_wpa_psk(const char *fname,
|
||||||
{
|
{
|
||||||
FILE *f;
|
FILE *f;
|
||||||
char buf[128], *pos;
|
char buf[128], *pos;
|
||||||
|
const char *keyid;
|
||||||
|
char *context;
|
||||||
|
char *context2;
|
||||||
|
char *token;
|
||||||
|
char *name;
|
||||||
|
char *value;
|
||||||
int line = 0, ret = 0, len, ok;
|
int line = 0, ret = 0, len, ok;
|
||||||
u8 addr[ETH_ALEN];
|
u8 addr[ETH_ALEN];
|
||||||
struct hostapd_wpa_psk *psk;
|
struct hostapd_wpa_psk *psk;
|
||||||
|
@ -288,9 +294,35 @@ static int hostapd_config_read_wpa_psk(const char *fname,
|
||||||
if (buf[0] == '\0')
|
if (buf[0] == '\0')
|
||||||
continue;
|
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 "
|
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;
|
ret = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -306,15 +338,14 @@ static int hostapd_config_read_wpa_psk(const char *fname,
|
||||||
else
|
else
|
||||||
os_memcpy(psk->addr, addr, ETH_ALEN);
|
os_memcpy(psk->addr, addr, ETH_ALEN);
|
||||||
|
|
||||||
pos = buf + 17;
|
pos = str_token(buf, "", &context);
|
||||||
if (*pos == '\0') {
|
if (!pos) {
|
||||||
wpa_printf(MSG_ERROR, "No PSK on line %d in '%s'",
|
wpa_printf(MSG_ERROR, "No PSK on line %d in '%s'",
|
||||||
line, fname);
|
line, fname);
|
||||||
os_free(psk);
|
os_free(psk);
|
||||||
ret = -1;
|
ret = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pos++;
|
|
||||||
|
|
||||||
ok = 0;
|
ok = 0;
|
||||||
len = os_strlen(pos);
|
len = os_strlen(pos);
|
||||||
|
@ -333,6 +364,18 @@ static int hostapd_config_read_wpa_psk(const char *fname,
|
||||||
break;
|
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;
|
psk->next = ssid->wpa_psk;
|
||||||
ssid->wpa_psk = psk;
|
ssid->wpa_psk = psk;
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,6 +134,7 @@ struct hostapd_vlan {
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PMK_LEN 32
|
#define PMK_LEN 32
|
||||||
|
#define KEYID_LEN 32
|
||||||
#define MIN_PASSPHRASE_LEN 8
|
#define MIN_PASSPHRASE_LEN 8
|
||||||
#define MAX_PASSPHRASE_LEN 63
|
#define MAX_PASSPHRASE_LEN 63
|
||||||
struct hostapd_sta_wpa_psk_short {
|
struct hostapd_sta_wpa_psk_short {
|
||||||
|
@ -147,6 +148,7 @@ struct hostapd_sta_wpa_psk_short {
|
||||||
struct hostapd_wpa_psk {
|
struct hostapd_wpa_psk {
|
||||||
struct hostapd_wpa_psk *next;
|
struct hostapd_wpa_psk *next;
|
||||||
int group;
|
int group;
|
||||||
|
char keyid[KEYID_LEN];
|
||||||
u8 psk[PMK_LEN];
|
u8 psk[PMK_LEN];
|
||||||
u8 addr[ETH_ALEN];
|
u8 addr[ETH_ALEN];
|
||||||
u8 p2p_dev_addr[ETH_ALEN];
|
u8 p2p_dev_addr[ETH_ALEN];
|
||||||
|
|
|
@ -207,6 +207,7 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
|
||||||
char *buf, size_t buflen)
|
char *buf, size_t buflen)
|
||||||
{
|
{
|
||||||
int len, res, ret, i;
|
int len, res, ret, i;
|
||||||
|
const char *keyid;
|
||||||
|
|
||||||
if (!sta)
|
if (!sta)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -341,6 +342,13 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
|
||||||
len += ret;
|
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;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1163,6 +1163,32 @@ void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta)
|
||||||
#endif /* CONFIG_IEEE80211W */
|
#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,
|
void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
int authorized)
|
int authorized)
|
||||||
{
|
{
|
||||||
|
@ -1201,7 +1227,11 @@ void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
sta->addr, authorized, dev_addr);
|
sta->addr, authorized, dev_addr);
|
||||||
|
|
||||||
if (authorized) {
|
if (authorized) {
|
||||||
|
const char *keyid;
|
||||||
|
char keyid_buf[100];
|
||||||
char ip_addr[100];
|
char ip_addr[100];
|
||||||
|
|
||||||
|
keyid_buf[0] = '\0';
|
||||||
ip_addr[0] = '\0';
|
ip_addr[0] = '\0';
|
||||||
#ifdef CONFIG_P2P
|
#ifdef CONFIG_P2P
|
||||||
if (wpa_auth_get_ip_addr(sta->wpa_sm, ip_addr_buf) == 0) {
|
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 */
|
#endif /* CONFIG_P2P */
|
||||||
|
|
||||||
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s",
|
keyid = ap_sta_wpa_get_keyid(hapd, sta);
|
||||||
buf, ip_addr);
|
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 &&
|
if (hapd->msg_ctx_parent &&
|
||||||
hapd->msg_ctx_parent != hapd->msg_ctx)
|
hapd->msg_ctx_parent != hapd->msg_ctx)
|
||||||
wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO,
|
wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO,
|
||||||
AP_STA_CONNECTED "%s%s",
|
AP_STA_CONNECTED "%s%s%s",
|
||||||
buf, ip_addr);
|
buf, ip_addr, keyid_buf);
|
||||||
} else {
|
} else {
|
||||||
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED "%s", buf);
|
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED "%s", buf);
|
||||||
|
|
||||||
|
|
|
@ -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_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);
|
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);
|
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,
|
void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
const u8 *addr, u16 reason);
|
const u8 *addr, u16 reason);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue