View | Details | Raw Unified | Return to bug 135478
Collapse All | Expand All

(-)apache22.new/Makefile (+5 lines)
Lines 190-195 Link Here
190
show-options:
190
show-options:
191
	@${SED} -ne 's/^##//p' ${APACHEDIR}/Makefile.doc
191
	@${SED} -ne 's/^##//p' ${APACHEDIR}/Makefile.doc
192
192
193
#optionally enable mod_proxy_connect patch
194
.if defined(PATCH_PROXY_CONNECT)
195
EXTRA_PATCHES+= ${FILESDIR}/opt-patch-modules:proxy:mod_proxy_connect.c
196
.endif
197
193
post-patch:
198
post-patch:
194
	@${RM} -f ${WRKSRC}/docs/docroot/*.bak
199
	@${RM} -f ${WRKSRC}/docs/docroot/*.bak
195
	@${REINPLACE_CMD} -e 's," PLATFORM ",FreeBSD,' \
200
	@${REINPLACE_CMD} -e 's," PLATFORM ",FreeBSD,' \
(-)apache22.new/Makefile.options (+1 lines)
Lines 64-69 Link Here
64
	 VERSION "Enable mod_version" ON \
64
	 VERSION "Enable mod_version" ON \
65
	 PROXY "Enable mod_proxy" OFF \
65
	 PROXY "Enable mod_proxy" OFF \
66
	 PROXY_CONNECT "Enable mod_proxy_connect" OFF \
66
	 PROXY_CONNECT "Enable mod_proxy_connect" OFF \
67
	 PATCH_PROXY_CONNECT "Patch proxy_connect SSL support" ON \
67
	 PROXY_FTP "Enable mod_proxy_ftp" OFF \
68
	 PROXY_FTP "Enable mod_proxy_ftp" OFF \
68
	 PROXY_HTTP "Enable mod_proxy_http" OFF \
69
	 PROXY_HTTP "Enable mod_proxy_http" OFF \
69
	 PROXY_AJP "Enable mod_proxy_ajp" OFF \
70
	 PROXY_AJP "Enable mod_proxy_ajp" OFF \
(-)apache22.new/files/opt-patch-modules:proxy:mod_proxy_connect.c (+335 lines)
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
 }

Return to bug 135478