tinyproxy: fix CVE-2012-3505
authorSteven Barth <steven@midlink.org>
Mon, 11 Aug 2014 10:37:29 +0000 (12:37 +0200)
committerSteven Barth <steven@midlink.org>
Mon, 11 Aug 2014 10:38:07 +0000 (12:38 +0200)
Signed-off-by: Steven Barth <steven@midlink.org>
net/tinyproxy/Makefile
net/tinyproxy/patches/CVE-2012-3505-tiniproxy-randomized-hashmaps.patch [new file with mode: 0644]
net/tinyproxy/patches/CVE-2012-3505-tinyproxy-limit-headers.patch [new file with mode: 0644]

index fa03eb86393e8cedd1f15710967a1858a55d9be9..566b500ed4c1fb08de18987d2130aeef583a0aa6 100644 (file)
@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
 
 PKG_NAME:=tinyproxy
 PKG_VERSION:=1.8.3
-PKG_RELEASE:=1
+PKG_RELEASE:=2
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
 PKG_SOURCE_URL:=http://www.banu.com/pub/tinyproxy/1.8/
diff --git a/net/tinyproxy/patches/CVE-2012-3505-tiniproxy-randomized-hashmaps.patch b/net/tinyproxy/patches/CVE-2012-3505-tiniproxy-randomized-hashmaps.patch
new file mode 100644 (file)
index 0000000..4737b8b
--- /dev/null
@@ -0,0 +1,101 @@
+--- a/src/child.c
++++ b/src/child.c
+@@ -20,6 +20,9 @@
+  * processing incoming connections.
+  */
++#include <stdlib.h>
++#include <time.h>
++
+ #include "main.h"
+ #include "child.h"
+@@ -196,6 +199,7 @@ static void child_main (struct child_s *
+         }
+         ptr->connects = 0;
++      srand(time(NULL));
+         while (!config.quit) {
+                 ptr->status = T_WAITING;
+--- a/src/hashmap.c
++++ b/src/hashmap.c
+@@ -25,6 +25,8 @@
+  * don't try to free the data, or realloc the memory. :)
+  */
++#include <stdlib.h>
++
+ #include "main.h"
+ #include "hashmap.h"
+@@ -50,6 +52,7 @@ struct hashbucket_s {
+ };
+ struct hashmap_s {
++        uint32_t seed;
+         unsigned int size;
+         hashmap_iter end_iterator;
+@@ -65,7 +68,7 @@ struct hashmap_s {
+  *
+  * If any of the arguments are invalid a negative number is returned.
+  */
+-static int hashfunc (const char *key, unsigned int size)
++static int hashfunc (const char *key, unsigned int size, uint32_t seed)
+ {
+         uint32_t hash;
+@@ -74,7 +77,7 @@ static int hashfunc (const char *key, un
+         if (size == 0)
+                 return -ERANGE;
+-        for (hash = tolower (*key++); *key != '\0'; key++) {
++        for (hash = seed; *key != '\0'; key++) {
+                 uint32_t bit = (hash & 1) ? (1 << (sizeof (uint32_t) - 1)) : 0;
+                 hash >>= 1;
+@@ -104,6 +107,7 @@ hashmap_t hashmap_create (unsigned int n
+         if (!ptr)
+                 return NULL;
++      ptr->seed = (uint32_t)rand();
+         ptr->size = nbuckets;
+         ptr->buckets = (struct hashbucket_s *) safecalloc (nbuckets,
+                                                            sizeof (struct
+@@ -201,7 +205,7 @@ hashmap_insert (hashmap_t map, const cha
+         if (!data || len < 1)
+                 return -ERANGE;
+-        hash = hashfunc (key, map->size);
++        hash = hashfunc (key, map->size, map->seed);
+         if (hash < 0)
+                 return hash;
+@@ -382,7 +386,7 @@ ssize_t hashmap_search (hashmap_t map, c
+         if (map == NULL || key == NULL)
+                 return -EINVAL;
+-        hash = hashfunc (key, map->size);
++        hash = hashfunc (key, map->size, map->seed);
+         if (hash < 0)
+                 return hash;
+@@ -416,7 +420,7 @@ ssize_t hashmap_entry_by_key (hashmap_t
+         if (!map || !key || !data)
+                 return -EINVAL;
+-        hash = hashfunc (key, map->size);
++        hash = hashfunc (key, map->size, map->seed);
+         if (hash < 0)
+                 return hash;
+@@ -451,7 +455,7 @@ ssize_t hashmap_remove (hashmap_t map, c
+         if (map == NULL || key == NULL)
+                 return -EINVAL;
+-        hash = hashfunc (key, map->size);
++        hash = hashfunc (key, map->size, map->seed);
+         if (hash < 0)
+                 return hash;
diff --git a/net/tinyproxy/patches/CVE-2012-3505-tinyproxy-limit-headers.patch b/net/tinyproxy/patches/CVE-2012-3505-tinyproxy-limit-headers.patch
new file mode 100644 (file)
index 0000000..b8023ab
--- /dev/null
@@ -0,0 +1,44 @@
+--- a/src/reqs.c
++++ b/src/reqs.c
+@@ -610,6 +610,11 @@ add_header_to_connection (hashmap_t hash
+         return hashmap_insert (hashofheaders, header, sep, len);
+ }
++/* define max number of headers. big enough to handle legitimate cases,
++ * but limited to avoid DoS 
++ */
++#define MAX_HEADERS 10000
++
+ /*
+  * Read all the headers from the stream
+  */
+@@ -617,6 +622,7 @@ static int get_all_headers (int fd, hash
+ {
+         char *line = NULL;
+         char *header = NULL;
++      int count;
+         char *tmp;
+         ssize_t linelen;
+         ssize_t len = 0;
+@@ -625,7 +631,7 @@ static int get_all_headers (int fd, hash
+         assert (fd >= 0);
+         assert (hashofheaders != NULL);
+-        for (;;) {
++        for (count = 0; count < MAX_HEADERS; count++) {
+                 if ((linelen = readline (fd, &line)) <= 0) {
+                         safefree (header);
+                         safefree (line);
+@@ -691,6 +697,12 @@ static int get_all_headers (int fd, hash
+                 safefree (line);
+         }
++
++      /* if we get there, this is we reached MAX_HEADERS count.
++         bail out with error */
++      safefree (header);
++      safefree (line);
++      return -1;
+ }
+ /*