X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=src%2Fwps%2Fwps_er.c;h=4726e52612ca0302ebd5524a37dcba213c38a511;hb=2d5e0d78e98a8209a53ee8f5539fef751fc23adc;hp=3eed6e9f4ec30b767c5875f1ae97cf3b8071ffea;hpb=1a1bf008cb25f327a69fcb06451771c227574d2e;p=libeap.git diff --git a/src/wps/wps_er.c b/src/wps/wps_er.c index 3eed6e9..4726e52 100644 --- a/src/wps/wps_er.c +++ b/src/wps/wps_er.c @@ -85,6 +85,7 @@ static void wps_er_sta_free(struct wps_er_sta *sta) os_free(sta->dev_name); http_client_free(sta->http); eloop_cancel_timeout(wps_er_sta_timeout, sta, NULL); + os_free(sta->cred); os_free(sta); } @@ -479,7 +480,8 @@ static void wps_er_parse_device_description(struct wps_er_ap *ap, pos = os_strstr(ap->udn, "uuid:"); if (pos) { pos += 5; - uuid_str2bin(pos, ap->uuid); + if (uuid_str2bin(pos, ap->uuid) < 0) + wpa_printf(MSG_DEBUG, "WPS ER: Invalid UUID in UDN"); } ap->upc = xml_get_first_item(data, "UPC"); @@ -761,6 +763,7 @@ static void wps_er_process_wlanevent_probe_req(struct wps_er_ap *ap, } wps_er_add_sta_data(ap, addr, &attr, 1); + wps_registrar_probe_req_rx(ap->er->wps->registrar, addr, msg, 0); } @@ -952,6 +955,17 @@ static void wps_er_sta_start(struct wps_er_sta *sta, struct wpabuf *msg) return; sta->wps->er = 1; sta->wps->use_cred = sta->ap->ap_settings; + if (sta->ap->ap_settings) { + os_free(sta->cred); + sta->cred = os_malloc(sizeof(*sta->cred)); + if (sta->cred) { + os_memcpy(sta->cred, sta->ap->ap_settings, + sizeof(*sta->cred)); + sta->cred->cred_attr = NULL; + os_memcpy(sta->cred->mac_addr, sta->addr, ETH_ALEN); + sta->wps->use_cred = sta->cred; + } + } wps_er_sta_process(sta, msg, WSC_MSG); } @@ -1138,7 +1152,7 @@ static void wps_er_http_req(void *ctx, struct http_request *req) struct wps_er * -wps_er_init(struct wps_context *wps, const char *ifname) +wps_er_init(struct wps_context *wps, const char *ifname, const char *filter) { struct wps_er *er; struct in_addr addr; @@ -1154,11 +1168,26 @@ wps_er_init(struct wps_context *wps, const char *ifname) os_strlcpy(er->ifname, ifname, sizeof(er->ifname)); er->wps = wps; - os_get_random((unsigned char *) &er->event_id, sizeof(er->event_id)); + if (os_get_random((unsigned char *) &er->event_id, + sizeof(er->event_id)) < 0) { + wps_er_deinit(er, NULL, NULL); + return NULL; + } + /* Limit event_id to < 32 bits to avoid issues with atoi() */ + er->event_id &= 0x0fffffff; - if (get_netif_info(ifname, - &er->ip_addr, &er->ip_addr_text, - er->mac_addr, &er->mac_addr_text)) { + if (filter) { + if (inet_aton(filter, &er->filter_addr) == 0) { + wpa_printf(MSG_INFO, "WPS UPnP: Invalid filter " + "address %s", filter); + wps_er_deinit(er, NULL, NULL); + return NULL; + } + wpa_printf(MSG_DEBUG, "WPS UPnP: Only accepting connections " + "with %s", filter); + } + if (get_netif_info(ifname, &er->ip_addr, &er->ip_addr_text, + er->mac_addr)) { wpa_printf(MSG_INFO, "WPS UPnP: Could not get IP/MAC address " "for %s. Does it have IP address?", ifname); wps_er_deinit(er, NULL, NULL); @@ -1178,9 +1207,8 @@ wps_er_init(struct wps_context *wps, const char *ifname) } er->http_port = http_server_get_port(er->http_srv); - wpa_printf(MSG_DEBUG, "WPS ER: Start (ifname=%s ip_addr=%s " - "mac_addr=%s)", - er->ifname, er->ip_addr_text, er->mac_addr_text); + wpa_printf(MSG_DEBUG, "WPS ER: Start (ifname=%s ip_addr=%s)", + er->ifname, er->ip_addr_text); return er; } @@ -1212,7 +1240,6 @@ static void wps_er_deinit_finish(void *eloop_data, void *user_ctx) deinit_done_cb = er->deinit_done_cb; deinit_done_ctx = er->deinit_done_ctx; os_free(er->ip_addr_text); - os_free(er->mac_addr_text); os_free(er); if (deinit_done_cb) @@ -1323,20 +1350,43 @@ static int wps_er_build_sel_reg_config_methods(struct wpabuf *msg, } +static int wps_er_build_uuid_r(struct wpabuf *msg, const u8 *uuid_r) +{ +#ifdef CONFIG_WPS2 + wpabuf_put_be16(msg, ATTR_UUID_R); + wpabuf_put_be16(msg, WPS_UUID_LEN); + wpabuf_put_data(msg, uuid_r, WPS_UUID_LEN); +#endif /* CONFIG_WPS2 */ + return 0; +} + + void wps_er_set_sel_reg(struct wps_er *er, int sel_reg, u16 dev_passwd_id, u16 sel_reg_config_methods) { struct wpabuf *msg; struct wps_er_ap *ap; + struct wps_registrar *reg = er->wps->registrar; + const u8 *auth_macs; + size_t count; + + if (er->skip_set_sel_reg) { + wpa_printf(MSG_DEBUG, "WPS ER: Skip SetSelectedRegistrar"); + return; + } msg = wpabuf_alloc(500); if (msg == NULL) return; + auth_macs = wps_authorized_macs(reg, &count); + if (wps_build_version(msg) || wps_er_build_selected_registrar(msg, sel_reg) || wps_er_build_dev_password_id(msg, dev_passwd_id) || - wps_er_build_sel_reg_config_methods(msg, sel_reg_config_methods)) { + wps_er_build_sel_reg_config_methods(msg, sel_reg_config_methods) || + wps_build_wfa_ext(msg, 0, auth_macs, count) || + wps_er_build_uuid_r(msg, er->wps->uuid)) { wpabuf_free(msg); return; } @@ -1353,6 +1403,12 @@ int wps_er_pbc(struct wps_er *er, const u8 *uuid) if (er == NULL || er->wps == NULL) return -1; + if (wps_registrar_pbc_overlap(er->wps->registrar, NULL, NULL)) { + wpa_printf(MSG_DEBUG, "WPS ER: PBC overlap - do not start PBC " + "mode"); + return -1; + } + /* * TODO: Should enable PBC mode only in a single AP based on which AP * the Enrollee (uuid) is using. Now, we may end up enabling multiple @@ -1369,6 +1425,8 @@ int wps_er_pbc(struct wps_er *er, const u8 *uuid) static void wps_er_ap_settings_cb(void *ctx, const struct wps_credential *cred) { struct wps_er_ap *ap = ctx; + union wps_event_data data; + wpa_printf(MSG_DEBUG, "WPS ER: AP Settings received"); os_free(ap->ap_settings); ap->ap_settings = os_malloc(sizeof(*cred)); @@ -1377,7 +1435,11 @@ static void wps_er_ap_settings_cb(void *ctx, const struct wps_credential *cred) ap->ap_settings->cred_attr = NULL; } - /* TODO: send info through ctrl_iface */ + os_memset(&data, 0, sizeof(data)); + data.ap_settings.uuid = ap->uuid; + data.ap_settings.cred = cred; + ap->er->wps->event_cb(ap->er->wps->cb_ctx, WPS_EV_ER_AP_SETTINGS, + &data); } @@ -1471,10 +1533,26 @@ static void wps_er_ap_put_message(struct wps_er_ap *ap, static void wps_er_ap_process(struct wps_er_ap *ap, struct wpabuf *msg) { enum wps_process_res res; + struct wps_parse_attr attr; + enum wsc_op_code op_code; + + op_code = WSC_MSG; + if (wps_parse_msg(msg, &attr) == 0 && attr.msg_type) { + switch (*attr.msg_type) { + case WPS_WSC_ACK: + op_code = WSC_ACK; + break; + case WPS_WSC_NACK: + op_code = WSC_NACK; + break; + case WPS_WSC_DONE: + op_code = WSC_Done; + break; + } + } - res = wps_process_msg(ap->wps, WSC_MSG, msg); + res = wps_process_msg(ap->wps, op_code, msg); if (res == WPS_CONTINUE) { - enum wsc_op_code op_code; struct wpabuf *next = wps_get_msg(ap->wps, &op_code); if (next) { wps_er_ap_put_message(ap, next); @@ -1485,6 +1563,10 @@ static void wps_er_ap_process(struct wps_er_ap *ap, struct wpabuf *msg) wps_deinit(ap->wps); ap->wps = NULL; } + } else if (res == WPS_DONE) { + wpa_printf(MSG_DEBUG, "WPS ER: Protocol run done"); + wps_deinit(ap->wps); + ap->wps = NULL; } else { wpa_printf(MSG_DEBUG, "WPS ER: Failed to process message from " "AP (res=%d)", res); @@ -1640,8 +1722,71 @@ int wps_er_learn(struct wps_er *er, const u8 *uuid, const u8 *pin, if (wps_er_send_get_device_info(ap, wps_er_ap_learn_m1) < 0) return -1; - /* TODO: add PIN without SetSelectedRegistrar trigger to all APs */ - wps_registrar_add_pin(er->wps->registrar, uuid, pin, pin_len, 0); + er->skip_set_sel_reg = 1; + wps_registrar_add_pin(er->wps->registrar, NULL, uuid, pin, pin_len, 0); + er->skip_set_sel_reg = 0; + + return 0; +} + + +static void wps_er_ap_config_m1(struct wps_er_ap *ap, struct wpabuf *m1) +{ + struct wps_config cfg; + + if (ap->wps) { + wpa_printf(MSG_DEBUG, "WPS ER: Protocol run already in " + "progress with this AP"); + return; + } + + os_memset(&cfg, 0, sizeof(cfg)); + cfg.wps = ap->er->wps; + cfg.registrar = 1; + cfg.new_ap_settings = ap->ap_settings; + ap->wps = wps_init(&cfg); + if (ap->wps == NULL) + return; + ap->wps->ap_settings_cb = NULL; + ap->wps->ap_settings_cb_ctx = NULL; + + wps_er_ap_process(ap, m1); +} + + +int wps_er_config(struct wps_er *er, const u8 *uuid, const u8 *pin, + size_t pin_len, const struct wps_credential *cred) +{ + struct wps_er_ap *ap; + + if (er == NULL) + return -1; + + ap = wps_er_ap_get(er, NULL, uuid); + if (ap == NULL) { + wpa_printf(MSG_DEBUG, "WPS ER: AP not found for config " + "request"); + return -1; + } + if (ap->wps) { + wpa_printf(MSG_DEBUG, "WPS ER: Pending operation ongoing " + "with the AP - cannot start config"); + return -1; + } + + os_free(ap->ap_settings); + ap->ap_settings = os_malloc(sizeof(*cred)); + if (ap->ap_settings == NULL) + return -1; + os_memcpy(ap->ap_settings, cred, sizeof(*cred)); + ap->ap_settings->cred_attr = NULL; + + if (wps_er_send_get_device_info(ap, wps_er_ap_config_m1) < 0) + return -1; + + er->skip_set_sel_reg = 1; + wps_registrar_add_pin(er->wps->registrar, NULL, uuid, pin, pin_len, 0); + er->skip_set_sel_reg = 0; return 0; }