X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=src%2Fwps%2Fwps_upnp.c;h=410df463a2b74dc15915a4d730ea49506f78b0fc;hb=3904567d0bd5b5ae946ae0e954da257f960e77f8;hp=62c24c7cf9825e422e403a4f8a432f83777a2d92;hpb=f1de40f72803211c5851186e8556ebe04e7c5cbb;p=libeap.git diff --git a/src/wps/wps_upnp.c b/src/wps/wps_upnp.c index 62c24c7..410df46 100644 --- a/src/wps/wps_upnp.c +++ b/src/wps/wps_upnp.c @@ -3,7 +3,7 @@ * Copyright (c) 2000-2003 Intel Corporation * Copyright (c) 2006-2007 Sony Corporation * Copyright (c) 2008-2009 Atheros Communications - * Copyright (c) 2009, Jouni Malinen + * Copyright (c) 2009-2010, Jouni Malinen * * See below for more details on licensing and code history. */ @@ -270,7 +270,7 @@ static void uuid_make(u8 uuid[UUID_LEN]) /* subscr_addr_delete -- delete single unlinked subscriber address * (be sure to unlink first if need be) */ -static void subscr_addr_delete(struct subscr_addr *a) +void subscr_addr_delete(struct subscr_addr *a) { /* * Note: do NOT free domain_and_port or path because they point to @@ -293,7 +293,8 @@ static void subscr_addr_free_all(struct subscription *s) /* subscr_addr_add_url -- add address(es) for one url to subscription */ -static void subscr_addr_add_url(struct subscription *s, const char *url) +static void subscr_addr_add_url(struct subscription *s, const char *url, + size_t url_len) { int alloc_len; char *scratch_mem = NULL; @@ -307,20 +308,21 @@ static void subscr_addr_add_url(struct subscription *s, const char *url) struct addrinfo *result = NULL; struct addrinfo *rp; int rerr; - struct subscr_addr *a = NULL; /* url MUST begin with http: */ - if (os_strncasecmp(url, "http://", 7)) + if (url_len < 7 || os_strncasecmp(url, "http://", 7)) goto fail; url += 7; + url_len -= 7; /* allocate memory for the extra stuff we need */ - alloc_len = (2 * (os_strlen(url) + 1)); + alloc_len = 2 * (url_len + 1); scratch_mem = os_zalloc(alloc_len); if (scratch_mem == NULL) goto fail; mem = scratch_mem; - strcpy(mem, url); + os_strncpy(mem, url, url_len); + wpa_printf(MSG_DEBUG, "WPS UPnP: Adding URL '%s'", mem); domain_and_port = mem; mem += 1 + os_strlen(mem); delim = os_strchr(domain_and_port, '/'); @@ -332,7 +334,7 @@ static void subscr_addr_add_url(struct subscription *s, const char *url) } domain = mem; strcpy(domain, domain_and_port); - delim = strchr(domain, ':'); + delim = os_strchr(domain, ':'); if (delim) { *delim++ = 0; /* null terminate domain */ if (isdigit(*delim)) @@ -367,6 +369,8 @@ static void subscr_addr_add_url(struct subscription *s, const char *url) goto fail; } for (rp = result; rp; rp = rp->ai_next) { + struct subscr_addr *a; + /* Limit no. of address to avoid denial of service attack */ if (dl_list_len(&s->addr_list) >= MAX_ADDR_PER_SUBSCRIPTION) { wpa_printf(MSG_INFO, "WPS UPnP: subscr_addr_add_url: " @@ -377,7 +381,6 @@ static void subscr_addr_add_url(struct subscription *s, const char *url) a = os_zalloc(sizeof(*a) + alloc_len); if (a == NULL) continue; - a->s = s; mem = (void *) (a + 1); a->domain_and_port = mem; strcpy(mem, domain_and_port); @@ -386,19 +389,17 @@ static void subscr_addr_add_url(struct subscription *s, const char *url) if (path[0] != '/') *mem++ = '/'; strcpy(mem, path); - mem += 1 + strlen(mem); + mem += 1 + os_strlen(mem); os_memcpy(&a->saddr, rp->ai_addr, sizeof(a->saddr)); a->saddr.sin_port = htons(port); dl_list_add(&s->addr_list, &a->list); - a = NULL; /* don't free it below */ } fail: if (result) freeaddrinfo(result); os_free(scratch_mem); - os_free(a); } @@ -408,7 +409,8 @@ fail: static void subscr_addr_list_create(struct subscription *s, const char *url_list) { - char *end; + const char *end; + wpa_printf(MSG_DEBUG, "WPS UPnP: Parsing URL list '%s'", url_list); for (;;) { while (*url_list == ' ' || *url_list == '\t') url_list++; @@ -418,9 +420,8 @@ static void subscr_addr_list_create(struct subscription *s, end = os_strchr(url_list, '>'); if (end == NULL) break; - *end++ = 0; - subscr_addr_add_url(s, url_list); - url_list = end; + subscr_addr_add_url(s, url_list, end - url_list); + url_list = end + 1; } } @@ -498,9 +499,10 @@ static void upnp_wps_device_send_event(struct upnp_wps_device_sm *sm) dl_list_for_each_safe(s, tmp, &sm->subscriptions, struct subscription, list) { - if (event_add(s, buf)) { + if (event_add(s, buf, sm->wlanevent_type == + UPNP_WPS_WLANEVENT_TYPE_PROBE) == 1) { wpa_printf(MSG_INFO, "WPS UPnP: Dropping " - "subscriber due to event backlog"); + "subscriber %p due to event backlog", s); dl_list_del(&s->list); subscription_destroy(s); } @@ -566,8 +568,11 @@ static struct wpabuf * build_fake_wsc_ack(void) return NULL; wpabuf_put_u8(msg, UPNP_WPS_WLANEVENT_TYPE_EAP); wpabuf_put_str(msg, "00:00:00:00:00:00"); - wps_build_version(msg); - wps_build_msg_type(msg, WPS_WSC_ACK); + if (wps_build_version(msg) || + wps_build_msg_type(msg, WPS_WSC_ACK)) { + wpabuf_free(msg); + return NULL; + } /* Enrollee Nonce */ wpabuf_put_be16(msg, ATTR_ENROLLEE_NONCE); wpabuf_put_be16(msg, WPS_NONCE_LEN); @@ -576,6 +581,7 @@ static struct wpabuf * build_fake_wsc_ack(void) wpabuf_put_be16(msg, ATTR_REGISTRAR_NONCE); wpabuf_put_be16(msg, WPS_NONCE_LEN); wpabuf_put(msg, WPS_NONCE_LEN); + wps_build_wfa_ext(msg, 0, NULL, 0); return msg; } @@ -603,6 +609,7 @@ static int subscription_first_event(struct subscription *s) "\n"; const char *tail = "\n"; char txt[10]; + int ret; if (s->sm->wlanevent == NULL) { /* @@ -634,7 +641,7 @@ static int subscription_first_event(struct subscription *s) } buf = wpabuf_alloc(500 + os_strlen(wlan_event)); if (buf == NULL) - return 1; + return -1; wpabuf_put_str(buf, head); wpabuf_put_property(buf, "STAStatus", "1"); @@ -644,9 +651,10 @@ static int subscription_first_event(struct subscription *s) wpabuf_put_property(buf, "WLANEvent", wlan_event); wpabuf_put_str(buf, tail); - if (event_add(s, buf)) { + ret = event_add(s, buf, 0); + if (ret) { wpabuf_free(buf); - return 1; + return ret; } wpabuf_free(buf); @@ -690,6 +698,13 @@ struct subscription * subscription_start(struct upnp_wps_device_sm *sm, s->timeout_time = expire; uuid_make(s->uuid); subscr_addr_list_create(s, callback_urls); + if (dl_list_empty(&s->addr_list)) { + wpa_printf(MSG_DEBUG, "WPS UPnP: No valid callback URLs in " + "'%s' - drop subscription", callback_urls); + subscription_destroy(s); + return NULL; + } + /* Add to end of list, since it has the highest expiration time */ dl_list_add_tail(&sm->subscriptions, &s->list); /* Queue up immediate event message (our last event) @@ -784,6 +799,7 @@ int upnp_wps_device_send_wlan_event(struct upnp_wps_device_sm *sm, os_free(sm->wlanevent); sm->wlanevent = val; + sm->wlanevent_type = ev_type; upnp_wps_device_send_event(sm); ret = 0; @@ -795,7 +811,7 @@ fail: } -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) #include #include #include @@ -845,11 +861,10 @@ static int eth_get(const char *device, u8 ea[ETH_ALEN]) * @ip_addr: Buffer for returning IP address in network byte order * @ip_addr_text: Buffer for returning a pointer to allocated IP address text * @mac: Buffer for returning MAC address - * @mac_addr_text: Buffer for returning allocated MAC address text * Returns: 0 on success, -1 on failure */ int get_netif_info(const char *net_if, unsigned *ip_addr, char **ip_addr_text, - u8 mac[ETH_ALEN], char **mac_addr_text) + u8 mac[ETH_ALEN]) { struct ifreq req; int sock = -1; @@ -857,8 +872,7 @@ int get_netif_info(const char *net_if, unsigned *ip_addr, char **ip_addr_text, struct in_addr in_addr; *ip_addr_text = os_zalloc(16); - *mac_addr_text = os_zalloc(18); - if (*ip_addr_text == NULL || *mac_addr_text == NULL) + if (*ip_addr_text == NULL) goto fail; sock = socket(AF_INET, SOCK_DGRAM, 0); @@ -884,7 +898,7 @@ int get_netif_info(const char *net_if, unsigned *ip_addr, char **ip_addr_text, goto fail; } os_memcpy(mac, req.ifr_addr.sa_data, 6); -#elif defined(__FreeBSD__) +#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) if (eth_get(net_if, mac) < 0) { wpa_printf(MSG_ERROR, "WPS UPnP: Failed to get MAC address"); goto fail; @@ -892,7 +906,6 @@ int get_netif_info(const char *net_if, unsigned *ip_addr, char **ip_addr_text, #else #error MAC address fetch not implemented #endif - os_snprintf(*mac_addr_text, 18, MACSTR, MAC2STR(mac)); close(sock); return 0; @@ -902,12 +915,19 @@ fail: close(sock); os_free(*ip_addr_text); *ip_addr_text = NULL; - os_free(*mac_addr_text); - *mac_addr_text = NULL; return -1; } +static void upnp_wps_free_msearchreply(struct dl_list *head) +{ + struct advertisement_state_machine *a, *tmp; + dl_list_for_each_safe(a, tmp, head, struct advertisement_state_machine, + list) + msearchreply_state_machine_stop(a); +} + + static void upnp_wps_free_subscriptions(struct dl_list *head) { struct subscription *s, *tmp; @@ -929,8 +949,7 @@ void upnp_wps_device_stop(struct upnp_wps_device_sm *sm) wpa_printf(MSG_DEBUG, "WPS UPnP: Stop device"); web_listener_stop(sm); - while (sm->msearch_replies) - msearchreply_state_machine_stop(sm->msearch_replies); + upnp_wps_free_msearchreply(&sm->msearch_replies); upnp_wps_free_subscriptions(&sm->subscriptions); advertisement_state_machine_stop(sm, 1); @@ -938,10 +957,6 @@ void upnp_wps_device_stop(struct upnp_wps_device_sm *sm) event_send_stop_all(sm); os_free(sm->wlanevent); sm->wlanevent = NULL; - os_free(sm->net_if); - sm->net_if = NULL; - os_free(sm->mac_addr_text); - sm->mac_addr_text = NULL; os_free(sm->ip_addr_text); sm->ip_addr_text = NULL; if (sm->multicast_sd >= 0) @@ -967,7 +982,6 @@ int upnp_wps_device_start(struct upnp_wps_device_sm *sm, char *net_if) if (sm->started) upnp_wps_device_stop(sm); - sm->net_if = strdup(net_if); sm->multicast_sd = -1; sm->ssdp_sd = -1; sm->started = 1; @@ -978,9 +992,8 @@ int upnp_wps_device_start(struct upnp_wps_device_sm *sm, char *net_if) goto fail; /* Determine which IP and mac address we're using */ - if (get_netif_info(net_if, - &sm->ip_addr, &sm->ip_addr_text, - sm->mac_addr, &sm->mac_addr_text)) { + if (get_netif_info(net_if, &sm->ip_addr, &sm->ip_addr_text, + sm->mac_addr)) { wpa_printf(MSG_INFO, "WPS UPnP: Could not get IP/MAC address " "for %s. Does it have IP address?", net_if); goto fail; @@ -1059,6 +1072,7 @@ upnp_wps_device_init(struct upnp_wps_device_ctx *ctx, struct wps_context *wps, sm->ctx = ctx; sm->wps = wps; sm->priv = priv; + dl_list_init(&sm->msearch_replies); dl_list_init(&sm->subscriptions); return sm; @@ -1074,3 +1088,20 @@ int upnp_wps_subscribers(struct upnp_wps_device_sm *sm) { return !dl_list_empty(&sm->subscriptions); } + + +int upnp_wps_set_ap_pin(struct upnp_wps_device_sm *sm, const char *ap_pin) +{ + if (sm == NULL) + return 0; + + os_free(sm->ctx->ap_pin); + if (ap_pin) { + sm->ctx->ap_pin = os_strdup(ap_pin); + if (sm->ctx->ap_pin == NULL) + return -1; + } else + sm->ctx->ap_pin = NULL; + + return 0; +}