DPP: Clean up configuration parsing

Share a single parsing implementation for both hostapd and
wpa_supplicant to avoid code duplication. In addition, clean up the
implementation to be more easily extensible.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
This commit is contained in:
Jouni Malinen 2019-03-16 12:19:10 +02:00 committed by Jouni Malinen
parent 3e1cfead0b
commit 9305c2332b
4 changed files with 195 additions and 299 deletions

View file

@ -519,171 +519,31 @@ static int hostapd_dpp_set_configurator(struct hostapd_data *hapd,
struct dpp_authentication *auth,
const char *cmd)
{
const char *pos, *end;
struct dpp_configuration *conf_sta = NULL, *conf_ap = NULL;
struct dpp_configurator *conf = NULL;
u8 ssid[32] = { "test" };
size_t ssid_len = 4;
char pass[64] = { };
size_t pass_len = 0;
u8 psk[PMK_LEN];
int psk_set = 0;
char *group_id = NULL;
const char *pos;
if (!cmd)
return 0;
wpa_printf(MSG_DEBUG, "DPP: Set configurator parameters: %s", cmd);
pos = os_strstr(cmd, " ssid=");
if (pos) {
pos += 6;
end = os_strchr(pos, ' ');
ssid_len = end ? (size_t) (end - pos) : os_strlen(pos);
ssid_len /= 2;
if (ssid_len > sizeof(ssid) ||
hexstr2bin(pos, ssid, ssid_len) < 0)
goto fail;
}
pos = os_strstr(cmd, " pass=");
if (pos) {
pos += 6;
end = os_strchr(pos, ' ');
pass_len = end ? (size_t) (end - pos) : os_strlen(pos);
pass_len /= 2;
if (pass_len > sizeof(pass) - 1 || pass_len < 8 ||
hexstr2bin(pos, (u8 *) pass, pass_len) < 0)
goto fail;
}
pos = os_strstr(cmd, " psk=");
if (pos) {
pos += 5;
if (hexstr2bin(pos, psk, PMK_LEN) < 0)
goto fail;
psk_set = 1;
}
pos = os_strstr(cmd, " group_id=");
if (pos) {
size_t group_id_len;
pos += 10;
end = os_strchr(pos, ' ');
group_id_len = end ? (size_t) (end - pos) : os_strlen(pos);
group_id = os_malloc(group_id_len + 1);
if (!group_id)
goto fail;
os_memcpy(group_id, pos, group_id_len);
group_id[group_id_len] = '\0';
}
if (os_strstr(cmd, " conf=sta-")) {
conf_sta = os_zalloc(sizeof(struct dpp_configuration));
if (!conf_sta)
goto fail;
os_memcpy(conf_sta->ssid, ssid, ssid_len);
conf_sta->ssid_len = ssid_len;
if (os_strstr(cmd, " conf=sta-psk") ||
os_strstr(cmd, " conf=sta-sae") ||
os_strstr(cmd, " conf=sta-psk-sae")) {
if (os_strstr(cmd, " conf=sta-psk-sae"))
conf_sta->akm = DPP_AKM_PSK_SAE;
else if (os_strstr(cmd, " conf=sta-sae"))
conf_sta->akm = DPP_AKM_SAE;
else
conf_sta->akm = DPP_AKM_PSK;
if (psk_set) {
os_memcpy(conf_sta->psk, psk, PMK_LEN);
} else {
conf_sta->passphrase = os_strdup(pass);
if (!conf_sta->passphrase)
goto fail;
}
} else if (os_strstr(cmd, " conf=sta-dpp")) {
conf_sta->akm = DPP_AKM_DPP;
} else {
goto fail;
}
if (os_strstr(cmd, " group_id=")) {
conf_sta->group_id = group_id;
group_id = NULL;
}
}
if (os_strstr(cmd, " conf=ap-")) {
conf_ap = os_zalloc(sizeof(struct dpp_configuration));
if (!conf_ap)
goto fail;
os_memcpy(conf_ap->ssid, ssid, ssid_len);
conf_ap->ssid_len = ssid_len;
if (os_strstr(cmd, " conf=ap-psk") ||
os_strstr(cmd, " conf=ap-sae") ||
os_strstr(cmd, " conf=ap-psk-sae")) {
if (os_strstr(cmd, " conf=ap-psk-sae"))
conf_ap->akm = DPP_AKM_PSK_SAE;
else if (os_strstr(cmd, " conf=ap-sae"))
conf_ap->akm = DPP_AKM_SAE;
else
conf_ap->akm = DPP_AKM_PSK;
if (psk_set) {
os_memcpy(conf_ap->psk, psk, PMK_LEN);
} else if (pass_len > 0) {
conf_ap->passphrase = os_strdup(pass);
if (!conf_ap->passphrase)
goto fail;
} else {
goto fail;
}
} else if (os_strstr(cmd, " conf=ap-dpp")) {
conf_ap->akm = DPP_AKM_DPP;
} else {
goto fail;
}
if (os_strstr(cmd, " group_id=")) {
conf_ap->group_id = group_id;
group_id = NULL;
}
}
pos = os_strstr(cmd, " expiry=");
if (pos) {
long int val;
pos += 8;
val = strtol(pos, NULL, 0);
if (val <= 0)
goto fail;
if (conf_sta)
conf_sta->netaccesskey_expiry = val;
if (conf_ap)
conf_ap->netaccesskey_expiry = val;
}
pos = os_strstr(cmd, " configurator=");
if (pos) {
auth->configurator = 1;
pos += 14;
conf = hostapd_dpp_configurator_get_id(hapd, atoi(pos));
if (!conf) {
auth->conf = hostapd_dpp_configurator_get_id(hapd, atoi(pos));
if (!auth->conf) {
wpa_printf(MSG_INFO,
"DPP: Could not find the specified configurator");
goto fail;
return -1;
}
}
auth->conf_sta = conf_sta;
auth->conf_ap = conf_ap;
auth->conf = conf;
os_free(group_id);
return 0;
fail:
wpa_msg(hapd->msg_ctx, MSG_INFO,
"DPP: Failed to set configurator parameters");
dpp_configuration_free(conf_sta);
dpp_configuration_free(conf_ap);
os_free(group_id);
return -1;
if (dpp_configuration_parse(auth, cmd) < 0) {
wpa_msg(hapd->msg_ctx, MSG_INFO,
"DPP: Failed to set configurator parameters");
return -1;
}
return 0;
}

View file

@ -4048,6 +4048,70 @@ fail:
}
static int bin_str_eq(const char *val, size_t len, const char *cmp)
{
return os_strlen(cmp) == len && os_memcmp(val, cmp, len) == 0;
}
struct dpp_configuration * dpp_configuration_alloc(const char *type)
{
struct dpp_configuration *conf;
const char *end;
size_t len;
conf = os_zalloc(sizeof(*conf));
if (!conf)
goto fail;
end = os_strchr(type, ' ');
if (end)
len = end - type;
else
len = os_strlen(type);
if (bin_str_eq(type, len, "psk"))
conf->akm = DPP_AKM_PSK;
else if (bin_str_eq(type, len, "sae"))
conf->akm = DPP_AKM_SAE;
else if (bin_str_eq(type, len, "psk-sae"))
conf->akm = DPP_AKM_PSK_SAE;
else if (bin_str_eq(type, len, "dpp"))
conf->akm = DPP_AKM_DPP;
else
goto fail;
return conf;
fail:
dpp_configuration_free(conf);
return NULL;
}
static int dpp_akm_psk(enum dpp_akm akm)
{
return akm == DPP_AKM_PSK || akm == DPP_AKM_PSK_SAE;
}
static int dpp_akm_sae(enum dpp_akm akm)
{
return akm == DPP_AKM_SAE || akm == DPP_AKM_PSK_SAE;
}
int dpp_configuration_valid(const struct dpp_configuration *conf)
{
if (conf->ssid_len == 0)
return 0;
if (dpp_akm_psk(conf->akm) && !conf->passphrase && !conf->psk_set)
return 0;
if (dpp_akm_sae(conf->akm) && !conf->passphrase)
return 0;
return 1;
}
void dpp_configuration_free(struct dpp_configuration *conf)
{
if (!conf)
@ -4058,6 +4122,113 @@ void dpp_configuration_free(struct dpp_configuration *conf)
}
int dpp_configuration_parse(struct dpp_authentication *auth, const char *cmd)
{
const char *pos, *end;
struct dpp_configuration *conf_sta = NULL, *conf_ap = NULL;
struct dpp_configuration *conf = NULL;
pos = os_strstr(cmd, " conf=sta-");
if (pos) {
conf_sta = dpp_configuration_alloc(pos + 10);
if (!conf_sta)
goto fail;
conf = conf_sta;
}
pos = os_strstr(cmd, " conf=ap-");
if (pos) {
conf_ap = dpp_configuration_alloc(pos + 9);
if (!conf_ap)
goto fail;
conf = conf_ap;
}
if (!conf)
return 0;
pos = os_strstr(cmd, " ssid=");
if (pos) {
pos += 6;
end = os_strchr(pos, ' ');
conf->ssid_len = end ? (size_t) (end - pos) : os_strlen(pos);
conf->ssid_len /= 2;
if (conf->ssid_len > sizeof(conf->ssid) ||
hexstr2bin(pos, conf->ssid, conf->ssid_len) < 0)
goto fail;
} else {
#ifdef CONFIG_TESTING_OPTIONS
/* use a default SSID for legacy testing reasons */
os_memcpy(conf->ssid, "test", 4);
conf->ssid_len = 4;
#else /* CONFIG_TESTING_OPTIONS */
goto fail;
#endif /* CONFIG_TESTING_OPTIONS */
}
pos = os_strstr(cmd, " pass=");
if (pos) {
size_t pass_len;
pos += 6;
end = os_strchr(pos, ' ');
pass_len = end ? (size_t) (end - pos) : os_strlen(pos);
pass_len /= 2;
if (pass_len > 63 || pass_len < 8)
goto fail;
conf->passphrase = os_zalloc(pass_len + 1);
if (!conf->passphrase ||
hexstr2bin(pos, (u8 *) conf->passphrase, pass_len) < 0)
goto fail;
}
pos = os_strstr(cmd, " psk=");
if (pos) {
pos += 5;
if (hexstr2bin(pos, conf->psk, PMK_LEN) < 0)
goto fail;
conf->psk_set = 1;
}
pos = os_strstr(cmd, " group_id=");
if (pos) {
size_t group_id_len;
pos += 10;
end = os_strchr(pos, ' ');
group_id_len = end ? (size_t) (end - pos) : os_strlen(pos);
conf->group_id = os_malloc(group_id_len + 1);
if (!conf->group_id)
goto fail;
os_memcpy(conf->group_id, pos, group_id_len);
conf->group_id[group_id_len] = '\0';
}
pos = os_strstr(cmd, " expiry=");
if (pos) {
long int val;
pos += 8;
val = strtol(pos, NULL, 0);
if (val <= 0)
goto fail;
conf->netaccesskey_expiry = val;
}
if (!dpp_configuration_valid(conf))
goto fail;
auth->conf_sta = conf_sta;
auth->conf_ap = conf_ap;
return 0;
fail:
dpp_configuration_free(conf_sta);
dpp_configuration_free(conf_ap);
return -1;
}
void dpp_auth_deinit(struct dpp_authentication *auth)
{
if (!auth)

View file

@ -163,6 +163,7 @@ struct dpp_configuration {
/* For legacy configuration */
char *passphrase;
u8 psk[32];
int psk_set;
};
struct dpp_authentication {
@ -392,7 +393,10 @@ int dpp_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr,
const u8 *attr_start, size_t attr_len);
int dpp_notify_new_qr_code(struct dpp_authentication *auth,
struct dpp_bootstrap_info *peer_bi);
struct dpp_configuration * dpp_configuration_alloc(const char *type);
int dpp_configuration_valid(const struct dpp_configuration *conf);
void dpp_configuration_free(struct dpp_configuration *conf);
int dpp_configuration_parse(struct dpp_authentication *auth, const char *cmd);
void dpp_auth_deinit(struct dpp_authentication *auth);
struct wpabuf *
dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start,

View file

@ -554,169 +554,30 @@ static int wpas_dpp_set_configurator(struct wpa_supplicant *wpa_s,
struct dpp_authentication *auth,
const char *cmd)
{
const char *pos, *end;
struct dpp_configuration *conf_sta = NULL, *conf_ap = NULL;
struct dpp_configurator *conf = NULL;
u8 ssid[32] = { "test" };
size_t ssid_len = 4;
char pass[64] = { };
size_t pass_len = 0;
u8 psk[PMK_LEN];
int psk_set = 0;
char *group_id = NULL;
const char *pos;
if (!cmd)
return 0;
wpa_printf(MSG_DEBUG, "DPP: Set configurator parameters: %s", cmd);
pos = os_strstr(cmd, " ssid=");
if (pos) {
pos += 6;
end = os_strchr(pos, ' ');
ssid_len = end ? (size_t) (end - pos) : os_strlen(pos);
ssid_len /= 2;
if (ssid_len > sizeof(ssid) ||
hexstr2bin(pos, ssid, ssid_len) < 0)
goto fail;
}
pos = os_strstr(cmd, " pass=");
if (pos) {
pos += 6;
end = os_strchr(pos, ' ');
pass_len = end ? (size_t) (end - pos) : os_strlen(pos);
pass_len /= 2;
if (pass_len > sizeof(pass) - 1 || pass_len < 8 ||
hexstr2bin(pos, (u8 *) pass, pass_len) < 0)
goto fail;
}
pos = os_strstr(cmd, " psk=");
if (pos) {
pos += 5;
if (hexstr2bin(pos, psk, PMK_LEN) < 0)
goto fail;
psk_set = 1;
}
pos = os_strstr(cmd, " group_id=");
if (pos) {
size_t group_id_len;
pos += 10;
end = os_strchr(pos, ' ');
group_id_len = end ? (size_t) (end - pos) : os_strlen(pos);
group_id = os_malloc(group_id_len + 1);
if (!group_id)
goto fail;
os_memcpy(group_id, pos, group_id_len);
group_id[group_id_len] = '\0';
}
if (os_strstr(cmd, " conf=sta-")) {
conf_sta = os_zalloc(sizeof(struct dpp_configuration));
if (!conf_sta)
goto fail;
os_memcpy(conf_sta->ssid, ssid, ssid_len);
conf_sta->ssid_len = ssid_len;
if (os_strstr(cmd, " conf=sta-psk") ||
os_strstr(cmd, " conf=sta-sae") ||
os_strstr(cmd, " conf=sta-psk-sae")) {
if (os_strstr(cmd, " conf=sta-psk-sae"))
conf_sta->akm = DPP_AKM_PSK_SAE;
else if (os_strstr(cmd, " conf=sta-sae"))
conf_sta->akm = DPP_AKM_SAE;
else
conf_sta->akm = DPP_AKM_PSK;
if (psk_set) {
os_memcpy(conf_sta->psk, psk, PMK_LEN);
} else if (pass_len > 0) {
conf_sta->passphrase = os_strdup(pass);
if (!conf_sta->passphrase)
goto fail;
} else {
goto fail;
}
} else if (os_strstr(cmd, " conf=sta-dpp")) {
conf_sta->akm = DPP_AKM_DPP;
} else {
goto fail;
}
if (os_strstr(cmd, " group_id=")) {
conf_sta->group_id = group_id;
group_id = NULL;
}
}
if (os_strstr(cmd, " conf=ap-")) {
conf_ap = os_zalloc(sizeof(struct dpp_configuration));
if (!conf_ap)
goto fail;
os_memcpy(conf_ap->ssid, ssid, ssid_len);
conf_ap->ssid_len = ssid_len;
if (os_strstr(cmd, " conf=ap-psk") ||
os_strstr(cmd, " conf=ap-sae") ||
os_strstr(cmd, " conf=ap-psk-sae")) {
if (os_strstr(cmd, " conf=ap-psk-sae"))
conf_ap->akm = DPP_AKM_PSK_SAE;
else if (os_strstr(cmd, " conf=ap-sae"))
conf_ap->akm = DPP_AKM_SAE;
else
conf_ap->akm = DPP_AKM_PSK;
if (psk_set) {
os_memcpy(conf_ap->psk, psk, PMK_LEN);
} else {
conf_ap->passphrase = os_strdup(pass);
if (!conf_ap->passphrase)
goto fail;
}
} else if (os_strstr(cmd, " conf=ap-dpp")) {
conf_ap->akm = DPP_AKM_DPP;
} else {
goto fail;
}
if (os_strstr(cmd, " group_id=")) {
conf_ap->group_id = group_id;
group_id = NULL;
}
}
pos = os_strstr(cmd, " expiry=");
if (pos) {
long int val;
pos += 8;
val = strtol(pos, NULL, 0);
if (val <= 0)
goto fail;
if (conf_sta)
conf_sta->netaccesskey_expiry = val;
if (conf_ap)
conf_ap->netaccesskey_expiry = val;
}
pos = os_strstr(cmd, " configurator=");
if (pos) {
pos += 14;
conf = dpp_configurator_get_id(wpa_s, atoi(pos));
if (!conf) {
auth->conf = dpp_configurator_get_id(wpa_s, atoi(pos));
if (!auth->conf) {
wpa_printf(MSG_INFO,
"DPP: Could not find the specified configurator");
goto fail;
return -1;
}
}
auth->conf_sta = conf_sta;
auth->conf_ap = conf_ap;
auth->conf = conf;
os_free(group_id);
return 0;
fail:
wpa_msg(wpa_s, MSG_INFO, "DPP: Failed to set configurator parameters");
dpp_configuration_free(conf_sta);
dpp_configuration_free(conf_ap);
os_free(group_id);
return -1;
if (dpp_configuration_parse(auth, cmd) < 0) {
wpa_msg(wpa_s, MSG_INFO,
"DPP: Failed to set configurator parameters");
return -1;
}
return 0;
}