WPS ER: Add command for configuring an AP
wps_er_config can now be used to configure an AP. It is similar to wps_er_learn, but instead of only learning the current AP settings, it continues to send M8 with the new settings for the AP.
This commit is contained in:
parent
3085b8052e
commit
7d6640a62c
7 changed files with 252 additions and 7 deletions
|
@ -737,6 +737,8 @@ void wps_er_set_sel_reg(struct wps_er *er, int sel_reg, u16 dev_passwd_id,
|
||||||
int wps_er_pbc(struct wps_er *er, const u8 *uuid);
|
int wps_er_pbc(struct wps_er *er, const u8 *uuid);
|
||||||
int wps_er_learn(struct wps_er *er, const u8 *uuid, const u8 *pin,
|
int wps_er_learn(struct wps_er *er, const u8 *uuid, const u8 *pin,
|
||||||
size_t pin_len);
|
size_t pin_len);
|
||||||
|
int wps_er_config(struct wps_er *er, const u8 *uuid, const u8 *pin,
|
||||||
|
size_t pin_len, const struct wps_credential *cred);
|
||||||
|
|
||||||
int wps_dev_type_str2bin(const char *str, u8 dev_type[WPS_DEV_TYPE_LEN]);
|
int wps_dev_type_str2bin(const char *str, u8 dev_type[WPS_DEV_TYPE_LEN]);
|
||||||
char * wps_dev_type_bin2str(const u8 dev_type[WPS_DEV_TYPE_LEN], char *buf,
|
char * wps_dev_type_bin2str(const u8 dev_type[WPS_DEV_TYPE_LEN], char *buf,
|
||||||
|
|
|
@ -1501,10 +1501,26 @@ static void wps_er_ap_put_message(struct wps_er_ap *ap,
|
||||||
static void wps_er_ap_process(struct wps_er_ap *ap, struct wpabuf *msg)
|
static void wps_er_ap_process(struct wps_er_ap *ap, struct wpabuf *msg)
|
||||||
{
|
{
|
||||||
enum wps_process_res res;
|
enum wps_process_res res;
|
||||||
|
struct wps_parse_attr attr;
|
||||||
res = wps_process_msg(ap->wps, WSC_MSG, msg);
|
|
||||||
if (res == WPS_CONTINUE) {
|
|
||||||
enum wsc_op_code op_code;
|
enum wsc_op_code op_code;
|
||||||
|
|
||||||
|
op_code = WSC_MSG;
|
||||||
|
if (wps_parse_msg(msg, &attr) == 0 && attr.msg_type) {
|
||||||
|
switch (*attr.msg_type) {
|
||||||
|
case WPS_WSC_ACK:
|
||||||
|
op_code = WSC_ACK;
|
||||||
|
break;
|
||||||
|
case WPS_WSC_NACK:
|
||||||
|
op_code = WSC_NACK;
|
||||||
|
break;
|
||||||
|
case WPS_WSC_DONE:
|
||||||
|
op_code = WSC_Done;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res = wps_process_msg(ap->wps, op_code, msg);
|
||||||
|
if (res == WPS_CONTINUE) {
|
||||||
struct wpabuf *next = wps_get_msg(ap->wps, &op_code);
|
struct wpabuf *next = wps_get_msg(ap->wps, &op_code);
|
||||||
if (next) {
|
if (next) {
|
||||||
wps_er_ap_put_message(ap, next);
|
wps_er_ap_put_message(ap, next);
|
||||||
|
@ -1675,3 +1691,64 @@ int wps_er_learn(struct wps_er *er, const u8 *uuid, const u8 *pin,
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void wps_er_ap_config_m1(struct wps_er_ap *ap, struct wpabuf *m1)
|
||||||
|
{
|
||||||
|
struct wps_config cfg;
|
||||||
|
|
||||||
|
if (ap->wps) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WPS ER: Protocol run already in "
|
||||||
|
"progress with this AP");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
os_memset(&cfg, 0, sizeof(cfg));
|
||||||
|
cfg.wps = ap->er->wps;
|
||||||
|
cfg.registrar = 1;
|
||||||
|
cfg.new_ap_settings = ap->ap_settings;
|
||||||
|
ap->wps = wps_init(&cfg);
|
||||||
|
if (ap->wps == NULL)
|
||||||
|
return;
|
||||||
|
ap->wps->ap_settings_cb = NULL;
|
||||||
|
ap->wps->ap_settings_cb_ctx = NULL;
|
||||||
|
|
||||||
|
wps_er_ap_process(ap, m1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wps_er_config(struct wps_er *er, const u8 *uuid, const u8 *pin,
|
||||||
|
size_t pin_len, const struct wps_credential *cred)
|
||||||
|
{
|
||||||
|
struct wps_er_ap *ap;
|
||||||
|
|
||||||
|
if (er == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ap = wps_er_ap_get(er, NULL, uuid);
|
||||||
|
if (ap == NULL) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WPS ER: AP not found for config "
|
||||||
|
"request");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (ap->wps) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WPS ER: Pending operation ongoing "
|
||||||
|
"with the AP - cannot start config");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
os_free(ap->ap_settings);
|
||||||
|
ap->ap_settings = os_malloc(sizeof(*cred));
|
||||||
|
if (ap->ap_settings == NULL)
|
||||||
|
return -1;
|
||||||
|
os_memcpy(ap->ap_settings, cred, sizeof(*cred));
|
||||||
|
ap->ap_settings->cred_attr = NULL;
|
||||||
|
|
||||||
|
if (wps_er_send_get_device_info(ap, wps_er_ap_config_m1) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* TODO: add PIN without SetSelectedRegistrar trigger to all APs */
|
||||||
|
wps_registrar_add_pin(er->wps->registrar, uuid, pin, pin_len, 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -236,6 +236,15 @@ wps_er_stop
|
||||||
wps_er_learn <UUID> <AP PIN>
|
wps_er_learn <UUID> <AP PIN>
|
||||||
- learn AP configuration
|
- learn AP configuration
|
||||||
|
|
||||||
|
wps_er_config <UUID> <AP PIN> <new SSID> <auth> <encr> <new key>
|
||||||
|
- examples:
|
||||||
|
wps_er_config 87654321-9abc-def0-1234-56789abc0002 12345670 testing WPA2PSK CCMP 12345678
|
||||||
|
wpa_er_config 87654321-9abc-def0-1234-56789abc0002 12345670 clear OPEN NONE ""
|
||||||
|
|
||||||
|
<auth> must be one of the following: OPEN WPAPSK WPA2PSK
|
||||||
|
<encr> must be one of the following: NONE WEP TKIP CCMP
|
||||||
|
|
||||||
|
|
||||||
wps_er_pbc <Enrollee UUID>
|
wps_er_pbc <Enrollee UUID>
|
||||||
- accept an Enrollee PBC using External Registrar
|
- accept an Enrollee PBC using External Registrar
|
||||||
|
|
||||||
|
|
|
@ -330,6 +330,50 @@ static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s,
|
||||||
*pin++ = '\0';
|
*pin++ = '\0';
|
||||||
return wpas_wps_er_learn(wpa_s, uuid, pin);
|
return wpas_wps_er_learn(wpa_s, uuid, pin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wpa_supplicant_ctrl_iface_wps_er_config(
|
||||||
|
struct wpa_supplicant *wpa_s, char *cmd)
|
||||||
|
{
|
||||||
|
char *pin;
|
||||||
|
char *new_ssid;
|
||||||
|
char *new_auth;
|
||||||
|
char *new_encr;
|
||||||
|
char *new_key;
|
||||||
|
struct wps_new_ap_settings ap;
|
||||||
|
|
||||||
|
pin = os_strchr(cmd, ' ');
|
||||||
|
if (pin == NULL)
|
||||||
|
return -1;
|
||||||
|
*pin++ = '\0';
|
||||||
|
|
||||||
|
new_ssid = os_strchr(pin, ' ');
|
||||||
|
if (new_ssid == NULL)
|
||||||
|
return -1;
|
||||||
|
*new_ssid++ = '\0';
|
||||||
|
|
||||||
|
new_auth = os_strchr(new_ssid, ' ');
|
||||||
|
if (new_auth == NULL)
|
||||||
|
return -1;
|
||||||
|
*new_auth++ = '\0';
|
||||||
|
|
||||||
|
new_encr = os_strchr(new_auth, ' ');
|
||||||
|
if (new_encr == NULL)
|
||||||
|
return -1;
|
||||||
|
*new_encr++ = '\0';
|
||||||
|
|
||||||
|
new_key = os_strchr(new_encr, ' ');
|
||||||
|
if (new_key == NULL)
|
||||||
|
return -1;
|
||||||
|
*new_key++ = '\0';
|
||||||
|
|
||||||
|
os_memset(&ap, 0, sizeof(ap));
|
||||||
|
ap.ssid_hex = new_ssid;
|
||||||
|
ap.auth = new_auth;
|
||||||
|
ap.encr = new_encr;
|
||||||
|
ap.key_hex = new_key;
|
||||||
|
return wpas_wps_er_config(wpa_s, cmd, pin, &ap);
|
||||||
|
}
|
||||||
#endif /* CONFIG_WPS_ER */
|
#endif /* CONFIG_WPS_ER */
|
||||||
|
|
||||||
#endif /* CONFIG_WPS */
|
#endif /* CONFIG_WPS */
|
||||||
|
@ -1810,6 +1854,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
|
||||||
} else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) {
|
} else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) {
|
||||||
if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13))
|
if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13))
|
||||||
reply_len = -1;
|
reply_len = -1;
|
||||||
|
} else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) {
|
||||||
|
if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14))
|
||||||
|
reply_len = -1;
|
||||||
#endif /* CONFIG_WPS_ER */
|
#endif /* CONFIG_WPS_ER */
|
||||||
#endif /* CONFIG_WPS */
|
#endif /* CONFIG_WPS */
|
||||||
#ifdef CONFIG_IBSS_RSN
|
#ifdef CONFIG_IBSS_RSN
|
||||||
|
|
|
@ -602,7 +602,7 @@ static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
||||||
if (argc == 2)
|
if (argc == 2)
|
||||||
res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
|
res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
|
||||||
argv[0], argv[1]);
|
argv[0], argv[1]);
|
||||||
else if (argc == 6) {
|
else if (argc == 5 || argc == 6) {
|
||||||
char ssid_hex[2 * 32 + 1];
|
char ssid_hex[2 * 32 + 1];
|
||||||
char key_hex[2 * 64 + 1];
|
char key_hex[2 * 64 + 1];
|
||||||
int i;
|
int i;
|
||||||
|
@ -615,10 +615,13 @@ static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
key_hex[0] = '\0';
|
key_hex[0] = '\0';
|
||||||
|
if (argc == 6) {
|
||||||
for (i = 0; i < 64; i++) {
|
for (i = 0; i < 64; i++) {
|
||||||
if (argv[5][i] == '\0')
|
if (argv[5][i] == '\0')
|
||||||
break;
|
break;
|
||||||
os_snprintf(&key_hex[i * 2], 3, "%02x", argv[5][i]);
|
os_snprintf(&key_hex[i * 2], 3, "%02x",
|
||||||
|
argv[5][i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res = os_snprintf(cmd, sizeof(cmd),
|
res = os_snprintf(cmd, sizeof(cmd),
|
||||||
|
@ -736,6 +739,57 @@ static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
|
||||||
|
char *argv[])
|
||||||
|
{
|
||||||
|
char cmd[256];
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if (argc == 5 || argc == 6) {
|
||||||
|
char ssid_hex[2 * 32 + 1];
|
||||||
|
char key_hex[2 * 64 + 1];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
ssid_hex[0] = '\0';
|
||||||
|
for (i = 0; i < 32; i++) {
|
||||||
|
if (argv[2][i] == '\0')
|
||||||
|
break;
|
||||||
|
os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
key_hex[0] = '\0';
|
||||||
|
if (argc == 6) {
|
||||||
|
for (i = 0; i < 64; i++) {
|
||||||
|
if (argv[5][i] == '\0')
|
||||||
|
break;
|
||||||
|
os_snprintf(&key_hex[i * 2], 3, "%02x",
|
||||||
|
argv[5][i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res = os_snprintf(cmd, sizeof(cmd),
|
||||||
|
"WPS_ER_CONFIG %s %s %s %s %s %s",
|
||||||
|
argv[0], argv[1], ssid_hex, argv[3], argv[4],
|
||||||
|
key_hex);
|
||||||
|
} else {
|
||||||
|
printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
|
||||||
|
"- AP UUID\n"
|
||||||
|
"- AP PIN\n"
|
||||||
|
"- new SSID\n"
|
||||||
|
"- new auth (OPEN, WPAPSK, WPA2PSK)\n"
|
||||||
|
"- new encr (NONE, WEP, TKIP, CCMP)\n"
|
||||||
|
"- new key\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
|
||||||
|
printf("Too long WPS_ER_CONFIG command.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return wpa_ctrl_command(ctrl, cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
||||||
{
|
{
|
||||||
char cmd[256];
|
char cmd[256];
|
||||||
|
@ -1647,6 +1701,9 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
|
||||||
{ "wps_er_learn", wpa_cli_cmd_wps_er_learn,
|
{ "wps_er_learn", wpa_cli_cmd_wps_er_learn,
|
||||||
cli_cmd_flag_sensitive,
|
cli_cmd_flag_sensitive,
|
||||||
"<UUID> <PIN> = learn AP configuration" },
|
"<UUID> <PIN> = learn AP configuration" },
|
||||||
|
{ "wps_er_config", wpa_cli_cmd_wps_er_config,
|
||||||
|
cli_cmd_flag_sensitive,
|
||||||
|
"<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
|
||||||
{ "ibss_rsn", wpa_cli_cmd_ibss_rsn,
|
{ "ibss_rsn", wpa_cli_cmd_ibss_rsn,
|
||||||
cli_cmd_flag_none,
|
cli_cmd_flag_none,
|
||||||
"<addr> = request RSN authentication with <addr> in IBSS" },
|
"<addr> = request RSN authentication with <addr> in IBSS" },
|
||||||
|
|
|
@ -1194,6 +1194,57 @@ int wpas_wps_er_learn(struct wpa_supplicant *wpa_s, const char *uuid,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wpas_wps_er_config(struct wpa_supplicant *wpa_s, const char *uuid,
|
||||||
|
const char *pin, struct wps_new_ap_settings *settings)
|
||||||
|
{
|
||||||
|
u8 u[UUID_LEN];
|
||||||
|
struct wps_credential cred;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (uuid_str2bin(uuid, u))
|
||||||
|
return -1;
|
||||||
|
if (settings->ssid_hex == NULL || settings->auth == NULL ||
|
||||||
|
settings->encr == NULL || settings->key_hex == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
os_memset(&cred, 0, sizeof(cred));
|
||||||
|
len = os_strlen(settings->ssid_hex);
|
||||||
|
if ((len & 1) || len > 2 * sizeof(cred.ssid) ||
|
||||||
|
hexstr2bin(settings->ssid_hex, cred.ssid, len / 2))
|
||||||
|
return -1;
|
||||||
|
cred.ssid_len = len / 2;
|
||||||
|
|
||||||
|
len = os_strlen(settings->key_hex);
|
||||||
|
if ((len & 1) || len > 2 * sizeof(cred.key) ||
|
||||||
|
hexstr2bin(settings->key_hex, cred.key, len / 2))
|
||||||
|
return -1;
|
||||||
|
cred.key_len = len / 2;
|
||||||
|
|
||||||
|
if (os_strcmp(settings->auth, "OPEN") == 0)
|
||||||
|
cred.auth_type = WPS_AUTH_OPEN;
|
||||||
|
else if (os_strcmp(settings->auth, "WPAPSK") == 0)
|
||||||
|
cred.auth_type = WPS_AUTH_WPAPSK;
|
||||||
|
else if (os_strcmp(settings->auth, "WPA2PSK") == 0)
|
||||||
|
cred.auth_type = WPS_AUTH_WPA2PSK;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (os_strcmp(settings->encr, "NONE") == 0)
|
||||||
|
cred.encr_type = WPS_ENCR_NONE;
|
||||||
|
else if (os_strcmp(settings->encr, "WEP") == 0)
|
||||||
|
cred.encr_type = WPS_ENCR_WEP;
|
||||||
|
else if (os_strcmp(settings->encr, "TKIP") == 0)
|
||||||
|
cred.encr_type = WPS_ENCR_TKIP;
|
||||||
|
else if (os_strcmp(settings->encr, "CCMP") == 0)
|
||||||
|
cred.encr_type = WPS_ENCR_AES;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return wps_er_config(wpa_s->wps_er, u, (const u8 *) pin,
|
||||||
|
os_strlen(pin), &cred);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void wpas_wps_terminate_cb(void *ctx)
|
static void wpas_wps_terminate_cb(void *ctx)
|
||||||
{
|
{
|
||||||
wpa_printf(MSG_DEBUG, "WPS ER: Terminated");
|
wpa_printf(MSG_DEBUG, "WPS ER: Terminated");
|
||||||
|
|
|
@ -59,6 +59,8 @@ int wpas_wps_er_add_pin(struct wpa_supplicant *wpa_s, const char *uuid,
|
||||||
int wpas_wps_er_pbc(struct wpa_supplicant *wpa_s, const char *uuid);
|
int wpas_wps_er_pbc(struct wpa_supplicant *wpa_s, const char *uuid);
|
||||||
int wpas_wps_er_learn(struct wpa_supplicant *wpa_s, const char *uuid,
|
int wpas_wps_er_learn(struct wpa_supplicant *wpa_s, const char *uuid,
|
||||||
const char *pin);
|
const char *pin);
|
||||||
|
int wpas_wps_er_config(struct wpa_supplicant *wpa_s, const char *uuid,
|
||||||
|
const char *pin, struct wps_new_ap_settings *settings);
|
||||||
int wpas_wps_terminate_pending(struct wpa_supplicant *wpa_s);
|
int wpas_wps_terminate_pending(struct wpa_supplicant *wpa_s);
|
||||||
|
|
||||||
#else /* CONFIG_WPS */
|
#else /* CONFIG_WPS */
|
||||||
|
|
Loading…
Reference in a new issue