Line 0
Link Here
|
|
|
1 |
diff -Naurw modules/proxy/mod_proxy_connect.c modules/proxy/mod_proxy_connect.c |
2 |
--- modules/proxy/mod_proxy_connect.c 2007-09-02 18:42:59.000000000 +0100 |
3 |
+++ modules/proxy/mod_proxy_connect.c 2007-10-08 17:03:32.523635700 +0100 |
4 |
@@ -21,6 +21,8 @@ |
5 |
#include "mod_proxy.h" |
6 |
#include "apr_poll.h" |
7 |
|
8 |
+#define CONN_BLKSZ AP_IOBUFSIZE |
9 |
+ |
10 |
module AP_MODULE_DECLARE_DATA proxy_connect_module; |
11 |
|
12 |
/* |
13 |
@@ -71,6 +73,50 @@ |
14 |
return OK; |
15 |
} |
16 |
|
17 |
+/* read available data (in blocks of CONN_BLKSZ) from c_i and copy to c_o */ |
18 |
+static int proxy_connect_transfer(request_rec *r, conn_rec *c_i, conn_rec *c_o, |
19 |
+ apr_bucket_brigade *bb, char *name) |
20 |
+{ |
21 |
+ int rv; |
22 |
+#ifdef DEBUGGING |
23 |
+ apr_off_t len; |
24 |
+#endif |
25 |
+ |
26 |
+ do { |
27 |
+ apr_brigade_cleanup(bb); |
28 |
+ rv = ap_get_brigade(c_i->input_filters, bb, AP_MODE_READBYTES, |
29 |
+ APR_NONBLOCK_READ, CONN_BLKSZ); |
30 |
+ if (rv == APR_SUCCESS) { |
31 |
+ if (APR_BRIGADE_EMPTY(bb)) |
32 |
+ break; |
33 |
+#ifdef DEBUGGING |
34 |
+ len = -1; |
35 |
+ apr_brigade_length(bb, 0, &len); |
36 |
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, |
37 |
+ "proxy: CONNECT: read %" APR_OFF_T_FMT |
38 |
+ " bytes from %s", len, name); |
39 |
+#endif |
40 |
+ rv = ap_pass_brigade(c_o->output_filters, bb); |
41 |
+ if (rv == APR_SUCCESS) { |
42 |
+ ap_fflush(c_o->output_filters, bb); |
43 |
+ } else { |
44 |
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, |
45 |
+ "proxy: CONNECT: error on %s - ap_pass_brigade", |
46 |
+ name); |
47 |
+ } |
48 |
+ } else if (!APR_STATUS_IS_EAGAIN(rv)) { |
49 |
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, |
50 |
+ "proxy: CONNECT: error on %s - ap_get_brigade", |
51 |
+ name); |
52 |
+ } |
53 |
+ } while (rv == APR_SUCCESS); |
54 |
+ |
55 |
+ if (APR_STATUS_IS_EAGAIN(rv)) { |
56 |
+ rv = APR_SUCCESS; |
57 |
+ } |
58 |
+ return rv; |
59 |
+} |
60 |
+ |
61 |
/* CONNECT handler */ |
62 |
static int proxy_connect_handler(request_rec *r, proxy_worker *worker, |
63 |
proxy_server_conf *conf, |
64 |
@@ -79,11 +125,15 @@ |
65 |
{ |
66 |
apr_pool_t *p = r->pool; |
67 |
apr_socket_t *sock; |
68 |
+ conn_rec *c = r->connection; |
69 |
+ conn_rec *backconn; |
70 |
+ |
71 |
+ apr_bucket_brigade *bb = apr_brigade_create(p, c->bucket_alloc); |
72 |
apr_status_t err, rv; |
73 |
- apr_size_t i, o, nbytes; |
74 |
+ apr_size_t nbytes; |
75 |
char buffer[HUGE_STRING_LEN]; |
76 |
- apr_socket_t *client_socket = ap_get_module_config(r->connection->conn_config, &core_module); |
77 |
- int failed; |
78 |
+ apr_socket_t *client_socket = ap_get_module_config(c->conn_config, &core_module); |
79 |
+ int failed, rc; |
80 |
apr_pollset_t *pollset; |
81 |
apr_pollfd_t pollfd; |
82 |
const apr_pollfd_t *signalled; |
83 |
@@ -158,12 +208,10 @@ |
84 |
case APR_URI_SNEWS_DEFAULT_PORT: |
85 |
break; |
86 |
default: |
87 |
- /* XXX can we call ap_proxyerror() here to get a nice log message? */ |
88 |
- return HTTP_FORBIDDEN; |
89 |
+ return ap_proxyerror(r, HTTP_FORBIDDEN, "Connect to remote machine blocked"); |
90 |
} |
91 |
} else if(!allowed_port(conf, uri.port)) { |
92 |
- /* XXX can we call ap_proxyerror() here to get a nice log message? */ |
93 |
- return HTTP_FORBIDDEN; |
94 |
+ return ap_proxyerror(r, HTTP_FORBIDDEN, "Connect to remote machine blocked"); |
95 |
} |
96 |
|
97 |
/* |
98 |
@@ -205,18 +253,57 @@ |
99 |
} |
100 |
} |
101 |
|
102 |
+ /* setup polling for connection */ |
103 |
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, |
104 |
+ "proxy: CONNECT: setting up poll()"); |
105 |
+ |
106 |
+ if ((rv = apr_pollset_create(&pollset, 2, r->pool, 0)) != APR_SUCCESS) { |
107 |
+ apr_socket_close(sock); |
108 |
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, |
109 |
+ "proxy: CONNECT: error apr_pollset_create()"); |
110 |
+ return HTTP_INTERNAL_SERVER_ERROR; |
111 |
+ } |
112 |
+ |
113 |
+ /* Add client side to the poll */ |
114 |
+ pollfd.p = r->pool; |
115 |
+ pollfd.desc_type = APR_POLL_SOCKET; |
116 |
+ pollfd.reqevents = APR_POLLIN; |
117 |
+ pollfd.desc.s = client_socket; |
118 |
+ pollfd.client_data = NULL; |
119 |
+ apr_pollset_add(pollset, &pollfd); |
120 |
+ |
121 |
+ /* Add the server side to the poll */ |
122 |
+ pollfd.desc.s = sock; |
123 |
+ apr_pollset_add(pollset, &pollfd); |
124 |
+ |
125 |
/* |
126 |
* Step Three: Send the Request |
127 |
* |
128 |
* Send the HTTP/1.1 CONNECT request to the remote server |
129 |
*/ |
130 |
|
131 |
- /* we are acting as a tunnel - the output filter stack should |
132 |
- * be completely empty, because when we are done here we are done completely. |
133 |
- * We add the NULL filter to the stack to do this... |
134 |
- */ |
135 |
- r->output_filters = NULL; |
136 |
- r->connection->output_filters = NULL; |
137 |
+ backconn = ap_run_create_connection(c->pool, r->server, sock, |
138 |
+ c->id, c->sbh, c->bucket_alloc); |
139 |
+ if (!backconn) { |
140 |
+ /* peer reset */ |
141 |
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, |
142 |
+ "proxy: an error occurred creating a new connection " |
143 |
+ "to %pI (%s)", connect_addr, connectname); |
144 |
+ apr_socket_close(sock); |
145 |
+ return HTTP_INTERNAL_SERVER_ERROR; |
146 |
+ } |
147 |
+ ap_proxy_ssl_disable(backconn); |
148 |
+ rc = ap_run_pre_connection(backconn, sock); |
149 |
+ if (rc != OK && rc != DONE) { |
150 |
+ backconn->aborted = 1; |
151 |
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, |
152 |
+ "proxy: CONNECT: pre_connection setup failed (%d)", rc); |
153 |
+ return HTTP_INTERNAL_SERVER_ERROR; |
154 |
+ } |
155 |
+ |
156 |
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, |
157 |
+ "proxy: CONNECT: connection complete to %pI (%s)", |
158 |
+ connect_addr, connectname); |
159 |
|
160 |
|
161 |
/* If we are connecting through a remote proxy, we need to pass |
162 |
@@ -227,12 +314,11 @@ |
163 |
*/ |
164 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, |
165 |
"proxy: CONNECT: sending the CONNECT request to the remote proxy"); |
166 |
- nbytes = apr_snprintf(buffer, sizeof(buffer), |
167 |
+ ap_fprintf(backconn->output_filters, bb, |
168 |
"CONNECT %s HTTP/1.0" CRLF, r->uri); |
169 |
- apr_socket_send(sock, buffer, &nbytes); |
170 |
- nbytes = apr_snprintf(buffer, sizeof(buffer), |
171 |
- "Proxy-agent: %s" CRLF CRLF, ap_get_server_banner()); |
172 |
- apr_socket_send(sock, buffer, &nbytes); |
173 |
+ ap_fprintf(backconn->output_filters, bb, |
174 |
+ "Proxy-agent: %s" CRLF CRLF, ap_get_server_version()); |
175 |
+ ap_fflush(backconn->output_filters, bb); |
176 |
} |
177 |
else { |
178 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, |
179 |
@@ -240,11 +326,12 @@ |
180 |
nbytes = apr_snprintf(buffer, sizeof(buffer), |
181 |
"HTTP/1.0 200 Connection Established" CRLF); |
182 |
ap_xlate_proto_to_ascii(buffer, nbytes); |
183 |
- apr_socket_send(client_socket, buffer, &nbytes); |
184 |
+ ap_fwrite(c->output_filters, bb, buffer, nbytes); |
185 |
nbytes = apr_snprintf(buffer, sizeof(buffer), |
186 |
"Proxy-agent: %s" CRLF CRLF, ap_get_server_banner()); |
187 |
ap_xlate_proto_to_ascii(buffer, nbytes); |
188 |
- apr_socket_send(client_socket, buffer, &nbytes); |
189 |
+ ap_fwrite(c->output_filters, bb, buffer, nbytes); |
190 |
+ ap_fflush(c->output_filters, bb); |
191 |
#if 0 |
192 |
/* This is safer code, but it doesn't work yet. I'm leaving it |
193 |
* here so that I can fix it later. |
194 |
@@ -265,27 +352,15 @@ |
195 |
* Handle two way transfer of data over the socket (this is a tunnel). |
196 |
*/ |
197 |
|
198 |
+ /* we are now acting as a tunnel - the input/output filter stacks should |
199 |
+ * not contain any non-connection filters. |
200 |
+ */ |
201 |
+ r->output_filters = c->output_filters; |
202 |
+ r->proto_output_filters = c->output_filters; |
203 |
+ r->input_filters = c->input_filters; |
204 |
+ r->proto_input_filters = c->input_filters; |
205 |
/* r->sent_bodyct = 1;*/ |
206 |
|
207 |
- if ((rv = apr_pollset_create(&pollset, 2, r->pool, 0)) != APR_SUCCESS) { |
208 |
- apr_socket_close(sock); |
209 |
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, |
210 |
- "proxy: CONNECT: error apr_pollset_create()"); |
211 |
- return HTTP_INTERNAL_SERVER_ERROR; |
212 |
- } |
213 |
- |
214 |
- /* Add client side to the poll */ |
215 |
- pollfd.p = r->pool; |
216 |
- pollfd.desc_type = APR_POLL_SOCKET; |
217 |
- pollfd.reqevents = APR_POLLIN; |
218 |
- pollfd.desc.s = client_socket; |
219 |
- pollfd.client_data = NULL; |
220 |
- apr_pollset_add(pollset, &pollfd); |
221 |
- |
222 |
- /* Add the server side to the poll */ |
223 |
- pollfd.desc.s = sock; |
224 |
- apr_pollset_add(pollset, &pollfd); |
225 |
- |
226 |
while (1) { /* Infinite loop until error (one side closes the connection) */ |
227 |
if ((rv = apr_pollset_poll(pollset, -1, &pollcnt, &signalled)) != APR_SUCCESS) { |
228 |
apr_socket_close(sock); |
229 |
@@ -294,7 +369,7 @@ |
230 |
} |
231 |
#ifdef DEBUGGING |
232 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, |
233 |
- "proxy: CONNECT: woke from select(), i=%d", pollcnt); |
234 |
+ "proxy: CONNECT: woke from poll(), i=%d", pollcnt); |
235 |
#endif |
236 |
|
237 |
for (pi = 0; pi < pollcnt; pi++) { |
238 |
@@ -304,72 +379,32 @@ |
239 |
pollevent = cur->rtnevents; |
240 |
if (pollevent & APR_POLLIN) { |
241 |
#ifdef DEBUGGING |
242 |
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, |
243 |
- "proxy: CONNECT: sock was set"); |
244 |
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, |
245 |
+ "proxy: CONNECT: sock was readable"); |
246 |
#endif |
247 |
- nbytes = sizeof(buffer); |
248 |
- rv = apr_socket_recv(sock, buffer, &nbytes); |
249 |
- if (rv == APR_SUCCESS) { |
250 |
- o = 0; |
251 |
- i = nbytes; |
252 |
- while(i > 0) |
253 |
- { |
254 |
- nbytes = i; |
255 |
- /* This is just plain wrong. No module should ever write directly |
256 |
- * to the client. For now, this works, but this is high on my list of |
257 |
- * things to fix. The correct line is: |
258 |
- * if ((nbytes = ap_rwrite(buffer + o, nbytes, r)) < 0) |
259 |
- * rbb |
260 |
- */ |
261 |
- rv = apr_socket_send(client_socket, buffer + o, &nbytes); |
262 |
- if (rv != APR_SUCCESS) |
263 |
- break; |
264 |
- o += nbytes; |
265 |
- i -= nbytes; |
266 |
- } |
267 |
+ rv = proxy_connect_transfer(r, backconn, c, bb, "sock"); |
268 |
} |
269 |
- else |
270 |
- break; |
271 |
+ else if ((pollevent & APR_POLLERR) || (pollevent & APR_POLLHUP)) { |
272 |
+ rv = APR_EPIPE; |
273 |
+ ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, "proxy: CONNECT: err/hup on backconn"); |
274 |
} |
275 |
- else if ((pollevent & APR_POLLERR) || (pollevent & APR_POLLHUP)) |
276 |
- break; |
277 |
} |
278 |
else if (cur->desc.s == client_socket) { |
279 |
pollevent = cur->rtnevents; |
280 |
if (pollevent & APR_POLLIN) { |
281 |
#ifdef DEBUGGING |
282 |
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, |
283 |
- "proxy: CONNECT: client was set"); |
284 |
-#endif |
285 |
- nbytes = sizeof(buffer); |
286 |
- rv = apr_socket_recv(client_socket, buffer, &nbytes); |
287 |
- if (rv == APR_SUCCESS) { |
288 |
- o = 0; |
289 |
- i = nbytes; |
290 |
-#ifdef DEBUGGING |
291 |
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, |
292 |
- "proxy: CONNECT: read %d from client", i); |
293 |
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, |
294 |
+ "proxy: CONNECT: client was readable"); |
295 |
#endif |
296 |
- while(i > 0) |
297 |
- { |
298 |
- nbytes = i; |
299 |
- rv = apr_socket_send(sock, buffer + o, &nbytes); |
300 |
- if (rv != APR_SUCCESS) |
301 |
- break; |
302 |
- o += nbytes; |
303 |
- i -= nbytes; |
304 |
- } |
305 |
- } |
306 |
- else |
307 |
- break; |
308 |
+ rv = proxy_connect_transfer(r, c, backconn, bb, "client"); |
309 |
} |
310 |
- else if ((pollevent & APR_POLLERR) || (pollevent & APR_POLLHUP)) { |
311 |
- rv = APR_EOF; |
312 |
- break; |
313 |
} |
314 |
+ else { |
315 |
+ rv = APR_EBADF; |
316 |
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, |
317 |
+ "proxy: CONNECT: unknown socket in pollset"); |
318 |
} |
319 |
- else |
320 |
- break; |
321 |
+ |
322 |
} |
323 |
if (rv != APR_SUCCESS) { |
324 |
break; |
325 |
@@ -385,7 +420,9 @@ |
326 |
* Close the socket and clean up |
327 |
*/ |
328 |
|
329 |
- apr_socket_close(sock); |
330 |
+ ap_lingering_close(backconn); |
331 |
+ |
332 |
+ c->aborted = 1; |
333 |
|
334 |
return OK; |
335 |
} |