WPS: Store device info and make it available through AP ctrl_iface
Store a copy of device attributes during WPS protocol run and make it available for external programs via the control interface STA MIB command for associated stations. This gives access to device name and type which can be useful when showing user information about associated stations.
This commit is contained in:
parent
52eb293dd2
commit
2678509dec
13 changed files with 170 additions and 1 deletions
|
@ -155,6 +155,10 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
|
||||||
res = ieee802_1x_get_mib_sta(hapd, sta, buf + len, buflen - len);
|
res = ieee802_1x_get_mib_sta(hapd, sta, buf + len, buflen - len);
|
||||||
if (res >= 0)
|
if (res >= 0)
|
||||||
len += res;
|
len += res;
|
||||||
|
res = hostapd_wps_get_mib_sta(hapd, sta->addr, buf + len,
|
||||||
|
buflen - len);
|
||||||
|
if (res >= 0)
|
||||||
|
len += res;
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
|
@ -828,6 +828,7 @@ eapol_auth_alloc(struct eapol_authenticator *eapol, const u8 *addr,
|
||||||
eap_conf.tnc = eapol->conf.tnc;
|
eap_conf.tnc = eapol->conf.tnc;
|
||||||
eap_conf.wps = eapol->conf.wps;
|
eap_conf.wps = eapol->conf.wps;
|
||||||
eap_conf.assoc_wps_ie = sta->wps_ie;
|
eap_conf.assoc_wps_ie = sta->wps_ie;
|
||||||
|
eap_conf.peer_addr = addr;
|
||||||
sm->eap = eap_server_sm_init(sm, &eapol_cb, &eap_conf);
|
sm->eap = eap_server_sm_init(sm, &eapol_cb, &eap_conf);
|
||||||
if (sm->eap == NULL) {
|
if (sm->eap == NULL) {
|
||||||
eapol_auth_free(sm);
|
eapol_auth_free(sm);
|
||||||
|
|
|
@ -1092,3 +1092,10 @@ static void hostapd_wps_upnp_deinit(struct hostapd_data *hapd)
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_WPS_UPNP */
|
#endif /* CONFIG_WPS_UPNP */
|
||||||
|
|
||||||
|
|
||||||
|
int hostapd_wps_get_mib_sta(struct hostapd_data *hapd, const u8 *addr,
|
||||||
|
char *buf, size_t buflen)
|
||||||
|
{
|
||||||
|
return wps_registrar_get_info(hapd->wps->registrar, addr, buf, buflen);
|
||||||
|
}
|
||||||
|
|
|
@ -25,6 +25,8 @@ int hostapd_wps_add_pin(struct hostapd_data *hapd, const char *uuid,
|
||||||
int hostapd_wps_button_pushed(struct hostapd_data *hapd);
|
int hostapd_wps_button_pushed(struct hostapd_data *hapd);
|
||||||
int hostapd_wps_start_oob(struct hostapd_data *hapd, char *device_type,
|
int hostapd_wps_start_oob(struct hostapd_data *hapd, char *device_type,
|
||||||
char *path, char *method, char *name);
|
char *path, char *method, char *name);
|
||||||
|
int hostapd_wps_get_mib_sta(struct hostapd_data *hapd, const u8 *addr,
|
||||||
|
char *buf, size_t buflen);
|
||||||
|
|
||||||
#else /* CONFIG_WPS */
|
#else /* CONFIG_WPS */
|
||||||
|
|
||||||
|
@ -38,6 +40,13 @@ static inline void hostapd_deinit_wps(struct hostapd_data *hapd)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int hostapd_wps_get_mib_sta(struct hostapd_data *hapd,
|
||||||
|
const u8 *addr,
|
||||||
|
char *buf, size_t buflen)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_WPS */
|
#endif /* CONFIG_WPS */
|
||||||
|
|
||||||
#endif /* WPS_HOSTAPD_H */
|
#endif /* WPS_HOSTAPD_H */
|
||||||
|
|
|
@ -1238,6 +1238,8 @@ struct eap_sm * eap_server_sm_init(void *eapol_ctx,
|
||||||
sm->wps = conf->wps;
|
sm->wps = conf->wps;
|
||||||
if (conf->assoc_wps_ie)
|
if (conf->assoc_wps_ie)
|
||||||
sm->assoc_wps_ie = wpabuf_dup(conf->assoc_wps_ie);
|
sm->assoc_wps_ie = wpabuf_dup(conf->assoc_wps_ie);
|
||||||
|
if (conf->peer_addr)
|
||||||
|
os_memcpy(sm->peer_addr, conf->peer_addr, ETH_ALEN);
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "EAP: Server state machine created");
|
wpa_printf(MSG_DEBUG, "EAP: Server state machine created");
|
||||||
|
|
||||||
|
|
|
@ -105,6 +105,7 @@ struct eap_config {
|
||||||
int tnc;
|
int tnc;
|
||||||
struct wps_context *wps;
|
struct wps_context *wps;
|
||||||
const struct wpabuf *assoc_wps_ie;
|
const struct wpabuf *assoc_wps_ie;
|
||||||
|
const u8 *peer_addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -185,6 +185,8 @@ struct eap_sm {
|
||||||
struct wpabuf *assoc_wps_ie;
|
struct wpabuf *assoc_wps_ie;
|
||||||
|
|
||||||
Boolean start_reauth;
|
Boolean start_reauth;
|
||||||
|
|
||||||
|
u8 peer_addr[ETH_ALEN];
|
||||||
};
|
};
|
||||||
|
|
||||||
int eap_user_get(struct eap_sm *sm, const u8 *identity, size_t identity_len,
|
int eap_user_get(struct eap_sm *sm, const u8 *identity, size_t identity_len,
|
||||||
|
|
|
@ -126,6 +126,7 @@ static void * eap_wsc_init(struct eap_sm *sm)
|
||||||
cfg.pin_len = sm->user->password_len;
|
cfg.pin_len = sm->user->password_len;
|
||||||
}
|
}
|
||||||
cfg.assoc_wps_ie = sm->assoc_wps_ie;
|
cfg.assoc_wps_ie = sm->assoc_wps_ie;
|
||||||
|
cfg.peer_addr = sm->peer_addr;
|
||||||
data->wps = wps_init(&cfg);
|
data->wps = wps_init(&cfg);
|
||||||
if (data->wps == NULL) {
|
if (data->wps == NULL) {
|
||||||
os_free(data);
|
os_free(data);
|
||||||
|
|
|
@ -100,6 +100,9 @@ struct wps_data * wps_init(const struct wps_config *cfg)
|
||||||
sizeof(*data->new_ap_settings));
|
sizeof(*data->new_ap_settings));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cfg->peer_addr)
|
||||||
|
os_memcpy(data->peer_dev.mac_addr, cfg->peer_addr, ETH_ALEN);
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -142,6 +142,11 @@ struct wps_config {
|
||||||
* current AP settings by using AP PIN.
|
* current AP settings by using AP PIN.
|
||||||
*/
|
*/
|
||||||
const struct wps_credential *new_ap_settings;
|
const struct wps_credential *new_ap_settings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* peer_addr: MAC address of the peer in AP; %NULL if not AP
|
||||||
|
*/
|
||||||
|
const u8 *peer_addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wps_data * wps_init(const struct wps_config *cfg);
|
struct wps_data * wps_init(const struct wps_config *cfg);
|
||||||
|
@ -571,6 +576,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_update_ie(struct wps_registrar *reg);
|
||||||
int wps_registrar_set_selected_registrar(struct wps_registrar *reg,
|
int wps_registrar_set_selected_registrar(struct wps_registrar *reg,
|
||||||
const struct wpabuf *msg);
|
const struct wpabuf *msg);
|
||||||
|
int wps_registrar_get_info(struct wps_registrar *reg, const u8 *addr,
|
||||||
|
char *buf, size_t buflen);
|
||||||
|
|
||||||
unsigned int wps_pin_checksum(unsigned int pin);
|
unsigned int wps_pin_checksum(unsigned int pin);
|
||||||
unsigned int wps_pin_valid(unsigned int pin);
|
unsigned int wps_pin_valid(unsigned int pin);
|
||||||
|
|
|
@ -328,6 +328,16 @@ static struct wpabuf * wps_build_m7(struct wps_data *wps)
|
||||||
}
|
}
|
||||||
wpabuf_free(plain);
|
wpabuf_free(plain);
|
||||||
|
|
||||||
|
if (wps->wps->ap && wps->wps->registrar) {
|
||||||
|
/*
|
||||||
|
* If the Registrar is only learning our current configuration,
|
||||||
|
* it may not continue protocol run to successful completion.
|
||||||
|
* Store information here to make sure it remains available.
|
||||||
|
*/
|
||||||
|
wps_device_store(wps->wps->registrar, &wps->peer_dev,
|
||||||
|
wps->uuid_r);
|
||||||
|
}
|
||||||
|
|
||||||
wps->state = RECV_M8;
|
wps->state = RECV_M8;
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
@ -751,7 +761,8 @@ static enum wps_process_res wps_process_m2(struct wps_data *wps,
|
||||||
wps_process_enrollee_nonce(wps, attr->enrollee_nonce) ||
|
wps_process_enrollee_nonce(wps, attr->enrollee_nonce) ||
|
||||||
wps_process_uuid_r(wps, attr->uuid_r) ||
|
wps_process_uuid_r(wps, attr->uuid_r) ||
|
||||||
wps_process_pubkey(wps, attr->public_key, attr->public_key_len) ||
|
wps_process_pubkey(wps, attr->public_key, attr->public_key_len) ||
|
||||||
wps_process_authenticator(wps, attr->authenticator, msg)) {
|
wps_process_authenticator(wps, attr->authenticator, msg) ||
|
||||||
|
wps_process_device_attrs(&wps->peer_dev, attr)) {
|
||||||
wps->state = SEND_WSC_NACK;
|
wps->state = SEND_WSC_NACK;
|
||||||
return WPS_CONTINUE;
|
return WPS_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -247,6 +247,8 @@ enum wps_process_res wps_registrar_process_msg(struct wps_data *wps,
|
||||||
enum wsc_op_code op_code,
|
enum wsc_op_code op_code,
|
||||||
const struct wpabuf *msg);
|
const struct wpabuf *msg);
|
||||||
int wps_build_cred(struct wps_data *wps, struct wpabuf *msg);
|
int wps_build_cred(struct wps_data *wps, struct wpabuf *msg);
|
||||||
|
int wps_device_store(struct wps_registrar *reg,
|
||||||
|
struct wps_device_data *dev, const u8 *uuid);
|
||||||
|
|
||||||
/* ndef.c */
|
/* ndef.c */
|
||||||
struct wpabuf * ndef_parse_wifi(struct wpabuf *buf);
|
struct wpabuf * ndef_parse_wifi(struct wpabuf *buf);
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "wps_dev_attr.h"
|
#include "wps_dev_attr.h"
|
||||||
#include "wps_upnp.h"
|
#include "wps_upnp.h"
|
||||||
#include "crypto.h"
|
#include "crypto.h"
|
||||||
|
#include "uuid.h"
|
||||||
|
|
||||||
#define WPS_WORKAROUNDS
|
#define WPS_WORKAROUNDS
|
||||||
|
|
||||||
|
@ -79,6 +80,13 @@ static void wps_free_pbc_sessions(struct wps_pbc_session *pbc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct wps_registrar_device {
|
||||||
|
struct wps_registrar_device *next;
|
||||||
|
struct wps_device_data dev;
|
||||||
|
u8 uuid[WPS_UUID_LEN];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct wps_registrar {
|
struct wps_registrar {
|
||||||
struct wps_context *wps;
|
struct wps_context *wps;
|
||||||
|
|
||||||
|
@ -104,6 +112,8 @@ struct wps_registrar {
|
||||||
int sel_reg_dev_password_id_override;
|
int sel_reg_dev_password_id_override;
|
||||||
int sel_reg_config_methods_override;
|
int sel_reg_config_methods_override;
|
||||||
int static_wep_only;
|
int static_wep_only;
|
||||||
|
|
||||||
|
struct wps_registrar_device *devices;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -113,6 +123,74 @@ static void wps_registrar_set_selected_timeout(void *eloop_ctx,
|
||||||
void *timeout_ctx);
|
void *timeout_ctx);
|
||||||
|
|
||||||
|
|
||||||
|
static void wps_free_devices(struct wps_registrar_device *dev)
|
||||||
|
{
|
||||||
|
struct wps_registrar_device *prev;
|
||||||
|
|
||||||
|
while (dev) {
|
||||||
|
prev = dev;
|
||||||
|
dev = dev->next;
|
||||||
|
wps_device_data_free(&prev->dev);
|
||||||
|
os_free(prev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct wps_registrar_device * wps_device_get(struct wps_registrar *reg,
|
||||||
|
const u8 *addr)
|
||||||
|
{
|
||||||
|
struct wps_registrar_device *dev;
|
||||||
|
|
||||||
|
for (dev = reg->devices; dev; dev = dev->next) {
|
||||||
|
if (os_memcmp(dev->dev.mac_addr, addr, ETH_ALEN) == 0)
|
||||||
|
return dev;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void wps_device_clone_data(struct wps_device_data *dst,
|
||||||
|
struct wps_device_data *src)
|
||||||
|
{
|
||||||
|
os_memcpy(dst->mac_addr, src->mac_addr, ETH_ALEN);
|
||||||
|
dst->categ = src->categ;
|
||||||
|
dst->oui = src->oui;
|
||||||
|
dst->sub_categ = src->sub_categ;
|
||||||
|
|
||||||
|
#define WPS_STRDUP(n) \
|
||||||
|
os_free(dst->n); \
|
||||||
|
dst->n = src->n ? os_strdup(src->n) : NULL
|
||||||
|
|
||||||
|
WPS_STRDUP(device_name);
|
||||||
|
WPS_STRDUP(manufacturer);
|
||||||
|
WPS_STRDUP(model_name);
|
||||||
|
WPS_STRDUP(model_number);
|
||||||
|
WPS_STRDUP(serial_number);
|
||||||
|
#undef WPS_STRDUP
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wps_device_store(struct wps_registrar *reg,
|
||||||
|
struct wps_device_data *dev, const u8 *uuid)
|
||||||
|
{
|
||||||
|
struct wps_registrar_device *d;
|
||||||
|
|
||||||
|
d = wps_device_get(reg, dev->mac_addr);
|
||||||
|
if (d == NULL) {
|
||||||
|
d = os_zalloc(sizeof(*d));
|
||||||
|
if (d == NULL)
|
||||||
|
return -1;
|
||||||
|
d->next = reg->devices;
|
||||||
|
reg->devices = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
wps_device_clone_data(&d->dev, dev);
|
||||||
|
os_memcpy(d->uuid, uuid, WPS_UUID_LEN);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void wps_registrar_add_pbc_session(struct wps_registrar *reg,
|
static void wps_registrar_add_pbc_session(struct wps_registrar *reg,
|
||||||
const u8 *addr, const u8 *uuid_e)
|
const u8 *addr, const u8 *uuid_e)
|
||||||
{
|
{
|
||||||
|
@ -406,6 +484,7 @@ void wps_registrar_deinit(struct wps_registrar *reg)
|
||||||
wps_free_pins(reg->pins);
|
wps_free_pins(reg->pins);
|
||||||
wps_free_pbc_sessions(reg->pbc_sessions);
|
wps_free_pbc_sessions(reg->pbc_sessions);
|
||||||
wpabuf_free(reg->extra_cred);
|
wpabuf_free(reg->extra_cred);
|
||||||
|
wps_free_devices(reg->devices);
|
||||||
os_free(reg);
|
os_free(reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2401,6 +2480,8 @@ static enum wps_process_res wps_process_wsc_done(struct wps_data *wps,
|
||||||
if (wps->wps->wps_upnp && wps->ext_reg) {
|
if (wps->wps->wps_upnp && wps->ext_reg) {
|
||||||
wpa_printf(MSG_DEBUG, "WPS: Negotiation using external "
|
wpa_printf(MSG_DEBUG, "WPS: Negotiation using external "
|
||||||
"Registrar completed successfully");
|
"Registrar completed successfully");
|
||||||
|
wps_device_store(wps->wps->registrar, &wps->peer_dev,
|
||||||
|
wps->uuid_e);
|
||||||
return WPS_DONE;
|
return WPS_DONE;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_WPS_UPNP */
|
#endif /* CONFIG_WPS_UPNP */
|
||||||
|
@ -2419,6 +2500,8 @@ static enum wps_process_res wps_process_wsc_done(struct wps_data *wps,
|
||||||
}
|
}
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "WPS: Negotiation completed successfully");
|
wpa_printf(MSG_DEBUG, "WPS: Negotiation completed successfully");
|
||||||
|
wps_device_store(wps->wps->registrar, &wps->peer_dev,
|
||||||
|
wps->uuid_e);
|
||||||
|
|
||||||
if (wps->wps->wps_state == WPS_STATE_NOT_CONFIGURED && wps->new_psk &&
|
if (wps->wps->wps_state == WPS_STATE_NOT_CONFIGURED && wps->new_psk &&
|
||||||
wps->wps->ap && !wps->wps->registrar->disable_auto_conf) {
|
wps->wps->ap && !wps->wps->registrar->disable_auto_conf) {
|
||||||
|
@ -2606,3 +2689,39 @@ int wps_registrar_set_selected_registrar(struct wps_registrar *reg,
|
||||||
reg, NULL);
|
reg, NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wps_registrar_get_info(struct wps_registrar *reg, const u8 *addr,
|
||||||
|
char *buf, size_t buflen)
|
||||||
|
{
|
||||||
|
struct wps_registrar_device *d;
|
||||||
|
int len = 0, ret;
|
||||||
|
char uuid[40];
|
||||||
|
|
||||||
|
d = wps_device_get(reg, addr);
|
||||||
|
if (d == NULL)
|
||||||
|
return 0;
|
||||||
|
if (uuid_bin2str(d->uuid, uuid, sizeof(uuid)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ret = os_snprintf(buf + len, buflen - len,
|
||||||
|
"wpsUuid=%s\n"
|
||||||
|
"wpsPrimaryDeviceType=%u-%08X-%u\n"
|
||||||
|
"wpsDeviceName=%s\n"
|
||||||
|
"wpsManufacturer=%s\n"
|
||||||
|
"wpsModelName=%s\n"
|
||||||
|
"wpsModelNumber=%s\n"
|
||||||
|
"wpsSerialNumber=%s\n",
|
||||||
|
uuid,
|
||||||
|
d->dev.categ, d->dev.oui, d->dev.sub_categ,
|
||||||
|
d->dev.device_name ? d->dev.device_name : "",
|
||||||
|
d->dev.manufacturer ? d->dev.manufacturer : "",
|
||||||
|
d->dev.model_name ? d->dev.model_name : "",
|
||||||
|
d->dev.model_number ? d->dev.model_number : "",
|
||||||
|
d->dev.serial_number ? d->dev.serial_number : "");
|
||||||
|
if (ret < 0 || (size_t) ret >= buflen - len)
|
||||||
|
return len;
|
||||||
|
len += ret;
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue