X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;f=hostapd%2Fwps_hostapd.c;h=5f7dd897bf1596b7e60a76221ced98c2adabc511;hb=fda90ab4b73b19d4638e8b7cd4c90458e51f9e3e;hp=a1560c981545fd92b19c239e5d6ef7b29308926e;hpb=aabe26a136459ca8d6e0926a0bcd85835ddafc9a;p=wpasupplicant diff --git a/hostapd/wps_hostapd.c b/hostapd/wps_hostapd.c index a1560c9..5f7dd89 100644 --- a/hostapd/wps_hostapd.c +++ b/hostapd/wps_hostapd.c @@ -20,12 +20,22 @@ #include "uuid.h" #include "wpa_ctrl.h" #include "ieee802_11_defs.h" +#include "sta_info.h" +#include "eapol_sm.h" #include "wps/wps.h" #include "wps/wps_defs.h" #include "wps/wps_dev_attr.h" #include "wps_hostapd.h" +#ifdef CONFIG_WPS_UPNP +#include "wps/wps_upnp.h" +static int hostapd_wps_upnp_init(struct hostapd_data *hapd, + struct wps_context *wps); +static void hostapd_wps_upnp_deinit(struct hostapd_data *hapd); +#endif /* CONFIG_WPS_UPNP */ + + static int hostapd_wps_new_psk_cb(void *ctx, const u8 *mac_addr, const u8 *psk, size_t psk_len) { @@ -376,6 +386,57 @@ static int hostapd_wps_cred_cb(void *ctx, const struct wps_credential *cred) } +static void hostapd_pwd_auth_fail(struct hostapd_data *hapd, + struct wps_event_pwd_auth_fail *data) +{ + FILE *f; + + if (!data->enrollee) + return; + + /* + * Registrar failed to prove its knowledge of the AP PIN. Lock AP setup + * if this happens multiple times. + */ + hapd->ap_pin_failures++; + if (hapd->ap_pin_failures < 4) + return; + + wpa_msg(hapd, MSG_INFO, WPS_EVENT_AP_SETUP_LOCKED); + hapd->wps->ap_setup_locked = 1; + + wps_registrar_update_ie(hapd->wps->registrar); + + if (hapd->conf->wps_cred_processing == 1) + return; + + f = fopen(hapd->iface->config_fname, "a"); + if (f == NULL) { + wpa_printf(MSG_WARNING, "WPS: Could not append to the current " + "configuration file"); + return; + } + + fprintf(f, "# WPS AP Setup Locked based on possible attack\n"); + fprintf(f, "ap_setup_locked=1\n"); + fclose(f); + + /* TODO: dualband AP may need to update multiple configuration files */ + + wpa_printf(MSG_DEBUG, "WPS: AP configuration updated"); +} + + +static void hostapd_wps_event_cb(void *ctx, enum wps_event event, + union wps_event_data *data) +{ + struct hostapd_data *hapd = ctx; + + if (event == WPS_EV_PWD_AUTH_FAIL) + hostapd_pwd_auth_fail(hapd, &data->pwd_auth_fail); +} + + static void hostapd_wps_clear_ies(struct hostapd_data *hapd) { os_free(hapd->wps_beacon_ie); @@ -406,6 +467,7 @@ int hostapd_init_wps(struct hostapd_data *hapd, return -1; wps->cred_cb = hostapd_wps_cred_cb; + wps->event_cb = hostapd_wps_event_cb; wps->cb_ctx = hapd; os_memset(&cfg, 0, sizeof(cfg)); @@ -421,11 +483,16 @@ int hostapd_init_wps(struct hostapd_data *hapd, os_memcpy(wps->ssid, hapd->conf->ssid.ssid, wps->ssid_len); wps->ap = 1; os_memcpy(wps->dev.mac_addr, hapd->own_addr, ETH_ALEN); - wps->dev.device_name = os_strdup(hapd->conf->device_name); - wps->dev.manufacturer = os_strdup(hapd->conf->manufacturer); - wps->dev.model_name = os_strdup(hapd->conf->model_name); - wps->dev.model_number = os_strdup(hapd->conf->model_number); - wps->dev.serial_number = os_strdup(hapd->conf->serial_number); + wps->dev.device_name = hapd->conf->device_name ? + os_strdup(hapd->conf->device_name) : NULL; + wps->dev.manufacturer = hapd->conf->manufacturer ? + os_strdup(hapd->conf->manufacturer) : NULL; + wps->dev.model_name = hapd->conf->model_name ? + os_strdup(hapd->conf->model_name) : NULL; + wps->dev.model_number = hapd->conf->model_number ? + os_strdup(hapd->conf->model_number) : NULL; + wps->dev.serial_number = hapd->conf->serial_number ? + os_strdup(hapd->conf->serial_number) : NULL; if (hapd->conf->config_methods) { char *m = hapd->conf->config_methods; if (os_strstr(m, "label")) @@ -540,6 +607,9 @@ int hostapd_init_wps(struct hostapd_data *hapd, wps->encr_types = WPS_ENCR_AES | WPS_ENCR_TKIP; } + wps->ap_settings = conf->ap_settings; + wps->ap_settings_len = conf->ap_settings_len; + cfg.new_psk_cb = hostapd_wps_new_psk_cb; cfg.set_ie_cb = hostapd_wps_set_ie_cb; cfg.pin_needed_cb = hostapd_wps_pin_needed_cb; @@ -559,6 +629,22 @@ int hostapd_init_wps(struct hostapd_data *hapd, return -1; } +#ifdef CONFIG_WPS_UPNP + wps->friendly_name = hapd->conf->friendly_name; + wps->manufacturer_url = hapd->conf->manufacturer_url; + wps->model_description = hapd->conf->model_description; + wps->model_url = hapd->conf->model_url; + wps->upc = hapd->conf->upc; + + if (hostapd_wps_upnp_init(hapd, wps) < 0) { + wpa_printf(MSG_ERROR, "Failed to initialize WPS UPnP"); + wps_registrar_deinit(wps->registrar); + os_free(wps->network_key); + os_free(wps); + return -1; + } +#endif /* CONFIG_WPS_UPNP */ + hapd->wps = wps; return 0; @@ -569,9 +655,13 @@ void hostapd_deinit_wps(struct hostapd_data *hapd) { if (hapd->wps == NULL) return; +#ifdef CONFIG_WPS_UPNP + hostapd_wps_upnp_deinit(hapd); +#endif /* CONFIG_WPS_UPNP */ wps_registrar_deinit(hapd->wps->registrar); os_free(hapd->wps->network_key); wps_device_data_free(&hapd->wps->dev); + wpabuf_free(hapd->wps->upnp_msg); os_free(hapd->wps); hapd->wps = NULL; hostapd_wps_clear_ies(hapd); @@ -645,8 +735,244 @@ void hostapd_wps_probe_req_rx(struct hostapd_data *hapd, const u8 *addr, pos += 2 + pos[1]; } - if (wpabuf_len(wps_ie) > 0) + if (wpabuf_len(wps_ie) > 0) { wps_registrar_probe_req_rx(hapd->wps->registrar, addr, wps_ie); +#ifdef CONFIG_WPS_UPNP + /* FIX: what exactly should be included in the WLANEvent? + * WPS attributes? Full ProbeReq frame? */ + upnp_wps_device_send_wlan_event(hapd->wps_upnp, addr, + UPNP_WPS_WLANEVENT_TYPE_PROBE, + wps_ie); +#endif /* CONFIG_WPS_UPNP */ + } wpabuf_free(wps_ie); } + + +#ifdef CONFIG_WPS_UPNP + +static struct wpabuf * +hostapd_rx_req_get_device_info(void *priv, struct upnp_wps_peer *peer) +{ + struct hostapd_data *hapd = priv; + struct wps_config cfg; + struct wps_data *wps; + enum wsc_op_code op_code; + struct wpabuf *m1; + + /* + * Request for DeviceInfo, i.e., M1 TLVs. This is a start of WPS + * registration over UPnP with the AP acting as an Enrollee. It should + * be noted that this is frequently used just to get the device data, + * i.e., there may not be any intent to actually complete the + * registration. + */ + + if (peer->wps) + wps_deinit(peer->wps); + + os_memset(&cfg, 0, sizeof(cfg)); + cfg.wps = hapd->wps; + cfg.pin = (u8 *) hapd->conf->ap_pin; + cfg.pin_len = os_strlen(hapd->conf->ap_pin); + wps = wps_init(&cfg); + if (wps == NULL) + return NULL; + + m1 = wps_get_msg(wps, &op_code); + if (m1 == NULL) { + wps_deinit(wps); + return NULL; + } + + peer->wps = wps; + + return m1; +} + + +static struct wpabuf * +hostapd_rx_req_put_message(void *priv, struct upnp_wps_peer *peer, + const struct wpabuf *msg) +{ + enum wps_process_res res; + enum wsc_op_code op_code; + + /* PutMessage: msg = InMessage, return OutMessage */ + res = wps_process_msg(peer->wps, WSC_UPnP, msg); + if (res == WPS_FAILURE) + return NULL; + return wps_get_msg(peer->wps, &op_code); +} + + +static struct wpabuf * +hostapd_rx_req_get_ap_settings(void *priv, const struct wpabuf *msg) +{ + wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__); + return NULL; +} + + +static int hostapd_rx_req_set_ap_settings(void *priv, const struct wpabuf *msg) +{ + wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__); + return -1; +} + + +static int hostapd_rx_req_del_ap_settings(void *priv, const struct wpabuf *msg) +{ + wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__); + return -1; +} + + +static struct wpabuf * +hostapd_rx_req_get_sta_settings(void *priv, const struct wpabuf *msg) +{ + wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__); + return NULL; +} + + +static int hostapd_rx_req_set_sta_settings(void *priv, + const struct wpabuf *msg) +{ + wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__); + return -1; +} + + +static int hostapd_rx_req_del_sta_settings(void *priv, + const struct wpabuf *msg) +{ + wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__); + return -1; +} + + +static int hostapd_rx_req_put_wlan_event_response( + void *priv, enum upnp_wps_wlanevent_type ev_type, + const u8 *mac_addr, const struct wpabuf *msg) +{ + struct hostapd_data *hapd = priv; + struct sta_info *sta; + + wpa_printf(MSG_DEBUG, "WPS UPnP: PutWLANResponse ev_type=%d mac_addr=" + MACSTR, ev_type, MAC2STR(mac_addr)); + wpa_hexdump_ascii(MSG_MSGDUMP, "WPS UPnP: PutWLANResponse NewMessage", + wpabuf_head(msg), wpabuf_len(msg)); + if (ev_type != UPNP_WPS_WLANEVENT_TYPE_EAP) { + wpa_printf(MSG_DEBUG, "WPS UPnP: Ignored unexpected " + "PutWLANResponse WLANEventType %d", ev_type); + return -1; + } + + /* + * EAP response to ongoing to WPS Registration. Send it to EAP-WSC + * server implementation for delivery to the peer. + */ + + /* TODO: support multiple pending UPnP messages */ + os_memcpy(hapd->wps->upnp_msg_addr, mac_addr, ETH_ALEN); + wpabuf_free(hapd->wps->upnp_msg); + hapd->wps->upnp_msg = wpabuf_dup(msg); + + sta = ap_get_sta(hapd, mac_addr); + if (sta) + return eapol_auth_eap_pending_cb(sta->eapol_sm, + hapd->wps->pending_session); + + return 0; +} + + +static int hostapd_rx_req_set_selected_registrar(void *priv, + const struct wpabuf *msg) +{ + struct hostapd_data *hapd = priv; + return wps_registrar_set_selected_registrar(hapd->wps->registrar, msg); +} + + +static int hostapd_rx_req_reboot_ap(void *priv, const struct wpabuf *msg) +{ + wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__); + return -1; +} + + +static int hostapd_rx_req_reset_ap(void *priv, const struct wpabuf *msg) +{ + wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__); + return -1; +} + + +static int hostapd_rx_req_reboot_sta(void *priv, const struct wpabuf *msg) +{ + wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__); + return -1; +} + + +static int hostapd_rx_req_reset_sta(void *priv, const struct wpabuf *msg) +{ + wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__); + return -1; +} + + +static int hostapd_wps_upnp_init(struct hostapd_data *hapd, + struct wps_context *wps) +{ + struct upnp_wps_device_ctx *ctx; + + if (!hapd->conf->upnp_iface) + return 0; + ctx = os_zalloc(sizeof(*ctx)); + if (ctx == NULL) + return -1; + + ctx->rx_req_get_device_info = hostapd_rx_req_get_device_info; + ctx->rx_req_put_message = hostapd_rx_req_put_message; + ctx->rx_req_get_ap_settings = hostapd_rx_req_get_ap_settings; + ctx->rx_req_set_ap_settings = hostapd_rx_req_set_ap_settings; + ctx->rx_req_del_ap_settings = hostapd_rx_req_del_ap_settings; + ctx->rx_req_get_sta_settings = hostapd_rx_req_get_sta_settings; + ctx->rx_req_set_sta_settings = hostapd_rx_req_set_sta_settings; + ctx->rx_req_del_sta_settings = hostapd_rx_req_del_sta_settings; + ctx->rx_req_put_wlan_event_response = + hostapd_rx_req_put_wlan_event_response; + ctx->rx_req_set_selected_registrar = + hostapd_rx_req_set_selected_registrar; + ctx->rx_req_reboot_ap = hostapd_rx_req_reboot_ap; + ctx->rx_req_reset_ap = hostapd_rx_req_reset_ap; + ctx->rx_req_reboot_sta = hostapd_rx_req_reboot_sta; + ctx->rx_req_reset_sta = hostapd_rx_req_reset_sta; + + hapd->wps_upnp = upnp_wps_device_init(ctx, wps, hapd); + if (hapd->wps_upnp == NULL) { + os_free(ctx); + return -1; + } + wps->wps_upnp = hapd->wps_upnp; + + if (upnp_wps_device_start(hapd->wps_upnp, hapd->conf->upnp_iface)) { + upnp_wps_device_deinit(hapd->wps_upnp); + hapd->wps_upnp = NULL; + return -1; + } + + return 0; +} + + +static void hostapd_wps_upnp_deinit(struct hostapd_data *hapd) +{ + upnp_wps_device_deinit(hapd->wps_upnp); +} + +#endif /* CONFIG_WPS_UPNP */