]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
WPS: Store device info and make it available through AP ctrl_iface
authorJouni Malinen <jouni.malinen@atheros.com>
Mon, 7 Sep 2009 19:09:13 +0000 (22:09 +0300)
committerJouni Malinen <j@w1.fi>
Mon, 7 Sep 2009 19:09:13 +0000 (22:09 +0300)
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.

13 files changed:
hostapd/ctrl_iface.c
hostapd/eapol_sm.c
hostapd/wps_hostapd.c
hostapd/wps_hostapd.h
src/eap_server/eap.c
src/eap_server/eap.h
src/eap_server/eap_i.h
src/eap_server/eap_wsc.c
src/wps/wps.c
src/wps/wps.h
src/wps/wps_enrollee.c
src/wps/wps_i.h
src/wps/wps_registrar.c

index 6fe401e58af7977378bc439326db7310e7bd657a..bdc02f062334a7cdb3b785ddcd03646ed374bac1 100644 (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;
 }
index 5491fc4d08231ea7d9db0559d17e30706eddee35..ab6598e228593fa3bbdebb0f2652d1c055cc9970 100644 (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);
index a0c1e3a1d49e37e0b58404c05262ea1f2f123088..5ecf3a44428afd1eb64ad646c07990a3ff3b6f61 100644 (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);
+}
index 5f094f5871006479158ea7b887a022b31075f4c2..c4ac246c82272b19b7f83caabb919fc280bd12dd 100644 (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 */
index d23ae2f90d491babc4e80565e56a0a98c37de391..abb807b2172bdf61372de7236dc8b14d0b63f0dc 100644 (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");
 
index 6a20da4f46b0b1d27e1579fb1ae7ba80e164a498..dc00c3198aa5a3d4e27f3aaeffa5b8d0b3c800db 100644 (file)
@@ -105,6 +105,7 @@ struct eap_config {
        int tnc;
        struct wps_context *wps;
        const struct wpabuf *assoc_wps_ie;
+       const u8 *peer_addr;
 };
 
 
index d52b86f9558f0b3360b49bac85d93b059c6c5019..4269a8cfd6a012f237e68a6e32f123d1f57cb73f 100644 (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,
index 3c17577889b745be366f9c47842f7b33360292a3..9d14d20a4a47b0475fde58e8f662ef063311d0cc 100644 (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);
index e0e19c8880b52b93e4faca594af64eca49378dc7..cc8a45be290d919183b83168259bcfd54eead1b8 100644 (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;
 }
 
index c33e8013a1ef1d850ad53ee4edc23b0fc3606bbe..446ff4f167d6012813a8fde6bef13cf98f1493d4 100644 (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);
index 8c8d087e16b9e4faa310c3950e76a5f7d4c3d505..89d229e51808ad6662d7bdd450ab4f94e8552115 100644 (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;
        }
index b79c5291fde561dcbcf5dfa7f94f279fcf337077..c5a9d9f91825464e240f8dfba3ed97ab90d9e97f 100644 (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);
index b625d21c4b5c076538f159e071e7561ef571056a..cfe63aeb5e6cdf07ed3649844cc6cb8fae194461 100644 (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;
+}