• 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_int.h"
13 #include "proxy_http_int.h"
14 #include "qemu-common.h"
15 #include <errno.h>
16 #include <stdio.h>
17 #include <string.h>
18 
19 #define  HTTP_VERSION  "1.1"
20 
21 static void
http_service_free(HttpService * service)22 http_service_free( HttpService*  service )
23 {
24     PROXY_LOG("%s", __FUNCTION__);
25     if (service->footer != service->footer0)
26         qemu_free(service->footer);
27     qemu_free(service);
28 }
29 
30 
31 static ProxyConnection*
http_service_connect(HttpService * service,SocketType sock_type,SockAddress * address)32 http_service_connect( HttpService*  service,
33                       SocketType    sock_type,
34                       SockAddress*  address )
35 {
36     /* the HTTP proxy can only handle TCP connections */
37     if (sock_type != SOCKET_STREAM)
38         return NULL;
39 
40     /* if the client tries to directly connect to the proxy, let it do so */
41     if (sock_address_equal( address, &service->server_addr ))
42         return NULL;
43 
44     PROXY_LOG("%s: trying to connect to %s",
45               __FUNCTION__, sock_address_to_string(address));
46 
47     if (sock_address_get_port(address) == 80) {
48         /* use the rewriter for HTTP */
49         PROXY_LOG("%s: using HTTP rewriter", __FUNCTION__);
50         return http_rewriter_connect(service, address);
51     } else {
52         PROXY_LOG("%s: using HTTP rewriter", __FUNCTION__);
53         return http_connector_connect(service, address);
54     }
55 }
56 
57 
58 int
proxy_http_setup(const char * servername,int servernamelen,int serverport,int num_options,const ProxyOption * options)59 proxy_http_setup( const char*         servername,
60                   int                 servernamelen,
61                   int                 serverport,
62                   int                 num_options,
63                   const ProxyOption*  options )
64 {
65     HttpService*        service;
66     SockAddress         server_addr;
67     const ProxyOption*  opt_nocache   = NULL;
68     const ProxyOption*  opt_keepalive = NULL;
69     const ProxyOption*  opt_auth_user = NULL;
70     const ProxyOption*  opt_auth_pass = NULL;
71     const ProxyOption*  opt_user_agent = NULL;
72 
73     if (servernamelen < 0)
74         servernamelen = strlen(servername);
75 
76     PROXY_LOG( "%s: creating http proxy service connecting to: %.*s:%d",
77                __FUNCTION__, servernamelen, servername, serverport );
78 
79     /* resolve server address */
80     if (proxy_resolve_server(&server_addr, servername,
81                              servernamelen, serverport) < 0)
82     {
83         return -1;
84     }
85 
86     /* create service object */
87     service = qemu_mallocz(sizeof(*service));
88     if (service == NULL) {
89         PROXY_LOG("%s: not enough memory to allocate new proxy service", __FUNCTION__);
90         return -1;
91     }
92 
93     service->server_addr = server_addr;
94 
95     /* parse options */
96     {
97         const ProxyOption*  opt = options;
98         const ProxyOption*  end = opt + num_options;
99 
100         for ( ; opt < end; opt++ ) {
101             switch (opt->type) {
102                 case PROXY_OPTION_HTTP_NOCACHE:     opt_nocache    = opt; break;
103                 case PROXY_OPTION_HTTP_KEEPALIVE:   opt_keepalive  = opt; break;
104                 case PROXY_OPTION_AUTH_USERNAME:    opt_auth_user  = opt; break;
105                 case PROXY_OPTION_AUTH_PASSWORD:    opt_auth_pass  = opt; break;
106                 case PROXY_OPTION_HTTP_USER_AGENT:  opt_user_agent = opt; break;
107                 default: ;
108             }
109         }
110     }
111 
112     /* prepare footer */
113     {
114         int    wlen;
115         char*  p    = service->footer0;
116         char*  end  = p + sizeof(service->footer0);
117 
118         /* no-cache */
119         if (opt_nocache) {
120             p += snprintf(p, end-p, "Pragma: no-cache\r\nCache-Control: no-cache\r\n");
121             if (p >= end) goto FooterOverflow;
122         }
123         /* keep-alive */
124         if (opt_keepalive) {
125             p += snprintf(p, end-p, "Connection: Keep-Alive\r\nProxy-Connection: Keep-Alive\r\n");
126             if (p >= end) goto FooterOverflow;
127         }
128         /* authentication */
129         if (opt_auth_user && opt_auth_pass) {
130             char  user_pass[256];
131             char  encoded[512];
132             int   uplen;
133 
134             uplen = snprintf( user_pass, sizeof(user_pass), "%.*s:%.*s",
135                               opt_auth_user->string_len, opt_auth_user->string,
136                               opt_auth_pass->string_len, opt_auth_pass->string );
137 
138             if (uplen >= sizeof(user_pass)) goto FooterOverflow;
139 
140             wlen = proxy_base64_encode(user_pass, uplen, encoded, (int)sizeof(encoded));
141             if (wlen < 0) {
142                 PROXY_LOG( "could not base64 encode '%.*s'", uplen, user_pass);
143                 goto FooterOverflow;
144             }
145 
146             p += snprintf(p, end-p, "Proxy-authorization: Basic %.*s\r\n", wlen, encoded);
147             if (p >= end) goto FooterOverflow;
148         }
149         /* user agent */
150         if (opt_user_agent) {
151             p += snprintf(p, end-p, "User-Agent: %.*s\r\n",
152                           opt_user_agent->string_len,
153                           opt_user_agent->string);
154             if (p >= end) goto FooterOverflow;
155         }
156 
157         p += snprintf(p, end-p, "\r\n");
158 
159         if (p >= end) {
160         FooterOverflow:
161             PROXY_LOG( "%s: buffer overflow when creating connection footer",
162                        __FUNCTION__);
163             http_service_free(service);
164             return -1;
165         }
166 
167         service->footer     = service->footer0;
168         service->footer_len = (p - service->footer);
169     }
170 
171     PROXY_LOG( "%s: creating HTTP Proxy Service Footer is (len=%d):\n'%.*s'",
172                __FUNCTION__, service->footer_len,
173                service->footer_len, service->footer );
174 
175     service->root->opaque       = service;
176     service->root->serv_free    = (ProxyServiceFreeFunc)    http_service_free;
177     service->root->serv_connect = (ProxyServiceConnectFunc) http_service_connect;
178 
179     if (proxy_manager_add_service( service->root ) < 0) {
180         PROXY_LOG("%s: could not register service ?", __FUNCTION__);
181         http_service_free(service);
182         return -1;
183     }
184     return 0;
185 }
186 
187