WPS: Cleaned up URL parser not to modify const buffer
[libeap.git] / src / wps / wps_upnp.c
index d2e4731..4825d2a 100644 (file)
@@ -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 <j@w1.fi>
+ * Copyright (c) 2009-2010, Jouni Malinen <j@w1.fi>
  *
  * See below for more details on licensing and code history.
  */
@@ -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: "
@@ -385,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);
 }
 
 
@@ -407,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++;
@@ -417,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;
        }
 }
 
@@ -693,6 +695,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)