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:
Jouni Malinen 2009-09-07 22:09:13 +03:00 committed by Jouni Malinen
parent 52eb293dd2
commit 2678509dec
13 changed files with 170 additions and 1 deletions

View File

@ -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);
if (res >= 0)
len += res;
res = hostapd_wps_get_mib_sta(hapd, sta->addr, buf + len,
buflen - len);
if (res >= 0)
len += res;
return len;
}

View File

@ -828,6 +828,7 @@ eapol_auth_alloc(struct eapol_authenticator *eapol, const u8 *addr,
eap_conf.tnc = eapol->conf.tnc;
eap_conf.wps = eapol->conf.wps;
eap_conf.assoc_wps_ie = sta->wps_ie;
eap_conf.peer_addr = addr;
sm->eap = eap_server_sm_init(sm, &eapol_cb, &eap_conf);
if (sm->eap == NULL) {
eapol_auth_free(sm);

View File

@ -1092,3 +1092,10 @@ static void hostapd_wps_upnp_deinit(struct hostapd_data *hapd)
}
#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);
}

View File

@ -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_start_oob(struct hostapd_data *hapd, char *device_type,
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 */
@ -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 /* WPS_HOSTAPD_H */

View File

@ -1238,6 +1238,8 @@ struct eap_sm * eap_server_sm_init(void *eapol_ctx,
sm->wps = conf->wps;
if (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");

View File

@ -105,6 +105,7 @@ struct eap_config {
int tnc;
struct wps_context *wps;
const struct wpabuf *assoc_wps_ie;
const u8 *peer_addr;
};

View File

@ -185,6 +185,8 @@ struct eap_sm {
struct wpabuf *assoc_wps_ie;
Boolean start_reauth;
u8 peer_addr[ETH_ALEN];
};
int eap_user_get(struct eap_sm *sm, const u8 *identity, size_t identity_len,

View File

@ -126,6 +126,7 @@ static void * eap_wsc_init(struct eap_sm *sm)
cfg.pin_len = sm->user->password_len;
}
cfg.assoc_wps_ie = sm->assoc_wps_ie;
cfg.peer_addr = sm->peer_addr;
data->wps = wps_init(&cfg);
if (data->wps == NULL) {
os_free(data);

View File

@ -100,6 +100,9 @@ struct wps_data * wps_init(const struct wps_config *cfg)
sizeof(*data->new_ap_settings));
}
if (cfg->peer_addr)
os_memcpy(data->peer_dev.mac_addr, cfg->peer_addr, ETH_ALEN);
return data;
}

View File

@ -142,6 +142,11 @@ struct wps_config {
* current AP settings by using AP PIN.
*/
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);
@ -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_set_selected_registrar(struct wps_registrar *reg,
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_valid(unsigned int pin);

View File

@ -328,6 +328,16 @@ static struct wpabuf * wps_build_m7(struct wps_data *wps)
}
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;
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_uuid_r(wps, attr->uuid_r) ||
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;
return WPS_CONTINUE;
}

View File

@ -247,6 +247,8 @@ enum wps_process_res wps_registrar_process_msg(struct wps_data *wps,
enum wsc_op_code op_code,
const 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 */
struct wpabuf * ndef_parse_wifi(struct wpabuf *buf);

View File

@ -23,6 +23,7 @@
#include "wps_dev_attr.h"
#include "wps_upnp.h"
#include "crypto.h"
#include "uuid.h"
#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_context *wps;
@ -104,6 +112,8 @@ struct wps_registrar {
int sel_reg_dev_password_id_override;
int sel_reg_config_methods_override;
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);
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,
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_pbc_sessions(reg->pbc_sessions);
wpabuf_free(reg->extra_cred);
wps_free_devices(reg->devices);
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) {
wpa_printf(MSG_DEBUG, "WPS: Negotiation using external "
"Registrar completed successfully");
wps_device_store(wps->wps->registrar, &wps->peer_dev,
wps->uuid_e);
return WPS_DONE;
}
#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");
wps_device_store(wps->wps->registrar, &wps->peer_dev,
wps->uuid_e);
if (wps->wps->wps_state == WPS_STATE_NOT_CONFIGURED && wps->new_psk &&
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);
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;
}