case insensitive http headers
authorAndy Green <andy.green@linaro.org>
Wed, 13 Nov 2013 00:03:05 +0000 (08:03 +0800)
committerAndy Green <andy.green@linaro.org>
Wed, 13 Nov 2013 00:03:05 +0000 (08:03 +0800)
Svetlin wrote on github

According to RFC2616, all header field names in both HTTP requests and HTTP responses are case-insensitive. But libwebsockets uses a case-sensitive compare.

Reproduce:
Run libwebsockets against a server that sends all of its HTTP header field names in lower-case (for example: https://github.com/extend/cowboy). libwebsockets reports an error. The expected behavior is no errors reported and a successful handshake procedure.

This changes the parser reference table in minilex to all lower case.

The code to walk the parser tables then just forces a tolower on the incoming chars.

This (and minilex tables) only applies to header names.

Reported-by: svetlin-mladnov <?@github>
Signed-off-by: Andy Green <andy.green@linaro.org>
lib/lextable.h
lib/minilex.c
lib/parsers.c

index 7e3e096..f25102a 100644 (file)
@@ -1,21 +1,21 @@
-/* pos   0: state   0 */    0x47 /* 'G' */, 0x0C  /* (to pos  24 state   1) */,
-                            0x48 /* 'H' */, 0x0F  /* (to pos  32 state   5) */,
-                            0x43 /* 'C' */, 0x14  /* (to pos  44 state  10) */,
-                            0x53 /* 'S' */, 0x21  /* (to pos  72 state  21) */,
-                            0x55 /* 'U' */, 0x47  /* (to pos 150 state  51) */,
-                            0x4F /* 'O' */, 0x4E  /* (to pos 166 state  59) */,
+/* pos   0: state   0 */    0x67 /* 'g' */, 0x0C  /* (to pos  24 state   1) */,
+                            0x68 /* 'h' */, 0x0F  /* (to pos  32 state   5) */,
+                            0x63 /* 'c' */, 0x14  /* (to pos  44 state  10) */,
+                            0x73 /* 's' */, 0x21  /* (to pos  72 state  21) */,
+                            0x75 /* 'u' */, 0x47  /* (to pos 150 state  51) */,
+                            0x6F /* 'o' */, 0x4E  /* (to pos 166 state  59) */,
                             0x0D /* '.' */, 0x5A  /* (to pos 192 state  72) */,
-                            0x41 /* 'A' */, 0x8B  /* (to pos 292 state 122) */,
-                            0x49 /* 'I' */, 0x93  /* (to pos 310 state 129) */,
-                            0x50 /* 'P' */, 0xB8  /* (to pos 386 state 166) */,
-                            0x44 /* 'D' */, 0xE7  /* (to pos 482 state 214) */,
-                            0xD2 /* 'R' */, 0xEB  /* (to pos 492 state 219) */,
-/* pos  24: state   1 */    0xC5 /* 'E' */, 0x01  /* (to pos  26 state   2) */,
-/* pos  26: state   2 */    0xD4 /* 'T' */, 0x01  /* (to pos  28 state   3) */,
+                            0x61 /* 'a' */, 0x8B  /* (to pos 292 state 122) */,
+                            0x69 /* 'i' */, 0x93  /* (to pos 310 state 129) */,
+                            0x70 /* 'p' */, 0xB8  /* (to pos 386 state 166) */,
+                            0x64 /* 'd' */, 0xE7  /* (to pos 482 state 214) */,
+                            0xF2 /* 'r' */, 0xEB  /* (to pos 492 state 219) */,
+/* pos  24: state   1 */    0xE5 /* 'e' */, 0x01  /* (to pos  26 state   2) */,
+/* pos  26: state   2 */    0xF4 /* 't' */, 0x01  /* (to pos  28 state   3) */,
 /* pos  28: state   3 */    0xA0 /* ' ' */, 0x01  /* (to pos  30 state   4) */,
 /* pos  30: state   4 */    0x80, 0x00            /* - terminal marker  0 - */, 
 /* pos  32: state   5 */    0x6F /* 'o' */, 0x02  /* (to pos  36 state   6) */,
-                            0xD4 /* 'T' */, 0x79  /* (to pos 276 state 114) */,
+                            0xF4 /* 't' */, 0x79  /* (to pos 276 state 114) */,
 /* pos  36: state   6 */    0xF3 /* 's' */, 0x01  /* (to pos  38 state   7) */,
 /* pos  38: state   7 */    0xF4 /* 't' */, 0x01  /* (to pos  40 state   8) */,
 /* pos  40: state   8 */    0xBA /* ':' */, 0x01  /* (to pos  42 state   9) */,
 /* pos  72: state  21 */    0xE5 /* 'e' */, 0x01  /* (to pos  74 state  22) */,
 /* pos  74: state  22 */    0xE3 /* 'c' */, 0x01  /* (to pos  76 state  23) */,
 /* pos  76: state  23 */    0xAD /* '-' */, 0x01  /* (to pos  78 state  24) */,
-/* pos  78: state  24 */    0xD7 /* 'W' */, 0x01  /* (to pos  80 state  25) */,
+/* pos  78: state  24 */    0xF7 /* 'w' */, 0x01  /* (to pos  80 state  25) */,
 /* pos  80: state  25 */    0xE5 /* 'e' */, 0x01  /* (to pos  82 state  26) */,
 /* pos  82: state  26 */    0xE2 /* 'b' */, 0x01  /* (to pos  84 state  27) */,
-/* pos  84: state  27 */    0xD3 /* 'S' */, 0x01  /* (to pos  86 state  28) */,
+/* pos  84: state  27 */    0xF3 /* 's' */, 0x01  /* (to pos  86 state  28) */,
 /* pos  86: state  28 */    0xEF /* 'o' */, 0x01  /* (to pos  88 state  29) */,
 /* pos  88: state  29 */    0xE3 /* 'c' */, 0x01  /* (to pos  90 state  30) */,
 /* pos  90: state  30 */    0xEB /* 'k' */, 0x01  /* (to pos  92 state  31) */,
 /* pos  92: state  31 */    0xE5 /* 'e' */, 0x01  /* (to pos  94 state  32) */,
 /* pos  94: state  32 */    0xF4 /* 't' */, 0x01  /* (to pos  96 state  33) */,
 /* pos  96: state  33 */    0xAD /* '-' */, 0x01  /* (to pos  98 state  34) */,
-/* pos  98: state  34 */    0x4B /* 'K' */, 0x08  /* (to pos 114 state  35) */,
-                            0x50 /* 'P' */, 0x10  /* (to pos 132 state  42) */,
-                            0x44 /* 'D' */, 0x27  /* (to pos 180 state  66) */,
-                            0x56 /* 'V' */, 0x2F  /* (to pos 198 state  75) */,
-                            0x4F /* 'O' */, 0x36  /* (to pos 214 state  83) */,
-                            0x45 /* 'E' */, 0x3C  /* (to pos 228 state  90) */,
-                            0x41 /* 'A' */, 0x46  /* (to pos 250 state 101) */,
-                            0xCE /* 'N' */, 0x4C  /* (to pos 264 state 108) */,
+/* pos  98: state  34 */    0x6B /* 'k' */, 0x08  /* (to pos 114 state  35) */,
+                            0x70 /* 'p' */, 0x10  /* (to pos 132 state  42) */,
+                            0x64 /* 'd' */, 0x27  /* (to pos 180 state  66) */,
+                            0x76 /* 'v' */, 0x2F  /* (to pos 198 state  75) */,
+                            0x6F /* 'o' */, 0x36  /* (to pos 214 state  83) */,
+                            0x65 /* 'e' */, 0x3C  /* (to pos 228 state  90) */,
+                            0x61 /* 'a' */, 0x46  /* (to pos 250 state 101) */,
+                            0xEE /* 'n' */, 0x4C  /* (to pos 264 state 108) */,
 /* pos 114: state  35 */    0xE5 /* 'e' */, 0x01  /* (to pos 116 state  36) */,
 /* pos 116: state  36 */    0xF9 /* 'y' */, 0x01  /* (to pos 118 state  37) */,
 /* pos 118: state  37 */    0x31 /* '1' */, 0x03  /* (to pos 124 state  38) */,
 /* pos 270: state 111 */    0xE5 /* 'e' */, 0x01  /* (to pos 272 state 112) */,
 /* pos 272: state 112 */    0xBA /* ':' */, 0x01  /* (to pos 274 state 113) */,
 /* pos 274: state 113 */    0x8F, 0x00            /* - terminal marker 15 - */, 
-/* pos 276: state 114 */    0xD4 /* 'T' */, 0x01  /* (to pos 278 state 115) */,
-/* pos 278: state 115 */    0xD0 /* 'P' */, 0x01  /* (to pos 280 state 116) */,
+/* pos 276: state 114 */    0xF4 /* 't' */, 0x01  /* (to pos 278 state 115) */,
+/* pos 278: state 115 */    0xF0 /* 'p' */, 0x01  /* (to pos 280 state 116) */,
 /* pos 280: state 116 */    0xAF /* '/' */, 0x01  /* (to pos 282 state 117) */,
 /* pos 282: state 117 */    0xB1 /* '1' */, 0x01  /* (to pos 284 state 118) */,
 /* pos 284: state 118 */    0xAE /* '.' */, 0x01  /* (to pos 286 state 119) */,
 /* pos 308: state 128 */    0x91, 0x00            /* - terminal marker 17 - */, 
 /* pos 310: state 129 */    0xE6 /* 'f' */, 0x01  /* (to pos 312 state 130) */,
 /* pos 312: state 130 */    0xAD /* '-' */, 0x01  /* (to pos 314 state 131) */,
-/* pos 314: state 131 */    0xCD /* 'M' */, 0x01  /* (to pos 316 state 132) */,
+/* pos 314: state 131 */    0xED /* 'm' */, 0x01  /* (to pos 316 state 132) */,
 /* pos 316: state 132 */    0xEF /* 'o' */, 0x01  /* (to pos 318 state 133) */,
 /* pos 318: state 133 */    0xE4 /* 'd' */, 0x01  /* (to pos 320 state 134) */,
 /* pos 320: state 134 */    0xE9 /* 'i' */, 0x01  /* (to pos 322 state 135) */,
 /* pos 326: state 137 */    0xE5 /* 'e' */, 0x01  /* (to pos 328 state 138) */,
 /* pos 328: state 138 */    0xE4 /* 'd' */, 0x01  /* (to pos 330 state 139) */,
 /* pos 330: state 139 */    0xAD /* '-' */, 0x01  /* (to pos 332 state 140) */,
-/* pos 332: state 140 */    0xD3 /* 'S' */, 0x01  /* (to pos 334 state 141) */,
+/* pos 332: state 140 */    0xF3 /* 's' */, 0x01  /* (to pos 334 state 141) */,
 /* pos 334: state 141 */    0xE9 /* 'i' */, 0x01  /* (to pos 336 state 142) */,
 /* pos 336: state 142 */    0xEE /* 'n' */, 0x01  /* (to pos 338 state 143) */,
 /* pos 338: state 143 */    0xE3 /* 'c' */, 0x01  /* (to pos 340 state 144) */,
 /* pos 340: state 144 */    0xE5 /* 'e' */, 0x01  /* (to pos 342 state 145) */,
 /* pos 342: state 145 */    0xBA /* ':' */, 0x01  /* (to pos 344 state 146) */,
 /* pos 344: state 146 */    0x92, 0x00            /* - terminal marker 18 - */, 
-/* pos 346: state 147 */    0x45 /* 'E' */, 0x02  /* (to pos 350 state 148) */,
-                            0xCC /* 'L' */, 0x0A  /* (to pos 368 state 157) */,
+/* pos 346: state 147 */    0x65 /* 'e' */, 0x02  /* (to pos 350 state 148) */,
+                            0xEC /* 'l' */, 0x0A  /* (to pos 368 state 157) */,
 /* pos 350: state 148 */    0xEE /* 'n' */, 0x01  /* (to pos 352 state 149) */,
 /* pos 352: state 149 */    0xE3 /* 'c' */, 0x01  /* (to pos 354 state 150) */,
 /* pos 354: state 150 */    0xEF /* 'o' */, 0x01  /* (to pos 356 state 151) */,
 /* pos 402: state 174 */    0xE8 /* 'h' */, 0x01  /* (to pos 404 state 175) */,
 /* pos 404: state 175 */    0xE5 /* 'e' */, 0x01  /* (to pos 406 state 176) */,
 /* pos 406: state 176 */    0xAD /* '-' */, 0x01  /* (to pos 408 state 177) */,
-/* pos 408: state 177 */    0xC3 /* 'C' */, 0x01  /* (to pos 410 state 178) */,
+/* pos 408: state 177 */    0xE3 /* 'c' */, 0x01  /* (to pos 410 state 178) */,
 /* pos 410: state 178 */    0xEF /* 'o' */, 0x01  /* (to pos 412 state 179) */,
 /* pos 412: state 179 */    0xEE /* 'n' */, 0x01  /* (to pos 414 state 180) */,
 /* pos 414: state 180 */    0xF4 /* 't' */, 0x01  /* (to pos 416 state 181) */,
 /* pos 464: state 205 */    0xEE /* 'n' */, 0x01  /* (to pos 466 state 206) */,
 /* pos 466: state 206 */    0xF4 /* 't' */, 0x01  /* (to pos 468 state 207) */,
 /* pos 468: state 207 */    0xAD /* '-' */, 0x01  /* (to pos 470 state 208) */,
-/* pos 470: state 208 */    0xD4 /* 'T' */, 0x01  /* (to pos 472 state 209) */,
+/* pos 470: state 208 */    0xF4 /* 't' */, 0x01  /* (to pos 472 state 209) */,
 /* pos 472: state 209 */    0xF9 /* 'y' */, 0x01  /* (to pos 474 state 210) */,
 /* pos 474: state 210 */    0xF0 /* 'p' */, 0x01  /* (to pos 476 state 211) */,
 /* pos 476: state 211 */    0xE5 /* 'e' */, 0x01  /* (to pos 478 state 212) */,
index a085c33..babe50e 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 
-/* set of parsable strings */
+/* set of parsable strings -- ALL LOWER CASE */
 
 const char *set[] = {
-       "GET ",
-       "Host:",
-       "Connection:",
-       "Sec-WebSocket-Key1:",
-       "Sec-WebSocket-Key2:",
-       "Sec-WebSocket-Protocol:",
-       "Upgrade:",
-       "Origin:",
-       "Sec-WebSocket-Draft:",
+       "get ",
+       "host:",
+       "connection:",
+       "sec-websocket-key1:",
+       "sec-websocket-key2:",
+       "sec-websocket-protocol:",
+       "upgrade:",
+       "origin:",
+       "sec-websocket-draft:",
        "\x0d\x0a",
 
-       "Sec-WebSocket-Key:",
-       "Sec-WebSocket-Version:",
-       "Sec-WebSocket-Origin:",
-
-       "Sec-WebSocket-Extensions:",
-
-       "Sec-WebSocket-Accept:",
-       "Sec-WebSocket-Nonce:",
-       "HTTP/1.1 ",
-
-       "Accept:",
-       "If-Modified-Since:",
-       "Accept-Encoding:",
-       "Accept-Language:",
-       "Pragma:",
-       "Cache-Control:",
-       "Authorization:",
-       "Cookie:",
-       "Content-Type:",
-       "Date:",
-       "Range:",
-       "Referer:"
+       "sec-websocket-key:",
+       "sec-websocket-version:",
+       "sec-websocket-origin:",
+
+       "sec-websocket-extensions:",
+
+       "sec-websocket-accept:",
+       "sec-websocket-nonce:",
+       "http/1.1 ",
+
+       "accept:",
+       "if-modified-since:",
+       "accept-encoding:",
+       "accept-language:",
+       "pragma:",
+       "cache-control:",
+       "authorization:",
+       "cookie:",
+       "content-type:",
+       "date:",
+       "range:",
+       "referer:",
+       "", /* not matchable */
+
 };
 
 unsigned char lextable[] = {
@@ -104,6 +106,11 @@ int main(void)
                walk = 0;
                prev = 0;
 
+               if (set[n][0] == '\0') {
+                       n++;
+                       continue;
+               }
+
                while (set[n][m]) {
 
                        saw = 0;
@@ -189,6 +196,9 @@ again:
                walk = 0;
                m = 0;
 
+               if (set[n][0] == '\0')
+                       continue;
+
                fprintf(stderr, "Trying '%s'\n", set[n]);
 
                while (set[n][m]) {
index fb43fca..95753e5 100644 (file)
@@ -36,7 +36,8 @@ int lextable_decode(int pos, char c)
                if (lextable[pos + 1] == 0) /* terminal marker */
                        return pos;
 
-               if ((lextable[pos] & 0x7f) == c)
+               /* case insensitive - RFC2616 */
+               if ((lextable[pos] & 0x7f) == tolower(c))
                        return pos + (lextable[pos + 1] << 1);
 
                if (lextable[pos] & 0x80)