1 /*
2 * %CopyrightBegin%
3 *
4 * Copyright Ericsson AB 2008-2018. All Rights Reserved.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * %CopyrightEnd%
19 */
20
21 /* A protocol decoder. Simple packet length extraction as well as packet
22 * body parsing with protocol specific callback interfaces (http and ssl).
23 *
24 * Code ripped out from inet_drv.c to also be used by BIF decode_packet.
25 */
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include "packet_parser.h"
31
32 #include <ctype.h>
33 #include "sys.h"
34
35 /* #define INET_DRV_DEBUG 1 */
36 #ifdef INET_DRV_DEBUG
37 # define DEBUG 1
38 # undef DEBUGF
39 # define DEBUGF(X) printf X
40 #endif
41
42 #if !defined(__WIN32__) && !defined(HAVE_STRNCASECMP)
43 #define STRNCASECMP my_strncasecmp
44
my_strncasecmp(const char * s1,const char * s2,size_t n)45 static int my_strncasecmp(const char *s1, const char *s2, size_t n)
46 {
47 int i;
48
49 for (i=0;i<n-1 && s1[i] && s2[i] && toupper(s1[i]) == toupper(s2[i]);++i)
50 ;
51 return (toupper(s1[i]) - toupper(s2[i]));
52 }
53
54
55 #else
56 #define STRNCASECMP strncasecmp
57 #endif
58
59
60 #define HTTP_HDR_HASH_SIZE 53
61 #define HTTP_METH_HASH_SIZE 13
62 #define HTTP_MAX_NAME_LEN 50
63
64 static char tspecial[128];
65
66 static const char* http_hdr_strings[] = {
67 "Cache-Control",
68 "Connection",
69 "Date",
70 "Pragma",
71 "Transfer-Encoding",
72 "Upgrade",
73 "Via",
74 "Accept",
75 "Accept-Charset",
76 "Accept-Encoding",
77 "Accept-Language",
78 "Authorization",
79 "From",
80 "Host",
81 "If-Modified-Since",
82 "If-Match",
83 "If-None-Match",
84 "If-Range",
85 "If-Unmodified-Since",
86 "Max-Forwards",
87 "Proxy-Authorization",
88 "Range",
89 "Referer",
90 "User-Agent",
91 "Age",
92 "Location",
93 "Proxy-Authenticate",
94 "Public",
95 "Retry-After",
96 "Server",
97 "Vary",
98 "Warning",
99 "Www-Authenticate",
100 "Allow",
101 "Content-Base",
102 "Content-Encoding",
103 "Content-Language",
104 "Content-Length",
105 "Content-Location",
106 "Content-Md5",
107 "Content-Range",
108 "Content-Type",
109 "Etag",
110 "Expires",
111 "Last-Modified",
112 "Accept-Ranges",
113 "Set-Cookie",
114 "Set-Cookie2",
115 "X-Forwarded-For",
116 "Cookie",
117 "Keep-Alive",
118 "Proxy-Connection",
119 NULL
120 };
121
122
123 static const char* http_meth_strings[] = {
124 "OPTIONS",
125 "GET",
126 "HEAD",
127 "POST",
128 "PUT",
129 "DELETE",
130 "TRACE",
131 NULL
132 };
133
134 static http_atom_t http_hdr_table[sizeof(http_hdr_strings)/sizeof(char*)];
135 static http_atom_t http_meth_table[sizeof(http_meth_strings)/sizeof(char*)];
136
137 static http_atom_t* http_hdr_hash[HTTP_HDR_HASH_SIZE];
138 static http_atom_t* http_meth_hash[HTTP_METH_HASH_SIZE];
139
140 #define CRNL(ptr) (((ptr)[0] == '\r') && ((ptr)[1] == '\n'))
141 #define NL(ptr) ((ptr)[0] == '\n')
142 #define SP(ptr) (((ptr)[0] == ' ') || ((ptr)[0] == '\t'))
143 #define is_tspecial(x) ((((x) > 32) && ((x) < 128)) ? tspecial[(x)] : 1)
144
145 #define hash_update(h,c) do { \
146 unsigned long __g; \
147 (h) = ((h) << 4) + (c); \
148 if ((__g = (h) & 0xf0000000)) { \
149 (h) ^= (__g >> 24); \
150 (h) ^= __g; \
151 } \
152 } while(0)
153
http_hash_insert(const char * name,http_atom_t * entry,http_atom_t ** hash,int hsize)154 static void http_hash_insert(const char* name, http_atom_t* entry,
155 http_atom_t** hash, int hsize)
156 {
157 unsigned long h = 0;
158 const unsigned char* ptr = (const unsigned char*) name;
159 int ix;
160 int len = 0;
161
162 while (*ptr != '\0') {
163 hash_update(h, *ptr);
164 ptr++;
165 len++;
166 }
167 ix = h % hsize;
168
169 entry->next = hash[ix];
170 entry->h = h;
171 entry->name = name;
172 entry->len = len;
173 entry->atom = driver_mk_atom((char*)name);
174
175 hash[ix] = entry;
176 }
177
178
http_init(void)179 static int http_init(void)
180 {
181 int i;
182 unsigned char* ptr;
183
184 for (i = 0; i < 33; i++)
185 tspecial[i] = 1;
186 for (i = 33; i < 127; i++)
187 tspecial[i] = 0;
188 for (ptr = (unsigned char*)"()<>@,;:\\\"/[]?={} \t"; *ptr != '\0'; ptr++)
189 tspecial[*ptr] = 1;
190
191 for (i = 0; i < HTTP_HDR_HASH_SIZE; i++)
192 http_hdr_hash[i] = NULL;
193 for (i = 0; http_hdr_strings[i] != NULL; i++) {
194 ASSERT(sys_strlen(http_hdr_strings[i]) <= HTTP_MAX_NAME_LEN);
195 http_hdr_table[i].index = i;
196 http_hash_insert(http_hdr_strings[i],
197 &http_hdr_table[i],
198 http_hdr_hash, HTTP_HDR_HASH_SIZE);
199 }
200
201 for (i = 0; i < HTTP_METH_HASH_SIZE; i++)
202 http_meth_hash[i] = NULL;
203 for (i = 0; http_meth_strings[i] != NULL; i++) {
204 http_meth_table[i].index = i;
205 http_hash_insert(http_meth_strings[i],
206 &http_meth_table[i],
207 http_meth_hash, HTTP_METH_HASH_SIZE);
208 }
209 return 0;
210 }
211
212
213 #define CDR_MAGIC "GIOP"
214
215 struct cdr_head {
216 unsigned char magic[4]; /* 4 bytes must be 'GIOP' */
217 unsigned char major; /* major version */
218 unsigned char minor; /* minor version */
219 unsigned char flags; /* bit 0: 0 == big endian, 1 == little endian
220 bit 1: 1 == more fragments follow */
221 unsigned char message_type; /* message type ... */
222 unsigned char message_size[4]; /* size in (flags bit 0 byte order) */
223 };
224
225 #define TPKT_VRSN 3
226
227 struct tpkt_head {
228 unsigned char vrsn; /* contains TPKT_VRSN */
229 unsigned char reserved;
230 unsigned char packet_length[2]; /* size incl header, big-endian (?) */
231 };
232
packet_parser_init()233 void packet_parser_init()
234 {
235 static int done = 0;
236 if (!done) {
237 done = 1;
238 http_init();
239 }
240 }
241
242 /* Return > 0 Total packet length.in bytes
243 * = 0 Length unknown, need more data.
244 * < 0 Error, invalid format.
245 */
packet_get_length(enum PacketParseType htype,const char * ptr,unsigned n,unsigned max_plen,unsigned trunc_len,char delimiter,int * statep)246 int packet_get_length(enum PacketParseType htype,
247 const char* ptr, unsigned n, /* Bytes read so far */
248 unsigned max_plen, /* Max packet length, 0=no limit */
249 unsigned trunc_len, /* Truncate (lines) if longer, 0=no limit */
250 char delimiter, /* Line delimiting character */
251 int* statep) /* Protocol specific state */
252 {
253 unsigned hlen, plen;
254
255 switch (htype) {
256 case TCP_PB_RAW:
257 if (n == 0) goto more;
258 else {
259 DEBUGF((" => nothing remain packet=%d\r\n", n));
260 return n;
261 }
262
263 case TCP_PB_1:
264 /* TCP_PB_1: [L0 | Data] */
265 hlen = 1;
266 if (n < hlen) goto more;
267 plen = get_int8(ptr);
268 goto remain;
269
270 case TCP_PB_2:
271 /* TCP_PB_2: [L1,L0 | Data] */
272 hlen = 2;
273 if (n < hlen) goto more;
274 plen = get_int16(ptr);
275 goto remain;
276
277 case TCP_PB_4:
278 /* TCP_PB_4: [L3,L2,L1,L0 | Data] */
279 hlen = 4;
280 if (n < hlen) goto more;
281 plen = get_int32(ptr);
282 goto remain;
283
284 case TCP_PB_RM:
285 /* TCP_PB_RM: [L3,L2,L1,L0 | Data]
286 ** where MSB (bit) is used to signal end of record
287 */
288 hlen = 4;
289 if (n < hlen) goto more;
290 plen = get_int32(ptr) & 0x7fffffff;
291 goto remain;
292
293 case TCP_PB_LINE_LF: {
294 /* TCP_PB_LINE_LF: [Data ... Delimiter] */
295 const char* ptr2;
296 if ((ptr2 = memchr(ptr, delimiter, n)) == NULL) {
297 if (n > max_plen && max_plen != 0) { /* packet full */
298 DEBUGF((" => packet full (no NL)=%d\r\n", n));
299 goto error;
300 }
301 else if (n >= trunc_len && trunc_len!=0) { /* buffer full */
302 DEBUGF((" => line buffer full (no NL)=%d\r\n", n));
303 return trunc_len;
304 }
305 goto more;
306 }
307 else {
308 int len = (ptr2 - ptr) + 1; /* including newline */
309 if (len > max_plen && max_plen!=0) {
310 DEBUGF((" => packet_size %d exceeded\r\n", max_plen));
311 goto error;
312 }
313 if (len > trunc_len && trunc_len!=0) {
314 DEBUGF((" => truncated line=%d\r\n", trunc_len));
315 return trunc_len;
316 }
317 DEBUGF((" => nothing remain packet=%d\r\n", len));
318 return len;
319 }
320 }
321
322 case TCP_PB_ASN1: {
323 /* TCP_PB_ASN1: handles long (4 bytes) or short length format */
324 const char* tptr = ptr;
325 int length;
326 int nn = n;
327
328 if (n < 2) goto more;
329 nn--;
330 if ((*tptr++ & 0x1f) == 0x1f) { /* Long tag format */
331 while (nn && ((*tptr & 0x80) == 0x80)) {
332 tptr++;
333 nn--;
334 }
335 if (nn < 2) goto more;
336 tptr++;
337 nn--;
338 }
339
340 /* tptr now point to length field and nn characters remain */
341 length = *tptr & 0x7f;
342 if ((*tptr & 0x80) == 0x80) { /* Long length format */
343 tptr++;
344 nn--;
345 if (nn < length) goto more;
346 switch (length) {
347 case 0: plen = 0; break;
348 case 1: plen = get_int8(tptr); tptr += 1; break;
349 case 2: plen = get_int16(tptr); tptr += 2; break;
350 case 3: plen = get_int24(tptr); tptr += 3; break;
351 case 4: plen = get_int32(tptr); tptr += 4; break;
352 default: goto error; /* error */
353 }
354 }
355 else {
356 tptr++;
357 plen = length;
358 }
359 hlen = (tptr-ptr);
360 goto remain;
361 }
362
363 case TCP_PB_CDR: {
364 const struct cdr_head* hp;
365 hlen = sizeof(struct cdr_head);
366 if (n < hlen) goto more;
367 hp = (struct cdr_head*) ptr;
368 if (sys_memcmp(hp->magic, CDR_MAGIC, 4) != 0)
369 goto error;
370 if (hp->flags & 0x01) /* Byte ordering flag */
371 plen = get_little_int32(hp->message_size);
372 else
373 plen = get_int32(hp->message_size);
374 goto remain;
375 }
376
377 case TCP_PB_FCGI: {
378 const struct fcgi_head* hp;
379 hlen = sizeof(struct fcgi_head);
380 if (n < hlen) goto more;
381 hp = (struct fcgi_head*) ptr;
382 if (hp->version != FCGI_VERSION_1)
383 goto error;
384 plen = ((hp->contentLengthB1 << 8) | hp->contentLengthB0)
385 + hp->paddingLength;
386 goto remain;
387 }
388 case TCP_PB_HTTPH:
389 case TCP_PB_HTTPH_BIN:
390 *statep = !0;
391 case TCP_PB_HTTP:
392 case TCP_PB_HTTP_BIN:
393 /* TCP_PB_HTTP: data \r\n(SP data\r\n)* */
394 plen = n;
395 if (((plen == 1) && NL(ptr)) || ((plen == 2) && CRNL(ptr)))
396 goto done;
397 else {
398 const char* ptr1 = ptr;
399 int len = plen;
400
401 if (!max_plen) {
402 /* This is for backward compatibility with old user of decode_packet
403 * that might use option 'line_length' to limit accepted length of
404 * http lines.
405 */
406 max_plen = trunc_len;
407 }
408
409 while (1) {
410 const char* ptr2 = memchr(ptr1, '\n', len);
411
412 if (ptr2 == NULL) {
413 if (max_plen != 0) {
414 if (n >= max_plen) /* packet full */
415 goto error;
416 }
417 goto more;
418 }
419 else {
420 plen = (ptr2 - ptr) + 1;
421
422 if (*statep == 0) {
423 if (max_plen != 0 && plen > max_plen)
424 goto error;
425 goto done;
426 }
427
428 if (plen < n) {
429 if (SP(ptr2+1) && plen>2) {
430 /* header field value continue on next line */
431 ptr1 = ptr2+1;
432 len = n - plen;
433 }
434 else {
435 if (max_plen != 0 && plen > max_plen)
436 goto error;
437 goto done;
438 }
439 }
440 else {
441 if (max_plen != 0 && plen > max_plen)
442 goto error;
443 goto more;
444 }
445 }
446 }
447 }
448 case TCP_PB_TPKT: {
449 const struct tpkt_head* hp;
450 hlen = sizeof(struct tpkt_head);
451 if (n < hlen)
452 goto more;
453 hp = (struct tpkt_head*) ptr;
454 if (hp->vrsn == TPKT_VRSN) {
455 plen = get_int16(hp->packet_length) - hlen;
456 } else {
457 goto error;
458 }
459 goto remain;
460 }
461
462 case TCP_PB_SSL_TLS:
463 hlen = 5;
464 if (n < hlen) goto more;
465 if ((ptr[0] & 0x80) && ptr[2] == 1) {
466 /* Ssl-v2 Client hello <<1:1, Len:15, 1:8, Version:16>> */
467 plen = (get_int16(&ptr[0]) & 0x7fff) - 3;
468 }
469 else {
470 /* <<ContentType:8, Version:16, Length:16>> */
471 plen = get_int16(&ptr[3]);
472 }
473 goto remain;
474
475 default:
476 DEBUGF((" => case error\r\n"));
477 return -1;
478 }
479
480 more:
481 return 0;
482
483 remain:
484 {
485 int tlen = hlen + plen;
486 if ((max_plen != 0 && plen > max_plen)
487 || tlen < (int)hlen) { /* wrap-around protection */
488 return -1;
489 }
490 return tlen;
491 }
492
493 done:
494 return plen;
495
496 error:
497 return -1;
498 }
499
500
http_hash_lookup(const char * name,int len,unsigned long h,http_atom_t ** hash,int hsize)501 static http_atom_t* http_hash_lookup(const char* name, int len,
502 unsigned long h,
503 http_atom_t** hash, int hsize)
504 {
505 int ix = h % hsize;
506 http_atom_t* ap = hash[ix];
507
508 while (ap != NULL) {
509 if ((ap->h == h) && (ap->len == len) &&
510 (sys_strncmp(ap->name, name, len) == 0))
511 return ap;
512 ap = ap->next;
513 }
514 return NULL;
515 }
516
517 static void
http_parse_absoluteURI(PacketHttpURI * uri,const char * uri_ptr,int uri_len)518 http_parse_absoluteURI(PacketHttpURI* uri, const char* uri_ptr, int uri_len)
519 {
520 const char* p;
521
522 if ((p = memchr(uri_ptr, '/', uri_len)) == NULL) {
523 /* host [":" port] */
524 uri->s2_ptr = "/";
525 uri->s2_len = 1;
526 }
527 else {
528 int n = (p - uri_ptr);
529 uri->s2_ptr = p;
530 uri->s2_len = uri_len - n;
531 uri_len = n;
532 }
533
534 uri->s1_ptr = uri_ptr;
535 uri->port = 0; /* undefined */
536 /* host[:port] */
537 if ((p = memchr(uri_ptr, ':', uri_len)) == NULL) {
538 uri->s1_len = uri_len;
539 }
540 else {
541 int n = (p - uri_ptr);
542 int port = 0;
543 uri->s1_len = n;
544 n = uri_len - (n+1);
545 p++;
546 while(n && isdigit((int) *p)) {
547 port = port*10 + (*p - '0');
548 n--;
549 p++;
550 }
551 if (n==0 && port!=0)
552 uri->port = port;
553 }
554 }
555
556 /*
557 ** Handle URI syntax:
558 **
559 ** Request-URI = "*" | absoluteURI | abs_path
560 ** absoluteURI = scheme ":" *( uchar | reserved )
561 ** net_path = "//" net_loc [ abs_path ]
562 ** abs_path = "/" rel_path
563 ** rel_path = [ path ] [ ";" params ] [ "?" query ]
564 ** path = fsegment *( "/" segment )
565 ** fsegment = 1*pchar
566 ** segment = *pchar
567 ** params = param *( ";" param )
568 ** param = *( pchar | "/" )
569 ** query = *( uchar | reserved )
570 **
571 ** http_URL = "http:" "//" host [ ":" port ] [ abs_path ]
572 **
573 ** host = <A legal Internet host domain name
574 ** or IP address (in dotted-decimal form),
575 ** as defined by Section 2.1 of RFC 1123>
576 ** port = *DIGIT
577 **
578 ** {absoluteURI, <scheme>, <host>, <port>, <path+params+query>}
579 ** when <scheme> = http | https
580 ** {scheme, <scheme>, <chars>}
581 ** wheb <scheme> is something else then http or https
582 ** {abs_path, <path>}
583 **
584 ** <string> (unknown form)
585 **
586 */
http_parse_uri(PacketHttpURI * uri,const char * uri_ptr,int uri_len)587 static void http_parse_uri(PacketHttpURI* uri, const char* uri_ptr, int uri_len)
588 {
589 if ((uri_len == 1) && (uri_ptr[0] == '*'))
590 uri->type = URI_STAR;
591 else if ((uri_len <= 1) || (uri_ptr[0] == '/')) {
592 uri->type = URI_ABS_PATH;
593 uri->s1_ptr = uri_ptr;
594 uri->s1_len = uri_len;
595 }
596 else if ((uri_len>=7) && (STRNCASECMP(uri_ptr, "http://", 7) == 0)) {
597 uri_len -= 7;
598 uri_ptr += 7;
599 uri->type = URI_HTTP;
600 http_parse_absoluteURI(uri, uri_ptr, uri_len);
601 }
602 else if ((uri_len>=8) && (STRNCASECMP(uri_ptr, "https://", 8) == 0)) {
603 uri_len -= 8;
604 uri_ptr += 8;
605 uri->type = URI_HTTPS;
606 http_parse_absoluteURI(uri, uri_ptr, uri_len);
607 }
608 else {
609 char* ptr;
610 if ((ptr = memchr(uri_ptr, ':', uri_len)) == NULL) {
611 uri->type = URI_STRING;
612 uri->s1_ptr = uri_ptr;
613 uri->s1_len = uri_len;
614 }
615 else {
616 int slen = ptr - uri_ptr;
617 uri->type = URI_SCHEME;
618 uri->s1_ptr = uri_ptr;
619 uri->s1_len = slen;
620 uri->s2_ptr = uri_ptr + (slen+1);
621 uri->s2_len = uri_len - (slen+1);
622 }
623 }
624 }
625
626 /*
627 ** parse http message:
628 ** http_eoh - end of headers
629 ** {http_header, Key, Value} - Key = atom() | string()
630 ** {http_request, Method,Url,Version}
631 ** {http_response, Version, Status, Message}
632 ** {http_error, Error-Line}
633 */
packet_parse_http(const char * buf,int len,int * statep,PacketCallbacks * pcb,void * arg)634 int packet_parse_http(const char* buf, int len, int* statep,
635 PacketCallbacks* pcb, void* arg)
636 {
637 const char* ptr = buf;
638 const char* p0;
639 int n = len;
640
641 /* remove trailing CRNL (accept NL as well) */
642 if ((n >= 2) && (buf[n-2] == '\r'))
643 n -= 2;
644 else if ((n >= 1) && (buf[n-1] == '\n'))
645 n -= 1;
646
647 if (*statep == 0) {
648 /* start-line = Request-Line | Status-Line */
649
650 if (n >= 5 && (sys_strncmp(buf, "HTTP/", 5) == 0)) {
651 int major = 0;
652 int minor = 0;
653 int status = 0;
654 /* Status-Line = HTTP-Version SP
655 * Status-Code SP Reason-Phrase
656 * CRNL
657 * HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT
658 */
659 ptr += 5;
660 n -= 5;
661 p0 = ptr;
662 while (n && isdigit((int) *ptr)) {
663 major = 10*major + (*ptr - '0');
664 ptr++;
665 n--;
666 }
667 if (ptr==p0 || !n || (*ptr != '.'))
668 return -1;
669 ptr++;
670 n--;
671 p0 = ptr;
672 while (n && isdigit((int) *ptr)) {
673 minor = 10*minor + (*ptr - '0');
674 ptr++;
675 n--;
676 }
677 if (ptr==p0) return -1;
678 p0 = ptr;
679 while (n && SP(ptr)) {
680 ptr++; n--;
681 }
682 if (ptr==p0) return -1;
683
684 while (n && isdigit((int) *ptr)) {
685 status = 10*status + (*ptr - '0');
686 ptr++;
687 n--;
688 }
689 p0 = ptr;
690 while (n && SP(ptr)) {
691 ptr++; n--;
692 }
693 if (ptr==p0 && n>0) return -1;
694
695 /* NOTE: the syntax allows empty reason phrases */
696 (*statep) = !0;
697
698 return pcb->http_response(arg, major, minor, status,
699 ptr, n);
700 }
701 else {
702 /* Request-Line = Method SP Request-URI SP HTTP-Version CRLF */
703 http_atom_t* meth;
704 const char* meth_ptr = buf;
705 int meth_len;
706 PacketHttpURI uri;
707 const char* uri_ptr;
708 int uri_len;
709 int major = 0;
710 int minor = 0;
711 unsigned long h = 0;
712
713 while (n && !is_tspecial((unsigned char)*ptr)) {
714 hash_update(h, (int)*ptr);
715 ptr++;
716 n--;
717 }
718 meth_len = ptr - meth_ptr;
719 if (n == 0 || meth_len == 0 || !SP(ptr)) return -1;
720
721 meth = http_hash_lookup(meth_ptr, meth_len, h,
722 http_meth_hash, HTTP_METH_HASH_SIZE);
723
724 while (n && SP(ptr)) {
725 ptr++; n--;
726 }
727 uri_ptr = ptr;
728 while (n && !SP(ptr)) {
729 ptr++; n--;
730 }
731 if ((uri_len = (ptr - uri_ptr)) == 0)
732 return -1;
733 while (n && SP(ptr)) {
734 ptr++; n--;
735 }
736 if (n == 0) {
737 (*statep) = !0;
738 http_parse_uri(&uri, uri_ptr, uri_len);
739 return pcb->http_request(arg, meth, meth_ptr, meth_len,
740 &uri, 0, 9);
741 }
742 if (n < 8)
743 return -1;
744 if (sys_strncmp(ptr, "HTTP/", 5) != 0)
745 return -1;
746 ptr += 5;
747 n -= 5;
748
749 p0 = ptr;
750 while (n && isdigit((int) *ptr)) {
751 major = 10*major + (*ptr - '0');
752 ptr++;
753 n--;
754 }
755 if (ptr==p0 || !n || (*ptr != '.'))
756 return -1;
757 ptr++;
758 n--;
759 p0 = ptr;
760 while (n && isdigit((int) *ptr)) {
761 minor = 10*minor + (*ptr - '0');
762 ptr++;
763 n--;
764 }
765 if (ptr==p0) return -1;
766
767 (*statep) = !0;
768 http_parse_uri(&uri, uri_ptr, uri_len);
769 return pcb->http_request(arg, meth, meth_ptr, meth_len,
770 &uri, major, minor);
771 }
772 }
773 else {
774 int up = 1; /* make next char uppercase */
775 http_atom_t* name;
776 char name_buf[HTTP_MAX_NAME_LEN];
777 const char* name_ptr = name_buf;
778 int name_len;
779 unsigned long h;
780
781 if (n == 0) {
782 /* end of headers */
783 *statep = 0; /* reset state (for next request) */
784 return pcb->http_eoh(arg);
785 }
786 h = 0;
787 name_len = 0;
788 while (!is_tspecial((unsigned char)*ptr)) {
789 if (name_len < HTTP_MAX_NAME_LEN) {
790 int c = *ptr;
791 if (up) {
792 if (islower(c)) {
793 c = toupper(c);
794 }
795 up = 0;
796 }
797 else {
798 if (isupper(c))
799 c = tolower(c);
800 else if (c == '-')
801 up = 1;
802 }
803 name_buf[name_len] = c;
804 hash_update(h, c);
805 }
806 name_len++;
807 ptr++;
808 if (--n == 0) return -1;
809 }
810 if (*ptr != ':') {
811 return -1;
812 }
813 if (name_len <= HTTP_MAX_NAME_LEN) {
814 name = http_hash_lookup(name_buf, name_len, h,
815 http_hdr_hash, HTTP_HDR_HASH_SIZE);
816 }
817 else {
818 /* Is it ok to return original name without case adjustments? */
819 name_ptr = buf;
820 name = NULL;
821 }
822 ptr++;
823 n--;
824 /* Skip white space after ':' */
825 while (n && SP(ptr)) {
826 ptr++; n--;
827 }
828 return pcb->http_header(arg, name,
829 name_ptr, name_len,
830 buf, name_len,
831 ptr, n);
832 }
833 return -1;
834 }
835
packet_parse_ssl(const char * buf,int len,PacketCallbacks * pcb,void * arg)836 int packet_parse_ssl(const char* buf, int len,
837 PacketCallbacks* pcb, void* arg)
838 {
839 /* Check for ssl-v2 client hello */
840 if ((buf[0] & 0x80) && buf[2] == 1) {
841 unsigned major = (unsigned char) buf[3];
842 unsigned minor = (unsigned char) buf[4];
843 char prefix[4];
844 /* <<1:8,Length:24,Data/binary>> */
845 prefix[0] = 1;
846 put_int24(len-3,&prefix[1]);
847 return pcb->ssl_tls(arg, 22, major, minor, buf+3, len-3, prefix, sizeof(prefix));
848 }
849 else {
850 /* ContentType (1 byte), ProtocolVersion (2 bytes), Length (2 bytes big-endian) */
851 unsigned type = (unsigned char) buf[0];
852 unsigned major = (unsigned char) buf[1];
853 unsigned minor = (unsigned char) buf[2];
854 return pcb->ssl_tls(arg, type, major, minor, buf+5, len-5, NULL, 0);
855 }
856 }
857
858