hostapd: Add wps_config ctrl_interface command for configuring AP

This command can be used to configure the AP using the internal
WPS registrar. It works in the same way as new AP settings received
from an ER.
This commit is contained in:
Jouni Malinen 2010-10-21 16:49:41 +03:00 committed by Jouni Malinen
parent 7374b68ee9
commit 450eddcfae
7 changed files with 177 additions and 0 deletions

View file

@ -239,6 +239,14 @@ hostapd_cli wps_ap_pin set <PIN> [timeout]
hostapd_cli get_config
- display the current configuration
hostapd_cli wps_config <new SSID> <auth> <encr> <new key>
examples:
hostapd_cli wps_config testing WPA2PSK CCMP 12345678
hostapd_cli wps_config "no security" OPEN NONE ""
<auth> must be one of the following: OPEN WPAPSK WPA2PSK
<encr> must be one of the following: NONE WEP TKIP CCMP
Credential generation and configuration changes
-----------------------------------------------

View file

@ -490,6 +490,33 @@ static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data *hapd, char *txt,
return -1;
}
static int hostapd_ctrl_iface_wps_config(struct hostapd_data *hapd, char *txt)
{
char *pos;
char *ssid, *auth, *encr = NULL, *key = NULL;
ssid = txt;
pos = os_strchr(txt, ' ');
if (!pos)
return -1;
*pos++ = '\0';
auth = pos;
pos = os_strchr(pos, ' ');
if (pos) {
*pos++ = '\0';
encr = pos;
pos = os_strchr(pos, ' ');
if (pos) {
*pos++ = '\0';
key = pos;
}
}
return hostapd_wps_config_ap(hapd, ssid, auth, encr, key);
}
#endif /* CONFIG_WPS */
@ -821,6 +848,9 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
} else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11,
reply, reply_size);
} else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) {
if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0)
reply_len = -1;
#endif /* CONFIG_WPS */
} else if (os_strcmp(buf, "GET_CONFIG") == 0) {
reply_len = hostapd_ctrl_iface_get_config(hapd, reply,

View file

@ -96,6 +96,7 @@ static const char *commands_help =
" wps_oob <type> <path> <method> use WPS with out-of-band (UFD)\n"
#endif /* CONFIG_WPS_OOB */
" wps_ap_pin <cmd> [params..] enable/disable AP PIN\n"
" wps_config <SSID> <auth> <encr> <key> configure AP\n"
#endif /* CONFIG_WPS */
" get_config show current configuration\n"
" help show this usage help\n"
@ -458,6 +459,50 @@ static int hostapd_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
snprintf(buf, sizeof(buf), "WPS_AP_PIN %s", argv[0]);
return wpa_ctrl_command(ctrl, buf);
}
static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
char buf[256];
char ssid_hex[2 * 32 + 1];
char key_hex[2 * 64 + 1];
int i;
if (argc < 1) {
printf("Invalid 'wps_config' command - at least two arguments "
"are required.\n");
return -1;
}
ssid_hex[0] = '\0';
for (i = 0; i < 32; i++) {
if (argv[0][i] == '\0')
break;
os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[0][i]);
}
key_hex[0] = '\0';
if (argc > 3) {
for (i = 0; i < 64; i++) {
if (argv[3][i] == '\0')
break;
os_snprintf(&key_hex[i * 2], 3, "%02x",
argv[3][i]);
}
}
if (argc > 3)
snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s %s",
ssid_hex, argv[1], argv[2], key_hex);
else if (argc > 2)
snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s",
ssid_hex, argv[1], argv[2]);
else
snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s",
ssid_hex, argv[1]);
return wpa_ctrl_command(ctrl, buf);
}
#endif /* CONFIG_WPS */
@ -649,6 +694,7 @@ static struct hostapd_cli_cmd hostapd_cli_commands[] = {
{ "wps_oob", hostapd_cli_cmd_wps_oob },
#endif /* CONFIG_WPS_OOB */
{ "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin },
{ "wps_config", hostapd_cli_cmd_wps_config },
#endif /* CONFIG_WPS */
{ "get_config", hostapd_cli_cmd_get_config },
{ "help", hostapd_cli_cmd_help },

View file

@ -1286,3 +1286,52 @@ void hostapd_wps_update_ie(struct hostapd_data *hapd)
{
hostapd_wps_for_each(hapd, wps_update_ie, NULL);
}
int hostapd_wps_config_ap(struct hostapd_data *hapd, const char *ssid,
const char *auth, const char *encr, const char *key)
{
struct wps_credential cred;
size_t len;
os_memset(&cred, 0, sizeof(cred));
len = os_strlen(ssid);
if ((len & 1) || len > 2 * sizeof(cred.ssid) ||
hexstr2bin(ssid, cred.ssid, len / 2))
return -1;
cred.ssid_len = len / 2;
if (os_strncmp(auth, "OPEN", 4) == 0)
cred.auth_type = WPS_AUTH_OPEN;
else if (os_strncmp(auth, "WPAPSK", 6) == 0)
cred.auth_type = WPS_AUTH_WPAPSK;
else if (os_strncmp(auth, "WPA2PSK", 7) == 0)
cred.auth_type = WPS_AUTH_WPA2PSK;
else
return -1;
if (encr) {
if (os_strncmp(encr, "NONE", 4) == 0)
cred.encr_type = WPS_ENCR_NONE;
else if (os_strncmp(encr, "WEP", 3) == 0)
cred.encr_type = WPS_ENCR_WEP;
else if (os_strncmp(encr, "TKIP", 4) == 0)
cred.encr_type = WPS_ENCR_TKIP;
else if (os_strncmp(encr, "CCMP", 4) == 0)
cred.encr_type = WPS_ENCR_AES;
else
return -1;
} else
cred.encr_type = WPS_ENCR_NONE;
if (key) {
len = os_strlen(key);
if ((len & 1) || len > 2 * sizeof(cred.key) ||
hexstr2bin(key, cred.key, len / 2))
return -1;
cred.key_len = len / 2;
}
return wps_registrar_config_ap(hapd->wps->registrar, &cred);
}

View file

@ -34,6 +34,8 @@ const char * hostapd_wps_ap_pin_get(struct hostapd_data *hapd);
int hostapd_wps_ap_pin_set(struct hostapd_data *hapd, const char *pin,
int timeout);
void hostapd_wps_update_ie(struct hostapd_data *hapd);
int hostapd_wps_config_ap(struct hostapd_data *hapd, const char *ssid,
const char *auth, const char *encr, const char *key);
#else /* CONFIG_WPS */

View file

@ -736,6 +736,8 @@ void wps_registrar_probe_req_rx(struct wps_registrar *reg, const u8 *addr,
int wps_registrar_update_ie(struct wps_registrar *reg);
int wps_registrar_get_info(struct wps_registrar *reg, const u8 *addr,
char *buf, size_t buflen);
int wps_registrar_config_ap(struct wps_registrar *reg,
struct wps_credential *cred);
unsigned int wps_pin_checksum(unsigned int pin);
unsigned int wps_pin_valid(unsigned int pin);

View file

@ -3161,3 +3161,43 @@ int wps_registrar_get_info(struct wps_registrar *reg, const u8 *addr,
return len;
}
int wps_registrar_config_ap(struct wps_registrar *reg,
struct wps_credential *cred)
{
#ifdef CONFIG_WPS2
printf("encr_type=0x%x\n", cred->encr_type);
if (!(cred->encr_type & (WPS_ENCR_NONE | WPS_ENCR_TKIP |
WPS_ENCR_AES))) {
if (cred->encr_type & WPS_ENCR_WEP) {
wpa_printf(MSG_INFO, "WPS: Reject new AP settings "
"due to WEP configuration");
return -1;
}
wpa_printf(MSG_INFO, "WPS: Reject new AP settings due to "
"invalid encr_type 0x%x", cred->encr_type);
return -1;
}
if ((cred->encr_type & (WPS_ENCR_TKIP | WPS_ENCR_AES)) ==
WPS_ENCR_TKIP) {
wpa_printf(MSG_DEBUG, "WPS: Upgrade encr_type TKIP -> "
"TKIP+AES");
cred->encr_type |= WPS_ENCR_AES;
}
if ((cred->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) ==
WPS_AUTH_WPAPSK) {
wpa_printf(MSG_DEBUG, "WPS: Upgrade auth_type WPAPSK -> "
"WPAPSK+WPA2PSK");
cred->auth_type |= WPS_AUTH_WPA2PSK;
}
#endif /* CONFIG_WPS2 */
if (reg->wps->cred_cb)
return reg->wps->cred_cb(reg->wps->cb_ctx, cred);
return -1;
}