• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (C) 2007-2008 The Android Open Source Project
2 **
3 ** This software is licensed under the terms of the GNU General Public
4 ** License version 2, as published by the Free Software Foundation, and
5 ** may be copied, distributed, and modified under those terms.
6 **
7 ** This program is distributed in the hope that it will be useful,
8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 ** GNU General Public License for more details.
11 */
12 #include "proxy_http_int.h"
13 #include <stdio.h>
14 #include <string.h>
15 #include "qemu-common.h"
16 #include "android/utils/system.h"  /* strsep */
17 
18 /* this implements a transparent HTTP rewriting proxy
19  *
20  * this is needed because the HTTP spec mandates that
21  * any query made to a proxy uses an absolute URI as
22  * in:
23  *
24  *    GET http://www.example.com/index.html HTTP/1.1
25  *
26  * while the Android browser will think it's talking to
27  * a normal web server and will issue a:
28  *
29  *    GET /index.html HTTP/1.1
30  *    Host: www.example.com
31  *
32  * what we do here is thus the following:
33  *
34  * - read the request header
35  * - rewrite the request's URI to use absolute URI
36  * - send the rewritten header to the proxy
37  * - then read the rest of the request, and tunnel it to the
38  *   proxy as well
39  * - read the answer as-is and send it back to the system
40  *
41  * this sounds all easy, but the rules for computing the
42  * sizes of HTTP Message Bodies makes the implementation
43  * a *bit* funky.
44  */
45 
46 /* define D_ACTIVE to 1 to dump additionnal debugging
47  * info when -debug-proxy is used. These are only needed
48  * when debugging the proxy code.
49  */
50 #define  D_ACTIVE  1
51 
52 #if D_ACTIVE
53 #  define  D(...)   PROXY_LOG(__VA_ARGS__)
54 #else
55 #  define  D(...)   ((void)0)
56 #endif
57 
58 
59 /** *************************************************************
60  **
61  **   HTTP HEADERS
62  **
63  **/
64 
65 /* HttpHeader is a simple structure used to hold a (key,value)
66  * pair in a linked list.
67  */
68 typedef struct HttpHeader {
69     struct HttpHeader*  next;
70     const char*         key;
71     const char*         value;
72 } HttpHeader;
73 
74 static void
http_header_free(HttpHeader * h)75 http_header_free( HttpHeader*  h )
76 {
77     if (h) {
78         qemu_free((char*)h->value);
79         qemu_free(h);
80     }
81 }
82 
83 static int
http_header_append(HttpHeader * h,const char * value)84 http_header_append( HttpHeader*  h, const char*  value )
85 {
86     int    old = strlen(h->value);
87     int    new = strlen(value);
88     char*  s   = realloc((char*)h->value, old+new+1);
89     if (s == NULL)
90         return -1;
91     memcpy(s + old, value, new+1);
92     h->value = (const char*)s;
93     return 0;
94 }
95 
96 static HttpHeader*
http_header_alloc(const char * key,const char * value)97 http_header_alloc( const char*  key, const char*  value )
98 {
99     int          len = strlen(key)+1;
100     HttpHeader*  h   = malloc(sizeof(*h) + len+1);
101     if (h) {
102         h->next  = NULL;
103         h->key   = (const char*)(h+1);
104         memcpy( (char*)h->key, key, len );
105         h->value = qemu_strdup(value);
106     }
107     return h;
108 }
109 
110 /** *************************************************************
111  **
112  **   HTTP HEADERS LIST
113  **
114  **/
115 
116 typedef struct {
117     HttpHeader*   first;
118     HttpHeader*   last;
119 } HttpHeaderList;
120 
121 static void
http_header_list_init(HttpHeaderList * l)122 http_header_list_init( HttpHeaderList*  l )
123 {
124     l->first = l->last = NULL;
125 }
126 
127 static void
http_header_list_done(HttpHeaderList * l)128 http_header_list_done( HttpHeaderList*  l )
129 {
130     while (l->first) {
131         HttpHeader*  h = l->first;
132         l->first = h->next;
133         http_header_free(h);
134     }
135     l->last = NULL;
136 }
137 
138 static void
http_header_list_add(HttpHeaderList * l,HttpHeader * h)139 http_header_list_add( HttpHeaderList*  l,
140                       HttpHeader*      h )
141 {
142     if (!l->first) {
143         l->first = h;
144     } else {
145         l->last->next = h;
146     }
147     h->next = NULL;
148     l->last = h;
149 }
150 
151 static const char*
http_header_list_find(HttpHeaderList * l,const char * key)152 http_header_list_find( HttpHeaderList*  l,
153                        const char*      key )
154 {
155     HttpHeader*  h;
156     for (h = l->first; h; h = h->next)
157         if (!strcasecmp(h->key, key))
158             return h->value;
159 
160     return NULL;
161 }
162 
163 /** *************************************************************
164  **
165  **   HTTP REQUEST AND REPLY
166  **
167  **/
168 
169 typedef enum {
170     HTTP_REQUEST_UNSUPPORTED = 0,
171     HTTP_REQUEST_GET,
172     HTTP_REQUEST_HEAD,
173     HTTP_REQUEST_POST,
174     HTTP_REQUEST_PUT,
175     HTTP_REQUEST_DELETE,
176 } HttpRequestType;
177 
178 /* HttpRequest is used both to store information about a specific
179  * request and the corresponding reply
180  */
181 typedef struct {
182     HttpRequestType   req_type;     /* request type */
183     char*             req_method;   /* "GET", "POST", "HEAD", etc... */
184     char*             req_uri;      /* the request URI */
185     char*             req_version;  /* "HTTP/1.0" or "HTTP/1.1" */
186     char*             rep_version;  /* reply version string */
187     int               rep_code;     /* reply code as decimal */
188     char*             rep_readable; /* human-friendly reply/error message */
189     HttpHeaderList    headers[1];   /* headers */
190 } HttpRequest;
191 
192 
193 static HttpRequest*
http_request_alloc(const char * method,const char * uri,const char * version)194 http_request_alloc( const char*      method,
195                     const char*      uri,
196                     const char*      version )
197 {
198     HttpRequest*  r = malloc(sizeof(*r));
199 
200     r->req_method   = qemu_strdup(method);
201     r->req_uri      = qemu_strdup(uri);
202     r->req_version  = qemu_strdup(version);
203     r->rep_version  = NULL;
204     r->rep_code     = -1;
205     r->rep_readable = NULL;
206 
207     if (!strcmp(method,"GET")) {
208         r->req_type = HTTP_REQUEST_GET;
209     } else if (!strcmp(method,"POST")) {
210         r->req_type = HTTP_REQUEST_POST;
211     } else if (!strcmp(method,"HEAD")) {
212         r->req_type = HTTP_REQUEST_HEAD;
213     } else if (!strcmp(method,"PUT")) {
214         r->req_type = HTTP_REQUEST_PUT;
215     } else if (!strcmp(method,"DELETE")) {
216         r->req_type = HTTP_REQUEST_DELETE;
217     } else
218         r->req_type = HTTP_REQUEST_UNSUPPORTED;
219 
220     http_header_list_init(r->headers);
221     return r;
222 }
223 
224 static void
http_request_replace_uri(HttpRequest * r,const char * uri)225 http_request_replace_uri( HttpRequest*  r,
226                           const char*   uri )
227 {
228     const char*  old = r->req_uri;
229     r->req_uri = qemu_strdup(uri);
230     qemu_free((char*)old);
231 }
232 
233 static void
http_request_free(HttpRequest * r)234 http_request_free( HttpRequest*  r )
235 {
236     if (r) {
237         http_header_list_done(r->headers);
238 
239         qemu_free(r->req_method);
240         qemu_free(r->req_uri);
241         qemu_free(r->req_version);
242         qemu_free(r->rep_version);
243         qemu_free(r->rep_readable);
244         qemu_free(r);
245     }
246 }
247 
248 static char*
http_request_find_header(HttpRequest * r,const char * key)249 http_request_find_header( HttpRequest*  r,
250                           const char*   key )
251 {
252     return (char*)http_header_list_find(r->headers, key);
253 }
254 
255 
256 static int
http_request_add_header(HttpRequest * r,const char * key,const char * value)257 http_request_add_header( HttpRequest*  r,
258                          const char*   key,
259                          const char*   value )
260 {
261     HttpHeader*  h = http_header_alloc(key,value);
262     if (h) {
263         http_header_list_add(r->headers, h);
264         return 0;
265     }
266     return -1;
267 }
268 
269 static int
http_request_add_to_last_header(HttpRequest * r,const char * line)270 http_request_add_to_last_header( HttpRequest*  r,
271                                  const char*   line )
272 {
273     if (r->headers->last) {
274         return http_header_append( r->headers->last, line );
275     } else {
276         return -1;
277     }
278 }
279 
280 static int
http_request_set_reply(HttpRequest * r,const char * version,const char * code,const char * readable)281 http_request_set_reply( HttpRequest*  r,
282                         const char*   version,
283                         const char*   code,
284                         const char*   readable )
285 {
286     if (strcmp(version,"HTTP/1.0") && strcmp(version,"HTTP/1.1")) {
287         PROXY_LOG("%s: bad reply protocol: %s", __FUNCTION__, version);
288         return -1;
289     }
290     r->rep_code = atoi(code);
291     if (r->rep_code == 0) {
292         PROXY_LOG("%s: bad reply code: %d", __FUNCTION__, code);
293         return -1;
294     }
295 
296     r->rep_version  = qemu_strdup(version);
297     r->rep_readable = qemu_strdup(readable);
298 
299     /* reset the list of headers */
300     http_header_list_done(r->headers);
301     return 0;
302 }
303 
304 /** *************************************************************
305  **
306  **   REWRITER CONNECTION
307  **
308  **/
309 
310 typedef enum {
311     STATE_CONNECTING = 0,
312     STATE_CREATE_SOCKET_PAIR,
313     STATE_REQUEST_FIRST_LINE,
314     STATE_REQUEST_HEADERS,
315     STATE_REQUEST_SEND,
316     STATE_REQUEST_BODY,
317     STATE_REPLY_FIRST_LINE,
318     STATE_REPLY_HEADERS,
319     STATE_REPLY_SEND,
320     STATE_REPLY_BODY,
321 } ConnectionState;
322 
323 /* root->socket is connected to the proxy server. while
324  * slirp_fd is connected to the slirp code through a
325  * socket_pair() we created for this specific purpose.
326  */
327 
328 typedef enum {
329     BODY_NONE = 0,
330     BODY_KNOWN_LENGTH,
331     BODY_UNTIL_CLOSE,
332     BODY_CHUNKED,
333     BODY_MODE_MAX
334 } BodyMode;
335 
336 static const char* const  body_mode_str[BODY_MODE_MAX] = {
337     "NONE", "KNOWN_LENGTH", "UNTIL_CLOSE", "CHUNKED"
338 };
339 
340 enum {
341     CHUNK_HEADER,    // Waiting for a chunk header + CR LF
342     CHUNK_DATA,      // Waiting for chunk data
343     CHUNK_DATA_END,  // Waiting for the CR LF after the chunk data
344     CHUNK_TRAILER    // Waiting for the chunk trailer + CR LF
345 };
346 
347 typedef struct {
348     ProxyConnection   root[1];
349     int               slirp_fd;
350     ConnectionState   state;
351     HttpRequest*      request;
352     BodyMode          body_mode;
353     int64_t           body_length;
354     int64_t           body_total;
355     int64_t           body_sent;
356     int64_t           chunk_length;
357     int64_t           chunk_total;
358     int               chunk_state;
359     char              body_has_data;
360     char              body_is_full;
361     char              body_is_closed;
362     char              parse_chunk_header;
363     char              parse_chunk_trailer;
364 } RewriteConnection;
365 
366 
367 static void
rewrite_connection_free(ProxyConnection * root)368 rewrite_connection_free( ProxyConnection*  root )
369 {
370     RewriteConnection*  conn = (RewriteConnection*)root;
371 
372     if (conn->slirp_fd >= 0) {
373         socket_close(conn->slirp_fd);
374         conn->slirp_fd = -1;
375     }
376     http_request_free(conn->request);
377     proxy_connection_done(root);
378     qemu_free(conn);
379 }
380 
381 
382 static int
rewrite_connection_init(RewriteConnection * conn)383 rewrite_connection_init( RewriteConnection*   conn )
384 {
385     HttpService*      service = (HttpService*) conn->root->service;
386     ProxyConnection*  root    = conn->root;
387 
388     conn->slirp_fd = -1;
389     conn->state    = STATE_CONNECTING;
390 
391     if (socket_connect( root->socket, &service->server_addr ) < 0) {
392         if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) {
393             PROXY_LOG("%s: connecting", conn->root->name);
394         }
395         else {
396             PROXY_LOG("%s: cannot connect to proxy: %s", root->name, errno_str);
397             return -1;
398         }
399     }
400     else {
401         PROXY_LOG("%s: immediate connection", root->name);
402         conn->state = STATE_CREATE_SOCKET_PAIR;
403     }
404     return 0;
405 }
406 
407 static int
rewrite_connection_create_sockets(RewriteConnection * conn)408 rewrite_connection_create_sockets( RewriteConnection*  conn )
409 {
410     /* immediate connection to the proxy. now create a socket
411         * pair and send a 'success' event to slirp */
412     int               slirp_1;
413     ProxyConnection*  root = conn->root;
414 
415     if (socket_pair( &slirp_1, &conn->slirp_fd ) < 0) {
416         PROXY_LOG("%s: coult not create socket pair: %s",
417                     root->name, errno_str);
418         return -1;
419     }
420 
421     root->ev_func( root->ev_opaque, slirp_1, PROXY_EVENT_CONNECTED );
422     conn->state = STATE_REQUEST_FIRST_LINE;
423     return 0;
424 }
425 
426 
427 /* read the first line of a given HTTP request. returns -1/0/+1 */
428 static DataStatus
rewrite_connection_read_request(RewriteConnection * conn)429 rewrite_connection_read_request( RewriteConnection*  conn )
430 {
431     ProxyConnection*  root = conn->root;
432     DataStatus        ret;
433 
434     ret = proxy_connection_receive_line(root, conn->slirp_fd);
435     if (ret == DATA_COMPLETED) {
436         /* now parse the first line to see if we can handle it */
437         char*  line   = root->str->s;
438         char*  method;
439         char*  uri;
440         char*  version;
441         char*  p = line;
442 
443         method = strsep(&p, " ");
444         if (p == NULL) {
445             PROXY_LOG("%s: can't parse method in '%'",
446                       root->name, line);
447             return DATA_ERROR;
448         }
449         uri = strsep(&p, " ");
450         if (p == NULL) {
451             PROXY_LOG( "%s: can't parse URI in '%s'",
452                        root->name, line);
453             return DATA_ERROR;
454         }
455         version = strsep(&p, " ");
456         if (p != NULL) {
457             PROXY_LOG( "%s: extra data after version in '%s'",
458                        root->name, line);
459             return DATA_ERROR;
460         }
461         if (conn->request)
462             http_request_free(conn->request);
463 
464         conn->request = http_request_alloc( method, uri, version );
465         if (!conn->request)
466             return DATA_ERROR;
467 
468         proxy_connection_rewind(root);
469     }
470     return ret;
471 }
472 
473 
474 static DataStatus
rewrite_connection_read_reply(RewriteConnection * conn)475 rewrite_connection_read_reply( RewriteConnection*  conn )
476 {
477     ProxyConnection*  root = conn->root;
478     DataStatus        ret;
479 
480     ret = proxy_connection_receive_line( root, root->socket );
481     if (ret == DATA_COMPLETED) {
482         HttpRequest*  request = conn->request;
483 
484         char*  line = stralloc_cstr( root->str );
485         char*  p = line;
486         char*  protocol;
487         char*  number;
488         char*  readable;
489 
490         protocol = strsep(&p, " ");
491         if (p == NULL) {
492             PROXY_LOG("%s: can't parse response protocol: '%s'",
493                       root->name, line);
494             return DATA_ERROR;
495         }
496         number = strsep(&p, " ");
497         if (p == NULL) {
498             PROXY_LOG("%s: can't parse response number: '%s'",
499                       root->name, line);
500             return DATA_ERROR;
501         }
502         readable = p;
503 
504         if (http_request_set_reply(request, protocol, number, readable) < 0)
505             return DATA_ERROR;
506 
507         proxy_connection_rewind(root);
508     }
509     return ret;
510 }
511 
512 
513 static DataStatus
rewrite_connection_read_headers(RewriteConnection * conn,int fd)514 rewrite_connection_read_headers( RewriteConnection*   conn,
515                                  int                  fd )
516 {
517     int               ret;
518     ProxyConnection*  root = conn->root;
519 
520     for (;;) {
521         char*        line;
522         stralloc_t*  str = root->str;
523 
524         ret = proxy_connection_receive_line(root, fd);
525         if (ret != DATA_COMPLETED)
526             break;
527 
528         str->n = 0;
529         line   = str->s;
530 
531         if (line[0] == 0) {
532             /* an empty line means the end of headers */
533             ret = 1;
534             break;
535         }
536 
537         /* it this a continuation ? */
538         if (line[0] == ' ' || line[0] == '\t') {
539             ret = http_request_add_to_last_header( conn->request, line );
540         }
541         else {
542             char*  key;
543             char*  value;
544 
545             value = line;
546             key   = strsep(&value, ":");
547             if (value == NULL) {
548                 PROXY_LOG("%s: can't parse header '%s'", root->name, line);
549                 ret = -1;
550                 break;
551             }
552             value += strspn(value, " ");
553             if (http_request_add_header(conn->request, key, value) < 0)
554                 ret = -1;
555         }
556         if (ret == DATA_ERROR)
557             break;
558     }
559     return ret;
560 }
561 
562 static int
rewrite_connection_rewrite_request(RewriteConnection * conn)563 rewrite_connection_rewrite_request( RewriteConnection*  conn )
564 {
565     ProxyConnection* root    = conn->root;
566     HttpService*     service = (HttpService*) root->service;
567     HttpRequest*     r       = conn->request;
568     stralloc_t*      str     = root->str;
569     HttpHeader*      h;
570 
571     proxy_connection_rewind(conn->root);
572 
573     /* only rewrite the URI if it is not absolute */
574     if (r->req_uri[0] == '/') {
575         char*  host = http_request_find_header(r, "Host");
576         if (host == NULL) {
577             PROXY_LOG("%s: uh oh, not Host: in request ?", root->name);
578         } else {
579             /* now create new URI */
580             stralloc_add_str(str, "http://");
581             stralloc_add_str(str, host);
582             stralloc_add_str(str, r->req_uri);
583             http_request_replace_uri(r, stralloc_cstr(str));
584             proxy_connection_rewind(root);
585         }
586     }
587 
588     stralloc_format( str, "%s %s %s\r\n", r->req_method, r->req_uri, r->req_version );
589     for (h = r->headers->first; h; h = h->next) {
590         stralloc_add_format( str, "%s: %s\r\n", h->key, h->value );
591     }
592     /* add the service's footer - includes final \r\n */
593     stralloc_add_bytes( str, service->footer, service->footer_len );
594 
595     return 0;
596 }
597 
598 static int
rewrite_connection_rewrite_reply(RewriteConnection * conn)599 rewrite_connection_rewrite_reply( RewriteConnection*  conn )
600 {
601     HttpRequest*     r    = conn->request;
602     ProxyConnection* root = conn->root;
603     stralloc_t*      str  = root->str;
604     HttpHeader*      h;
605 
606     proxy_connection_rewind(root);
607     stralloc_format(str, "%s %d %s\r\n", r->rep_version, r->rep_code, r->rep_readable);
608     for (h = r->headers->first; h; h = h->next) {
609         stralloc_add_format(str, "%s: %s\r\n", h->key, h->value);
610     }
611     stralloc_add_str(str, "\r\n");
612 
613     return 0;
614 }
615 
616 
617 static int
rewrite_connection_get_body_length(RewriteConnection * conn,int is_request)618 rewrite_connection_get_body_length( RewriteConnection*  conn,
619                                     int                 is_request )
620 {
621     HttpRequest*      r    = conn->request;
622     ProxyConnection*  root = conn->root;
623     char*             content_length;
624     char*             transfer_encoding;
625 
626     conn->body_mode      = BODY_NONE;
627     conn->body_length    = 0;
628     conn->body_total     = 0;
629     conn->body_sent      = 0;
630     conn->body_is_closed = 0;
631     conn->body_is_full   = 0;
632     conn->body_has_data  = 0;
633 
634     proxy_connection_rewind(root);
635 
636     if (is_request) {
637         /* only POST and PUT should have a body */
638         if (r->req_type != HTTP_REQUEST_POST &&
639             r->req_type != HTTP_REQUEST_PUT)
640         {
641             return 0;
642         }
643     } else {
644         /* HTTP 1.1 Section 4.3 Message Body states that HEAD requests must not have
645         * a message body, as well as any 1xx, 204 and 304 replies */
646         if (r->req_type == HTTP_REQUEST_HEAD || r->rep_code/100 == 1 ||
647             r->rep_code == 204 || r->rep_code == 304)
648             return 0;
649     }
650 
651     content_length = http_request_find_header(r, "Content-Length");
652     if (content_length != NULL) {
653         char*    end;
654         int64_t  body_len = strtoll( content_length, &end, 10 );
655         if (*end != '\0' || *content_length == '\0' || body_len < 0) {
656             PROXY_LOG("%s: bad content length: %s", root->name, content_length);
657             return DATA_ERROR;
658         }
659         if (body_len > 0) {
660             conn->body_mode   = BODY_KNOWN_LENGTH;
661             conn->body_length = body_len;
662         }
663     } else {
664         transfer_encoding = http_request_find_header(r, "Transfer-Encoding");
665         if (transfer_encoding && !strcasecmp(transfer_encoding, "Chunked")) {
666             conn->body_mode           = BODY_CHUNKED;
667             conn->parse_chunk_header  = 0;
668             conn->parse_chunk_trailer = 0;
669             conn->chunk_length        = -1;
670             conn->chunk_total         = 0;
671             conn->chunk_state         = CHUNK_HEADER;
672         }
673     }
674     if (conn->body_mode == BODY_NONE) {
675         char*  connection = http_request_find_header(r, "Proxy-Connection");
676 
677         if (!connection)
678             connection = http_request_find_header(r, "Connection");
679 
680         if (!connection || strcasecmp(connection, "Close")) {
681             /* hum, we can't support this at all */
682             PROXY_LOG("%s: can't determine content length, and client wants"
683                         " to keep connection opened",
684                         root->name);
685             return -1;
686         }
687         /* a negative value means that the data ends when the client
688          * disconnects the connection.
689          */
690         conn->body_mode = BODY_UNTIL_CLOSE;
691     }
692     D("%s: body_length=%lld body_mode=%s",
693       root->name, conn->body_length,
694       body_mode_str[conn->body_mode]);
695 
696     proxy_connection_rewind(root);
697     return 0;
698 }
699 
700 #define  MAX_BODY_BUFFER  65536
701 
702 static DataStatus
rewrite_connection_read_body(RewriteConnection * conn,int fd)703 rewrite_connection_read_body( RewriteConnection*  conn, int  fd )
704 {
705     ProxyConnection*  root   = conn->root;
706     stralloc_t*       str    = root->str;
707     int               wanted = 0, current, avail;
708     DataStatus        ret;
709 
710     if (conn->body_is_closed) {
711         return DATA_NEED_MORE;
712     }
713 
714     /* first, determine how many bytes we want to read. */
715     switch (conn->body_mode) {
716     case BODY_NONE:
717         D("%s: INTERNAL ERROR: SHOULDN'T BE THERE", root->name);
718         return DATA_COMPLETED;
719 
720     case BODY_KNOWN_LENGTH:
721         {
722             if (conn->body_length == 0)
723                 return DATA_COMPLETED;
724 
725             if (conn->body_length > MAX_BODY_BUFFER)
726                 wanted = MAX_BODY_BUFFER;
727             else
728                 wanted = (int)conn->body_length;
729         }
730         break;
731 
732     case BODY_UNTIL_CLOSE:
733         wanted = MAX_BODY_BUFFER;
734         break;
735 
736     case BODY_CHUNKED:
737         if (conn->chunk_state == CHUNK_DATA_END) {
738             /* We're waiting for the CR LF after the chunk data */
739             ret = proxy_connection_receive_line(root, fd);
740             if (ret != DATA_COMPLETED)
741                 return ret;
742 
743             if (str->s[0] != 0) { /* this should be an empty line */
744                 PROXY_LOG("%s: invalid chunk data end: '%s'",
745                             root->name, str->s);
746                 return DATA_ERROR;
747             }
748             /* proxy_connection_receive_line() did remove the
749             * trailing \r\n, but we must preserve it when we
750             * send the chunk size end to the proxy.
751             */
752             stralloc_add_str(root->str, "\r\n");
753             conn->chunk_state = CHUNK_HEADER;
754             /* fall-through */
755         }
756 
757         if (conn->chunk_state == CHUNK_HEADER) {
758             char*      line;
759             char*      end;
760             long long  length;
761             /* Ensure that the previous chunk was flushed before
762              * accepting a new header */
763             if (!conn->parse_chunk_header) {
764                 if (conn->body_has_data)
765                     return DATA_NEED_MORE;
766                 D("%s: waiting chunk header", root->name);
767                 conn->parse_chunk_header = 1;
768             }
769             ret = proxy_connection_receive_line(root, fd);
770             if (ret != DATA_COMPLETED) {
771                 return ret;
772             }
773             conn->parse_chunk_header = 0;
774 
775             line   = str->s;
776             length = strtoll(line, &end, 16);
777             if (line[0] == ' ' || (end[0] != '\0' && end[0] != ';')) {
778                 PROXY_LOG("%s: invalid chunk header: %s",
779                         root->name, line);
780                 return DATA_ERROR;
781             }
782             if (length < 0) {
783                 PROXY_LOG("%s: invalid chunk length %lld",
784                         root->name, length);
785                 return DATA_ERROR;
786             }
787             /* proxy_connection_receive_line() did remove the
788             * trailing \r\n, but we must preserve it when we
789             * send the chunk size to the proxy.
790             */
791             stralloc_add_str(root->str, "\r\n");
792 
793             conn->chunk_length = length;
794             conn->chunk_total  = 0;
795             conn->chunk_state  = CHUNK_DATA;
796             if (length == 0) {
797                 /* the last chunk, no we need to add the trailer */
798                 conn->chunk_state         = CHUNK_TRAILER;
799                 conn->parse_chunk_trailer = 0;
800             }
801         }
802 
803         if (conn->chunk_state == CHUNK_TRAILER) {
804             /* ensure that 'str' is flushed before reading the trailer */
805             if (!conn->parse_chunk_trailer) {
806                 if (conn->body_has_data)
807                     return DATA_NEED_MORE;
808                 conn->parse_chunk_trailer = 1;
809             }
810             ret = rewrite_connection_read_headers(conn, fd);
811             if (ret == DATA_COMPLETED) {
812                 conn->body_is_closed = 1;
813             }
814             return ret;
815         }
816 
817         /* if we get here, body_length > 0 */
818         if (conn->chunk_length > MAX_BODY_BUFFER)
819             wanted = MAX_BODY_BUFFER;
820         else
821             wanted = (int)conn->chunk_length;
822         break;
823 
824     default:
825         ;
826     }
827 
828     /* we don't want more than MAX_BODY_BUFFER bytes in the
829      * buffer we used to pass the body */
830     current = str->n;
831     avail   = MAX_BODY_BUFFER - current;
832     if (avail <= 0) {
833         /* wait for some flush */
834         conn->body_is_full = 1;
835         D("%s: waiting to flush %d bytes",
836           root->name, current);
837         return DATA_NEED_MORE;
838     }
839 
840     if (wanted > avail)
841         wanted = avail;
842 
843     ret = proxy_connection_receive(root, fd, wanted);
844     conn->body_has_data = (str->n > 0);
845     conn->body_is_full  = (str->n == MAX_BODY_BUFFER);
846 
847     if (ret == DATA_ERROR) {
848         if (conn->body_mode == BODY_UNTIL_CLOSE) {
849             /* a disconnection here is normal and signals the
850              * end of the body */
851             conn->body_total    += root->str_recv;
852             D("%s: body completed by close (%lld bytes)",
853                 root->name, conn->body_total);
854             conn->body_is_closed = 1;
855             ret = DATA_COMPLETED;
856         }
857     } else {
858         avail = root->str_recv;
859         ret   = DATA_NEED_MORE;  /* we're not really done yet */
860 
861         switch (conn->body_mode) {
862         case BODY_CHUNKED:
863             conn->chunk_total  += avail;
864             conn->chunk_length -= avail;
865 
866             if (conn->chunk_length == 0) {
867                 D("%s: chunk completed (%lld bytes)",
868                     root->name, conn->chunk_total);
869                 conn->body_total  += conn->chunk_total;
870                 conn->chunk_total  = 0;
871                 conn->chunk_length = -1;
872                 conn->chunk_state  = CHUNK_DATA;
873             }
874             break;
875 
876         case BODY_KNOWN_LENGTH:
877             conn->body_length -= avail;
878             conn->body_total  += avail;
879 
880             if (conn->body_length == 0) {
881                 D("%s: body completed (%lld bytes)",
882                     root->name, conn->body_total);
883                 conn->body_is_closed = 1;
884                 ret = DATA_COMPLETED;
885             }
886             break;
887 
888         case BODY_UNTIL_CLOSE:
889             conn->body_total += avail;
890             break;
891 
892         default:
893             ;
894         }
895     }
896     return ret;
897 }
898 
899 static DataStatus
rewrite_connection_send_body(RewriteConnection * conn,int fd)900 rewrite_connection_send_body( RewriteConnection*  conn, int  fd )
901 {
902     ProxyConnection*  root   = conn->root;
903     stralloc_t*       str    = root->str;
904     DataStatus        ret    = DATA_NEED_MORE;
905 
906     if (conn->body_has_data) {
907         ret = proxy_connection_send(root, fd);
908         if (ret != DATA_ERROR) {
909             int  pos = root->str_pos;
910 
911             memmove(str->s, str->s+pos, str->n-pos);
912             str->n         -= pos;
913             root->str_pos   = 0;
914             conn->body_is_full  = (str->n == MAX_BODY_BUFFER);
915             conn->body_has_data = (str->n > 0);
916             conn->body_sent    += root->str_sent;
917 
918             /* ensure that we return DATA_COMPLETED only when
919             * we have sent everything, and there is no more
920             * body pieces to read */
921             if (ret == DATA_COMPLETED) {
922                 if (!conn->body_is_closed || conn->body_has_data)
923                     ret = DATA_NEED_MORE;
924                 else {
925                     D("%s: sent all body (%lld bytes)",
926                         root->name, conn->body_sent);
927                 }
928             }
929             D("%s: sent closed=%d data=%d n=%d ret=%d",
930                 root->name, conn->body_is_closed,
931                 conn->body_has_data, str->n,
932                 ret);
933         }
934     }
935     return ret;
936 }
937 
938 
939 static void
rewrite_connection_select(ProxyConnection * root,ProxySelect * sel)940 rewrite_connection_select( ProxyConnection*  root,
941                            ProxySelect*      sel )
942 {
943     RewriteConnection*  conn = (RewriteConnection*)root;
944     int  slirp = conn->slirp_fd;
945     int  proxy = root->socket;
946 
947     switch (conn->state) {
948         case STATE_CONNECTING:
949         case STATE_CREATE_SOCKET_PAIR:
950             /* try to connect to the proxy server */
951             proxy_select_set( sel, proxy, PROXY_SELECT_WRITE );
952             break;
953 
954         case STATE_REQUEST_FIRST_LINE:
955         case STATE_REQUEST_HEADERS:
956             proxy_select_set( sel, slirp, PROXY_SELECT_READ );
957             break;
958 
959         case STATE_REQUEST_SEND:
960             proxy_select_set( sel, proxy, PROXY_SELECT_WRITE );
961             break;
962 
963         case STATE_REQUEST_BODY:
964             if (!conn->body_is_closed && !conn->body_is_full)
965                 proxy_select_set( sel, slirp, PROXY_SELECT_READ );
966 
967             if (conn->body_has_data)
968                 proxy_select_set( sel, proxy, PROXY_SELECT_WRITE );
969             break;
970 
971         case STATE_REPLY_FIRST_LINE:
972         case STATE_REPLY_HEADERS:
973             proxy_select_set( sel, proxy, PROXY_SELECT_READ );
974             break;
975 
976         case STATE_REPLY_SEND:
977             proxy_select_set( sel, slirp, PROXY_SELECT_WRITE );
978             break;
979 
980         case STATE_REPLY_BODY:
981             if (conn->body_has_data)
982                 proxy_select_set( sel, slirp, PROXY_SELECT_WRITE );
983 
984             if (!conn->body_is_closed && !conn->body_is_full)
985                 proxy_select_set( sel, proxy, PROXY_SELECT_READ );
986             break;
987         default:
988             ;
989     };
990 }
991 
992 static void
rewrite_connection_poll(ProxyConnection * root,ProxySelect * sel)993 rewrite_connection_poll( ProxyConnection*  root,
994                          ProxySelect*      sel )
995 {
996     RewriteConnection*  conn = (RewriteConnection*)root;
997 
998     int         slirp     = conn->slirp_fd;
999     int         proxy     = root->socket;
1000     int         has_slirp = proxy_select_poll(sel, slirp);
1001     int         has_proxy = proxy_select_poll(sel, proxy);
1002     DataStatus  ret       = DATA_NEED_MORE;
1003 
1004     switch (conn->state) {
1005         case STATE_CONNECTING:
1006             if (has_proxy) {
1007                 PROXY_LOG("%s: connected to proxy", root->name);
1008                 conn->state = STATE_CREATE_SOCKET_PAIR;
1009             }
1010             break;
1011 
1012         case STATE_CREATE_SOCKET_PAIR:
1013             if (has_proxy) {
1014                 if (rewrite_connection_create_sockets(conn) < 0) {
1015                     ret = DATA_ERROR;
1016                 } else {
1017                     D("%s: socket pair created", root->name);
1018                     conn->state = STATE_REQUEST_FIRST_LINE;
1019                 }
1020             }
1021             break;
1022 
1023         case STATE_REQUEST_FIRST_LINE:
1024             if (has_slirp) {
1025                 ret = rewrite_connection_read_request(conn);
1026                 if (ret == DATA_COMPLETED) {
1027                     PROXY_LOG("%s: request first line ok", root->name);
1028                     conn->state = STATE_REQUEST_HEADERS;
1029                 }
1030             }
1031             break;
1032 
1033         case STATE_REQUEST_HEADERS:
1034             if (has_slirp) {
1035                 ret = rewrite_connection_read_headers(conn, slirp);
1036                 if (ret == DATA_COMPLETED) {
1037                     PROXY_LOG("%s: request headers ok", root->name);
1038                     if (rewrite_connection_rewrite_request(conn) < 0)
1039                         ret = DATA_ERROR;
1040                     else
1041                         conn->state = STATE_REQUEST_SEND;
1042                 }
1043             }
1044             break;
1045 
1046         case STATE_REQUEST_SEND:
1047             if (has_proxy) {
1048                 ret = proxy_connection_send(root, proxy);
1049                 if (ret == DATA_COMPLETED) {
1050                     if (rewrite_connection_get_body_length(conn, 1) < 0) {
1051                         ret = DATA_ERROR;
1052                     } else if (conn->body_mode != BODY_NONE) {
1053                         PROXY_LOG("%s: request sent, waiting for body",
1054                                    root->name);
1055                         conn->state = STATE_REQUEST_BODY;
1056                     } else {
1057                         PROXY_LOG("%s: request sent, waiting for reply",
1058                                   root->name);
1059                         conn->state = STATE_REPLY_FIRST_LINE;
1060                     }
1061                 }
1062             }
1063             break;
1064 
1065         case STATE_REQUEST_BODY:
1066             if (has_slirp) {
1067                 ret = rewrite_connection_read_body(conn, slirp);
1068             }
1069             if (ret != DATA_ERROR && has_proxy) {
1070                 ret = rewrite_connection_send_body(conn, proxy);
1071                 if (ret == DATA_COMPLETED) {
1072                     PROXY_LOG("%s: request body ok, waiting for reply",
1073                               root->name);
1074                     conn->state = STATE_REPLY_FIRST_LINE;
1075                 }
1076             }
1077             break;
1078 
1079         case STATE_REPLY_FIRST_LINE:
1080             if (has_proxy) {
1081                 ret = rewrite_connection_read_reply(conn);
1082                 if (ret == DATA_COMPLETED) {
1083                     PROXY_LOG("%s: reply first line ok", root->name);
1084                     conn->state = STATE_REPLY_HEADERS;
1085                 }
1086             }
1087             break;
1088 
1089         case STATE_REPLY_HEADERS:
1090             if (has_proxy) {
1091                 ret = rewrite_connection_read_headers(conn, proxy);
1092                 if (ret == DATA_COMPLETED) {
1093                     PROXY_LOG("%s: reply headers ok", root->name);
1094                     if (rewrite_connection_rewrite_reply(conn) < 0)
1095                         ret = DATA_ERROR;
1096                     else
1097                         conn->state = STATE_REPLY_SEND;
1098                 }
1099             }
1100             break;
1101 
1102         case STATE_REPLY_SEND:
1103             if (has_slirp) {
1104                 ret = proxy_connection_send(conn->root, slirp);
1105                 if (ret == DATA_COMPLETED) {
1106                     if (rewrite_connection_get_body_length(conn, 0) < 0) {
1107                         ret = DATA_ERROR;
1108                     } else if (conn->body_mode != BODY_NONE) {
1109                         PROXY_LOG("%s: reply sent, waiting for body",
1110                                   root->name);
1111                         conn->state = STATE_REPLY_BODY;
1112                     } else {
1113                         PROXY_LOG("%s: reply sent, looping to waiting request",
1114                                   root->name);
1115                         conn->state = STATE_REQUEST_FIRST_LINE;
1116                     }
1117                 }
1118             }
1119             break;
1120 
1121         case STATE_REPLY_BODY:
1122             if (has_proxy) {
1123                 ret = rewrite_connection_read_body(conn, proxy);
1124             }
1125             if (ret != DATA_ERROR && has_slirp) {
1126                 ret = rewrite_connection_send_body(conn, slirp);
1127                 if (ret == DATA_COMPLETED) {
1128                     if (conn->body_mode == BODY_UNTIL_CLOSE) {
1129                         PROXY_LOG("%s: closing connection", root->name);
1130                         ret = DATA_ERROR;
1131                     } else {
1132                         PROXY_LOG("%s: reply body ok, looping to waiting request",
1133                                 root->name);
1134                         conn->state = STATE_REQUEST_FIRST_LINE;
1135                     }
1136                 }
1137             }
1138             break;
1139 
1140         default:
1141             ;
1142     }
1143     if (ret == DATA_ERROR)
1144         proxy_connection_free(root, 0, PROXY_EVENT_NONE);
1145 
1146     return;
1147 }
1148 
1149 
1150 ProxyConnection*
http_rewriter_connect(HttpService * service,SockAddress * address)1151 http_rewriter_connect( HttpService*  service,
1152                        SockAddress*  address )
1153 {
1154     RewriteConnection*  conn;
1155     int                 s;
1156 
1157     s = socket_create(address->family, SOCKET_STREAM );
1158     if (s < 0)
1159         return NULL;
1160 
1161     conn = qemu_mallocz(sizeof(*conn));
1162     if (conn == NULL) {
1163         socket_close(s);
1164         return NULL;
1165     }
1166 
1167     proxy_connection_init( conn->root, s, address, service->root,
1168                            rewrite_connection_free,
1169                            rewrite_connection_select,
1170                            rewrite_connection_poll );
1171 
1172     if ( rewrite_connection_init( conn ) < 0 ) {
1173         rewrite_connection_free( conn->root );
1174         return NULL;
1175     }
1176 
1177     return conn->root;
1178 }
1179