diff --git a/src/wps/wps.h b/src/wps/wps.h index a4b732308..beb21b64a 100644 --- a/src/wps/wps.h +++ b/src/wps/wps.h @@ -758,6 +758,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_learn(struct wps_er *er, const u8 *uuid, const u8 *pin, size_t pin_len); +int wps_er_set_config(struct wps_er *er, const u8 *uuid, + const struct wps_credential *cred); int wps_er_config(struct wps_er *er, const u8 *uuid, const u8 *pin, size_t pin_len, const struct wps_credential *cred); diff --git a/src/wps/wps_er.c b/src/wps/wps_er.c index f573d625a..473cfc315 100644 --- a/src/wps/wps_er.c +++ b/src/wps/wps_er.c @@ -1738,6 +1738,34 @@ int wps_er_learn(struct wps_er *er, const u8 *uuid, const u8 *pin, } +int wps_er_set_config(struct wps_er *er, const u8 *uuid, + 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 set config " + "request"); + 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; + wpa_printf(MSG_DEBUG, "WPS ER: Updated local AP settings based set " + "config request"); + + return 0; +} + + static void wps_er_ap_config_m1(struct wps_er_ap *ap, struct wpabuf *m1) { struct wps_config cfg; diff --git a/wpa_supplicant/README-WPS b/wpa_supplicant/README-WPS index e866eb035..6aa3a7be3 100644 --- a/wpa_supplicant/README-WPS +++ b/wpa_supplicant/README-WPS @@ -244,6 +244,12 @@ wps_er_stop wps_er_learn - learn AP configuration +wps_er_set_config +- use AP configuration from a locally configured network (e.g., from + wps_reg command); this does not change the AP's configuration, but + only prepares a configuration to be used when enrolling a new device + to the AP + wps_er_config - examples: wps_er_config 87654321-9abc-def0-1234-56789abc0002 12345670 testing WPA2PSK CCMP 12345678 diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 75c78ee0a..339eb9bff 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -416,6 +416,18 @@ static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s, } +static int wpa_supplicant_ctrl_iface_wps_er_set_config( + struct wpa_supplicant *wpa_s, char *cmd) +{ + char *uuid = cmd, *id; + id = os_strchr(uuid, ' '); + if (id == NULL) + return -1; + *id++ = '\0'; + return wpas_wps_er_set_config(wpa_s, uuid, atoi(id)); +} + + static int wpa_supplicant_ctrl_iface_wps_er_config( struct wpa_supplicant *wpa_s, char *cmd) { @@ -2804,6 +2816,10 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, } else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) { if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13)) reply_len = -1; + } else if (os_strncmp(buf, "WPS_ER_SET_CONFIG ", 18) == 0) { + if (wpa_supplicant_ctrl_iface_wps_er_set_config(wpa_s, + buf + 18)) + 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; diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index 587b8af0e..5e355a56f 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -832,6 +832,30 @@ static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc, } +static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char cmd[256]; + int res; + + if (argc != 2) { + printf("Invalid WPS_ER_SET_CONFIG command: need two " + "arguments:\n" + "- UUID: specify which AP to use\n" + "- Network configuration id\n"); + return -1; + } + + res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_SET_CONFIG %s %s", + argv[0], argv[1]); + if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { + printf("Too long WPS_ER_SET_CONFIG command.\n"); + return -1; + } + return wpa_ctrl_command(ctrl, cmd); +} + + static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc, char *argv[]) { @@ -2332,6 +2356,9 @@ static struct wpa_cli_cmd wpa_cli_commands[] = { { "wps_er_learn", wpa_cli_cmd_wps_er_learn, cli_cmd_flag_sensitive, " = learn AP configuration" }, + { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, + cli_cmd_flag_none, + " = set AP configuration for enrolling" }, { "wps_er_config", wpa_cli_cmd_wps_er_config, cli_cmd_flag_sensitive, " = configure AP" }, diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c index af8c4c424..bc8dc420f 100644 --- a/wpa_supplicant/wps_supplicant.c +++ b/wpa_supplicant/wps_supplicant.c @@ -1362,6 +1362,49 @@ int wpas_wps_er_learn(struct wpa_supplicant *wpa_s, const char *uuid, } +int wpas_wps_er_set_config(struct wpa_supplicant *wpa_s, const char *uuid, + int id) +{ + u8 u[UUID_LEN]; + struct wpa_ssid *ssid; + struct wps_credential cred; + + if (uuid_str2bin(uuid, u)) + return -1; + ssid = wpa_config_get_network(wpa_s->conf, id); + if (ssid == NULL || ssid->ssid == NULL) + return -1; + + os_memset(&cred, 0, sizeof(cred)); + if (ssid->ssid_len > 32) + return -1; + os_memcpy(cred.ssid, ssid->ssid, ssid->ssid_len); + cred.ssid_len = ssid->ssid_len; + if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) { + cred.auth_type = (ssid->proto & WPA_PROTO_RSN) ? + WPS_AUTH_WPA2PSK : WPS_AUTH_WPAPSK; + if (ssid->pairwise_cipher & WPA_CIPHER_CCMP) + cred.encr_type = WPS_ENCR_AES; + else + cred.encr_type = WPS_ENCR_TKIP; + if (ssid->passphrase) { + cred.key_len = os_strlen(ssid->passphrase); + if (cred.key_len >= 64) + return -1; + os_memcpy(cred.key, ssid->passphrase, cred.key_len); + } else if (ssid->psk_set) { + cred.key_len = 32; + os_memcpy(cred.key, ssid->psk, 32); + } else + return -1; + } else { + cred.auth_type = WPS_AUTH_OPEN; + cred.encr_type = WPS_ENCR_NONE; + } + return wps_er_set_config(wpa_s->wps_er, u, &cred); +} + + int wpas_wps_er_config(struct wpa_supplicant *wpa_s, const char *uuid, const char *pin, struct wps_new_ap_settings *settings) { diff --git a/wpa_supplicant/wps_supplicant.h b/wpa_supplicant/wps_supplicant.h index ce1776f19..b38c091dd 100644 --- a/wpa_supplicant/wps_supplicant.h +++ b/wpa_supplicant/wps_supplicant.h @@ -61,6 +61,8 @@ int wpas_wps_er_add_pin(struct wpa_supplicant *wpa_s, const u8 *addr, 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, const char *pin); +int wpas_wps_er_set_config(struct wpa_supplicant *wpa_s, const char *uuid, + int id); 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);