summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2019-09-20 06:57:58 +0200
committerJo-Philipp Wich <jo@mein.io>2019-09-20 13:12:53 +0200
commit3d47ddda0c64ad790a26de085e3a3e70c3578e12 (patch)
tree34e0ad83be8ee9e05bd9bad5aed0a6d19d21d41c
parenta88fb421f136d799af855dbe3dca917834db7185 (diff)
downloadiwinfo-3d47ddda0c64ad790a26de085e3a3e70c3578e12.tar.gz
nl80211: rework hostapd and wpa_supplicant wpa suite parsing
Refactor the parsing of wpa_supplicant scan list results, the wpa_supplicant status output and the hostapd configuration file format to properly detect WPA3 key management protocols like SAE, OWE or EAP Suite B. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
-rw-r--r--iwinfo_nl80211.c264
1 files changed, 148 insertions, 116 deletions
diff --git a/iwinfo_nl80211.c b/iwinfo_nl80211.c
index 690f8b2..2a4cc1e 100644
--- a/iwinfo_nl80211.c
+++ b/iwinfo_nl80211.c
@@ -1492,8 +1492,108 @@ static int nl80211_check_wepkey(const char *key)
return 0;
}
+static struct {
+ const char *match;
+ int version;
+ int suite;
+} wpa_key_mgmt_strings[] = {
+ { "IEEE 802.1X/EAP", 0, IWINFO_KMGMT_8021x },
+ { "EAP-SUITE-B-192", 4, IWINFO_KMGMT_8021x },
+ { "EAP-SUITE-B", 4, IWINFO_KMGMT_8021x },
+ { "EAP-SHA256", 0, IWINFO_KMGMT_8021x },
+ { "PSK-SHA256", 0, IWINFO_KMGMT_PSK },
+ { "NONE", 0, IWINFO_KMGMT_NONE },
+ { "None", 0, IWINFO_KMGMT_NONE },
+ { "PSK", 0, IWINFO_KMGMT_PSK },
+ { "EAP", 0, IWINFO_KMGMT_8021x },
+ { "SAE", 4, IWINFO_KMGMT_SAE },
+ { "OWE", 4, IWINFO_KMGMT_OWE }
+};
+
+static void parse_wpa_suites(const char *str, int defversion,
+ uint8_t *versions, uint8_t *suites)
+{
+ size_t l;
+ int i, version;
+ const char *p, *q, *m, *sep = " \t\n,-+/";
+
+ for (p = str; *p; )
+ {
+ q = p;
+
+ for (i = 0; i < ARRAY_SIZE(wpa_key_mgmt_strings); i++)
+ {
+ m = wpa_key_mgmt_strings[i].match;
+ l = strlen(m);
+
+ if (!strncmp(q, m, l) && (!q[l] || strchr(sep, q[l])))
+ {
+ if (wpa_key_mgmt_strings[i].version != 0)
+ version = wpa_key_mgmt_strings[i].version;
+ else
+ version = defversion;
+
+ *versions |= version;
+ *suites |= wpa_key_mgmt_strings[i].suite;
+
+ q += l;
+ break;
+ }
+ }
+
+ if (q == p)
+ q += strcspn(q, sep);
+
+ p = q + strspn(q, sep);
+ }
+}
+
+static struct {
+ const char *match;
+ int cipher;
+} wpa_cipher_strings[] = {
+ { "WEP-104", IWINFO_CIPHER_WEP104 },
+ { "WEP-40", IWINFO_CIPHER_WEP40 },
+ { "NONE", IWINFO_CIPHER_NONE },
+ { "TKIP", IWINFO_CIPHER_TKIP },
+ { "CCMP", IWINFO_CIPHER_CCMP }
+};
+
+static void parse_wpa_ciphers(const char *str, uint8_t *ciphers)
+{
+ int i;
+ size_t l;
+ const char *m, *p, *q, *sep = " \t\n,-+/";
+
+ for (p = str; *p; )
+ {
+ q = p;
+
+ for (i = 0; i < ARRAY_SIZE(wpa_cipher_strings); i++)
+ {
+ m = wpa_cipher_strings[i].match;
+ l = strlen(m);
+
+ if (!strncmp(q, m, l) && (!q[l] || strchr(sep, q[l])))
+ {
+ *ciphers |= wpa_cipher_strings[i].cipher;
+
+ q += l;
+ break;
+ }
+ }
+
+ if (q == p)
+ q += strcspn(q, sep);
+
+ p = q + strspn(q, sep);
+ }
+}
+
static int nl80211_get_encryption(const char *ifname, char *buf)
{
+ char *p;
+ uint8_t wpa_version = 0;
char wpa[2], wpa_key_mgmt[64], wpa_pairwise[16], wpa_groupwise[16];
char auth_algs[2], wep_key0[27], wep_key1[27], wep_key2[27], wep_key3[27];
@@ -1508,15 +1608,8 @@ static int nl80211_get_encryption(const char *ifname, char *buf)
/* WEP */
if (!strcmp(wpa_key_mgmt, "NONE"))
{
- if (strstr(wpa_pairwise, "WEP-40"))
- c->pair_ciphers |= IWINFO_CIPHER_WEP40;
- else if (strstr(wpa_pairwise, "WEP-104"))
- c->pair_ciphers |= IWINFO_CIPHER_WEP104;
-
- if (strstr(wpa_groupwise, "WEP-40"))
- c->group_ciphers |= IWINFO_CIPHER_WEP40;
- else if (strstr(wpa_groupwise, "WEP-104"))
- c->group_ciphers |= IWINFO_CIPHER_WEP104;
+ parse_wpa_ciphers(wpa_pairwise, &c->pair_ciphers);
+ parse_wpa_ciphers(wpa_groupwise, &c->group_ciphers);
c->enabled = !!(c->pair_ciphers | c->group_ciphers);
c->auth_suites |= IWINFO_KMGMT_NONE;
@@ -1524,42 +1617,25 @@ static int nl80211_get_encryption(const char *ifname, char *buf)
}
/* WPA */
- else if (strstr(wpa_key_mgmt, "WPA"))
+ else
{
- if (strstr(wpa_pairwise, "TKIP"))
- c->pair_ciphers |= IWINFO_CIPHER_TKIP;
- else if (strstr(wpa_pairwise, "CCMP"))
- c->pair_ciphers |= IWINFO_CIPHER_CCMP;
- else if (strstr(wpa_pairwise, "NONE"))
- c->pair_ciphers |= IWINFO_CIPHER_NONE;
- else if (strstr(wpa_pairwise, "WEP-40"))
- c->pair_ciphers |= IWINFO_CIPHER_WEP40;
- else if (strstr(wpa_pairwise, "WEP-104"))
- c->pair_ciphers |= IWINFO_CIPHER_WEP104;
-
- if (strstr(wpa_groupwise, "TKIP"))
- c->group_ciphers |= IWINFO_CIPHER_TKIP;
- else if (strstr(wpa_groupwise, "CCMP"))
- c->group_ciphers |= IWINFO_CIPHER_CCMP;
- else if (strstr(wpa_groupwise, "NONE"))
- c->group_ciphers |= IWINFO_CIPHER_NONE;
- else if (strstr(wpa_groupwise, "WEP-40"))
- c->group_ciphers |= IWINFO_CIPHER_WEP40;
- else if (strstr(wpa_groupwise, "WEP-104"))
- c->group_ciphers |= IWINFO_CIPHER_WEP104;
-
- if (strstr(wpa_key_mgmt, "WPA2"))
- c->wpa_version = 2;
- else if (strstr(wpa_key_mgmt, "WPA"))
- c->wpa_version = 1;
-
- if (strstr(wpa_key_mgmt, "PSK"))
- c->auth_suites |= IWINFO_KMGMT_PSK;
- else if (strstr(wpa_key_mgmt, "EAP") ||
- strstr(wpa_key_mgmt, "802.1X"))
- c->auth_suites |= IWINFO_KMGMT_8021x;
- else if (strstr(wpa_key_mgmt, "NONE"))
- c->auth_suites |= IWINFO_KMGMT_NONE;
+ parse_wpa_ciphers(wpa_pairwise, &c->pair_ciphers);
+ parse_wpa_ciphers(wpa_groupwise, &c->group_ciphers);
+
+ p = wpa_key_mgmt;
+
+ if (!strncmp(p, "WPA2-", 5) || !strncmp(p, "WPA2/", 5))
+ {
+ p += 5;
+ wpa_version = 2;
+ }
+ else if (!strncmp(p, "WPA-", 4))
+ {
+ p += 4;
+ wpa_version = 1;
+ }
+
+ parse_wpa_suites(p, wpa_version, &c->wpa_version, &c->auth_suites);
c->enabled = !!(c->wpa_version && c->auth_suites);
}
@@ -1578,49 +1654,27 @@ static int nl80211_get_encryption(const char *ifname, char *buf)
"wep_key2", wep_key2, sizeof(wep_key2),
"wep_key3", wep_key3, sizeof(wep_key3)))
{
- c->wpa_version = wpa[0] ? atoi(wpa) : 0;
+ c->wpa_version = 0;
if (wpa_key_mgmt[0])
{
- if (strstr(wpa_key_mgmt, "PSK"))
- c->auth_suites |= IWINFO_KMGMT_PSK;
-
- if (strstr(wpa_key_mgmt, "EAP"))
- c->auth_suites |= IWINFO_KMGMT_8021x;
-
- if (strstr(wpa_key_mgmt, "SAE")){
- c->auth_suites |= IWINFO_KMGMT_SAE;
- c->wpa_version = 4;
- }
+ for (p = strtok(wpa_key_mgmt, " \t"); p != NULL; p = strtok(NULL, " \t"))
+ {
+ if (!strncmp(p, "WPA-", 4))
+ p += 4;
- if (strstr(wpa_key_mgmt, "OWE")){
- c->auth_suites |= IWINFO_KMGMT_OWE;
- c->wpa_version = 4;
+ parse_wpa_suites(p, atoi(wpa), &c->wpa_version, &c->auth_suites);
}
- if (strstr(wpa_key_mgmt, "NONE"))
- c->auth_suites |= IWINFO_KMGMT_NONE;
- }
- else
- {
- c->auth_suites |= IWINFO_KMGMT_PSK;
+ c->enabled = c->wpa_version ? 1 : 0;
}
if (wpa_pairwise[0])
- {
- if (strstr(wpa_pairwise, "TKIP"))
- c->pair_ciphers |= IWINFO_CIPHER_TKIP;
-
- if (strstr(wpa_pairwise, "CCMP"))
- c->pair_ciphers |= IWINFO_CIPHER_CCMP;
-
- if (strstr(wpa_pairwise, "NONE"))
- c->pair_ciphers |= IWINFO_CIPHER_NONE;
- }
+ parse_wpa_ciphers(wpa_pairwise, &c->pair_ciphers);
if (auth_algs[0])
{
- switch(atoi(auth_algs))
+ switch (atoi(auth_algs))
{
case 1:
c->auth_algs |= IWINFO_AUTH_OPEN;
@@ -1636,6 +1690,7 @@ static int nl80211_get_encryption(const char *ifname, char *buf)
break;
}
+ c->enabled = c->auth_algs ? 1 : 0;
c->pair_ciphers |= nl80211_check_wepkey(wep_key0);
c->pair_ciphers |= nl80211_check_wepkey(wep_key1);
c->pair_ciphers |= nl80211_check_wepkey(wep_key2);
@@ -1643,7 +1698,6 @@ static int nl80211_get_encryption(const char *ifname, char *buf)
}
c->group_ciphers = c->pair_ciphers;
- c->enabled = (c->wpa_version || c->pair_ciphers) ? 1 : 0;
return 0;
}
@@ -2121,53 +2175,31 @@ static int nl80211_get_txpwrlist(const char *ifname, char *buf, int *len)
return -1;
}
-static void nl80211_get_scancrypto(const char *spec,
- struct iwinfo_crypto_entry *c)
+static void nl80211_get_scancrypto(char *spec, struct iwinfo_crypto_entry *c)
{
- if (strstr(spec, "WPA") || strstr(spec, "WEP"))
- {
- c->enabled = 1;
-
- if (strstr(spec, "WPA2-") && strstr(spec, "WPA-"))
- c->wpa_version = 3;
-
- else if (strstr(spec, "WPA2"))
- c->wpa_version = 2;
-
- else if (strstr(spec, "WPA"))
- c->wpa_version = 1;
+ int wpa_version = 0;
+ char *p, *proto, *suites;
- else if (strstr(spec, "WEP"))
- c->auth_algs = IWINFO_AUTH_OPEN | IWINFO_AUTH_SHARED;
-
-
- if (strstr(spec, "PSK"))
- c->auth_suites |= IWINFO_KMGMT_PSK;
-
- if (strstr(spec, "802.1X") || strstr(spec, "EAP"))
- c->auth_suites |= IWINFO_KMGMT_8021x;
-
- if (strstr(spec, "WPA-NONE"))
- c->auth_suites |= IWINFO_KMGMT_NONE;
+ c->enabled = 0;
+ for (p = strtok(spec, "[]"); p != NULL; p = strtok(NULL, "[]")) {
+ proto = strtok(p, "-");
+ suites = strtok(NULL, "]");
- if (strstr(spec, "TKIP"))
- c->pair_ciphers |= IWINFO_CIPHER_TKIP;
-
- if (strstr(spec, "CCMP"))
- c->pair_ciphers |= IWINFO_CIPHER_CCMP;
+ if (!proto || !suites)
+ continue;
- if (strstr(spec, "WEP-40"))
- c->pair_ciphers |= IWINFO_CIPHER_WEP40;
+ if (!strcmp(proto, "WPA2") || !strcmp(proto, "RSN"))
+ wpa_version = 2;
+ else if (!strcmp(proto, "WPA"))
+ wpa_version = 1;
+ else
+ continue;
- if (strstr(spec, "WEP-104"))
- c->pair_ciphers |= IWINFO_CIPHER_WEP104;
+ c->enabled = 1;
- c->group_ciphers = c->pair_ciphers;
- }
- else
- {
- c->enabled = 0;
+ parse_wpa_suites(suites, wpa_version, &c->wpa_version, &c->auth_suites);
+ parse_wpa_ciphers(suites, &c->pair_ciphers);
}
}