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

(-)httpd-2.2.2/modules/proxy/mod_proxy_connect.c.orig (-100 / +136 lines)
Lines 21-26 Link Here
21
#include "mod_proxy.h"
21
#include "mod_proxy.h"
22
#include "apr_poll.h"
22
#include "apr_poll.h"
23
23
24
#define CONN_BLKSZ AP_IOBUFSIZE
25
24
module AP_MODULE_DECLARE_DATA proxy_connect_module;
26
module AP_MODULE_DECLARE_DATA proxy_connect_module;
25
27
26
/*
28
/*
Lines 71-76 Link Here
71
    return OK;
73
    return OK;
72
}
74
}
73
75
76
/* read available data (in blocks of CONN_BLKSZ) from c_i and copy to c_o */
77
static int proxy_connect_transfer(request_rec *r, conn_rec *c_i, conn_rec *c_o,
78
				  apr_bucket_brigade *bb, char *name)
79
{
80
    int rv;
81
#ifdef DEBUGGING
82
    apr_off_t len;
83
#endif
84
85
    do {
86
	apr_brigade_cleanup(bb);
87
	rv = ap_get_brigade(c_i->input_filters, bb, AP_MODE_READBYTES,
88
			    APR_NONBLOCK_READ, CONN_BLKSZ);
89
	if (rv == APR_SUCCESS) {
90
	    if (APR_BRIGADE_EMPTY(bb))
91
		break;
92
#ifdef DEBUGGING
93
	    len = -1;
94
	    apr_brigade_length(bb, 0, &len);
95
	    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
96
			  "proxy: CONNECT: read %" APR_OFF_T_FMT
97
			  " bytes from %s", len, name);
98
#endif
99
	    rv = ap_pass_brigade(c_o->output_filters, bb);
100
	    if (rv == APR_SUCCESS) {
101
		ap_fflush(c_o->output_filters, bb);
102
	    } else {
103
		ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
104
			      "proxy: CONNECT: error on %s - ap_pass_brigade",
105
			      name);
106
	    }
107
	} else if (!APR_STATUS_IS_EAGAIN(rv)) {
108
	    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r,
109
			  "proxy: CONNECT: error on %s - ap_get_brigade",
110
			  name);
111
	}
112
    } while (rv == APR_SUCCESS);
113
114
    if (APR_STATUS_IS_EAGAIN(rv)) {
115
	rv = APR_SUCCESS;
116
    }
117
    return rv;
118
}
119
74
/* CONNECT handler */
120
/* CONNECT handler */
75
static int proxy_connect_handler(request_rec *r, proxy_worker *worker,
121
static int proxy_connect_handler(request_rec *r, proxy_worker *worker,
76
                                 proxy_server_conf *conf,
122
                                 proxy_server_conf *conf,
Lines 79-89 Link Here
79
{
125
{
80
    apr_pool_t *p = r->pool;
126
    apr_pool_t *p = r->pool;
81
    apr_socket_t *sock;
127
    apr_socket_t *sock;
128
    conn_rec *c = r->connection;
129
    conn_rec *backconn;
130
131
    apr_bucket_brigade *bb = apr_brigade_create(p, c->bucket_alloc);
82
    apr_status_t err, rv;
132
    apr_status_t err, rv;
83
    apr_size_t i, o, nbytes;
133
    apr_size_t nbytes;
84
    char buffer[HUGE_STRING_LEN];
134
    char buffer[HUGE_STRING_LEN];
85
    apr_socket_t *client_socket = ap_get_module_config(r->connection->conn_config, &core_module);
135
    apr_socket_t *client_socket = ap_get_module_config(c->conn_config, &core_module);
86
    int failed;
136
    int failed, rc;
87
    apr_pollset_t *pollset;
137
    apr_pollset_t *pollset;
88
    apr_pollfd_t pollfd;
138
    apr_pollfd_t pollfd;
89
    const apr_pollfd_t *signalled;
139
    const apr_pollfd_t *signalled;
Lines 151-162 Link Here
151
        case APR_URI_SNEWS_DEFAULT_PORT:
201
        case APR_URI_SNEWS_DEFAULT_PORT:
152
        break;
202
        break;
153
        default:
203
        default:
154
                /* XXX can we call ap_proxyerror() here to get a nice log message? */
204
        return ap_proxyerror(r, HTTP_FORBIDDEN, "Connect to remote machine blocked");
155
        return HTTP_FORBIDDEN;
156
    }
205
    }
157
    } else if(!allowed_port(conf, uri.port)) {
206
    } else if(!allowed_port(conf, uri.port)) {
158
        /* XXX can we call ap_proxyerror() here to get a nice log message? */
207
    return ap_proxyerror(r, HTTP_FORBIDDEN, "Connect to remote machine blocked");
159
    return HTTP_FORBIDDEN;
160
    }
208
    }
161
209
162
    /*
210
    /*
Lines 198-215 Link Here
198
        }
246
        }
199
    }
247
    }
200
248
249
    /* setup polling for connection */
250
    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
251
		  "proxy: CONNECT: setting up poll()");
252
253
    if ((rv = apr_pollset_create(&pollset, 2, r->pool, 0)) != APR_SUCCESS) {
254
	apr_socket_close(sock);
255
        ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
256
            "proxy: CONNECT: error apr_pollset_create()");
257
        return HTTP_INTERNAL_SERVER_ERROR;
258
    }
259
260
    /* Add client side to the poll */
261
    pollfd.p = r->pool;
262
    pollfd.desc_type = APR_POLL_SOCKET;
263
    pollfd.reqevents = APR_POLLIN;
264
    pollfd.desc.s = client_socket;
265
    pollfd.client_data = NULL;
266
    apr_pollset_add(pollset, &pollfd);
267
268
    /* Add the server side to the poll */
269
    pollfd.desc.s = sock;
270
    apr_pollset_add(pollset, &pollfd);
271
201
    /*
272
    /*
202
     * Step Three: Send the Request
273
     * Step Three: Send the Request
203
     *
274
     *
204
     * Send the HTTP/1.1 CONNECT request to the remote server
275
     * Send the HTTP/1.1 CONNECT request to the remote server
205
     */
276
     */
206
277
207
    /* we are acting as a tunnel - the output filter stack should
278
    backconn = ap_run_create_connection(c->pool, r->server, sock,
208
     * be completely empty, because when we are done here we are done completely.
279
					c->id, c->sbh, c->bucket_alloc);
209
     * We add the NULL filter to the stack to do this...
280
    if (!backconn) {
210
     */
281
	/* peer reset */
211
    r->output_filters = NULL;
282
	ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
212
    r->connection->output_filters = NULL;
283
		      "proxy: an error occurred creating a new connection "
284
		      "to %pI (%s)", connect_addr, connectname);
285
	apr_socket_close(sock);
286
	return HTTP_INTERNAL_SERVER_ERROR;
287
    }
288
    ap_proxy_ssl_disable(backconn);
289
    rc = ap_run_pre_connection(backconn, sock);
290
    if (rc != OK && rc != DONE) {
291
	backconn->aborted = 1;
292
	ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
293
		      "proxy: CONNECT: pre_connection setup failed (%d)", rc);
294
	return HTTP_INTERNAL_SERVER_ERROR;
295
    }
296
297
    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
298
		  "proxy: CONNECT: connection complete to %pI (%s)",
299
		  connect_addr, connectname);
213
300
214
301
215
    /* If we are connecting through a remote proxy, we need to pass
302
    /* If we are connecting through a remote proxy, we need to pass
Lines 220-231 Link Here
220
     */
307
     */
221
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
308
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
222
             "proxy: CONNECT: sending the CONNECT request to the remote proxy");
309
             "proxy: CONNECT: sending the CONNECT request to the remote proxy");
223
        nbytes = apr_snprintf(buffer, sizeof(buffer),
310
        ap_fprintf(backconn->output_filters, bb,
224
                  "CONNECT %s HTTP/1.0" CRLF, r->uri);
311
		   "CONNECT %s HTTP/1.0" CRLF, r->uri);
225
        apr_socket_send(sock, buffer, &nbytes);
312
        ap_fprintf(backconn->output_filters, bb,
226
        nbytes = apr_snprintf(buffer, sizeof(buffer),
313
		   "Proxy-agent: %s" CRLF CRLF, ap_get_server_version());
227
                  "Proxy-agent: %s" CRLF CRLF, ap_get_server_version());
314
        ap_fflush(backconn->output_filters, bb);
228
        apr_socket_send(sock, buffer, &nbytes);
229
    }
315
    }
230
    else {
316
    else {
231
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
317
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
Lines 233-243 Link Here
233
        nbytes = apr_snprintf(buffer, sizeof(buffer),
319
        nbytes = apr_snprintf(buffer, sizeof(buffer),
234
                  "HTTP/1.0 200 Connection Established" CRLF);
320
                  "HTTP/1.0 200 Connection Established" CRLF);
235
        ap_xlate_proto_to_ascii(buffer, nbytes);
321
        ap_xlate_proto_to_ascii(buffer, nbytes);
236
        apr_socket_send(client_socket, buffer, &nbytes);
322
	ap_fwrite(c->output_filters, bb, buffer, nbytes);
237
        nbytes = apr_snprintf(buffer, sizeof(buffer),
323
        nbytes = apr_snprintf(buffer, sizeof(buffer),
238
                  "Proxy-agent: %s" CRLF CRLF, ap_get_server_version());
324
                  "Proxy-agent: %s" CRLF CRLF, ap_get_server_version());
239
        ap_xlate_proto_to_ascii(buffer, nbytes);
325
        ap_xlate_proto_to_ascii(buffer, nbytes);
240
        apr_socket_send(client_socket, buffer, &nbytes);
326
        ap_fwrite(c->output_filters, bb, buffer, nbytes);
327
        ap_fflush(c->output_filters, bb);
241
#if 0
328
#if 0
242
        /* This is safer code, but it doesn't work yet.  I'm leaving it
329
        /* This is safer code, but it doesn't work yet.  I'm leaving it
243
         * here so that I can fix it later.
330
         * here so that I can fix it later.
Lines 258-284 Link Here
258
     * Handle two way transfer of data over the socket (this is a tunnel).
345
     * Handle two way transfer of data over the socket (this is a tunnel).
259
     */
346
     */
260
347
261
/*    r->sent_bodyct = 1;*/
348
    /* we are now acting as a tunnel - the input/output filter stacks should
262
349
     * not contain any non-connection filters.
263
    if ((rv = apr_pollset_create(&pollset, 2, r->pool, 0)) != APR_SUCCESS)
350
     */
264
    {
351
    r->output_filters = c->output_filters;
265
    apr_socket_close(sock);
352
    r->proto_output_filters = c->output_filters;
266
        ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
353
    r->input_filters = c->input_filters;
267
            "proxy: CONNECT: error apr_pollset_create()");
354
    r->proto_input_filters = c->input_filters;
268
        return HTTP_INTERNAL_SERVER_ERROR;
355
/*  r->sent_bodyct = 1;*/
269
    }
270
271
    /* Add client side to the poll */
272
    pollfd.p = r->pool;
273
    pollfd.desc_type = APR_POLL_SOCKET;
274
    pollfd.reqevents = APR_POLLIN;
275
    pollfd.desc.s = client_socket;
276
    pollfd.client_data = NULL;
277
    apr_pollset_add(pollset, &pollfd);
278
279
    /* Add the server side to the poll */
280
    pollfd.desc.s = sock;
281
    apr_pollset_add(pollset, &pollfd);
282
356
283
    while (1) { /* Infinite loop until error (one side closes the connection) */
357
    while (1) { /* Infinite loop until error (one side closes the connection) */
284
        if ((rv = apr_pollset_poll(pollset, -1, &pollcnt, &signalled)) != APR_SUCCESS) {
358
        if ((rv = apr_pollset_poll(pollset, -1, &pollcnt, &signalled)) != APR_SUCCESS) {
Lines 288-294 Link Here
288
        }
362
        }
289
#ifdef DEBUGGING
363
#ifdef DEBUGGING
290
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
364
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
291
                     "proxy: CONNECT: woke from select(), i=%d", pollcnt);
365
                     "proxy: CONNECT: woke from poll(), i=%d", pollcnt);
292
#endif
366
#endif
293
367
294
        for (pi = 0; pi < pollcnt; pi++) {
368
        for (pi = 0; pi < pollcnt; pi++) {
Lines 298-369 Link Here
298
                pollevent = cur->rtnevents;
372
                pollevent = cur->rtnevents;
299
                if (pollevent & APR_POLLIN) {
373
                if (pollevent & APR_POLLIN) {
300
#ifdef DEBUGGING
374
#ifdef DEBUGGING
301
                    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
375
                    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
302
                                 "proxy: CONNECT: sock was set");
376
                                 "proxy: CONNECT: sock was readable");
303
#endif
377
#endif
304
                    nbytes = sizeof(buffer);
378
                    rv = proxy_connect_transfer(r, backconn, c, bb, "sock");
305
                    rv = apr_socket_recv(sock, buffer, &nbytes);
306
                    if (rv == APR_SUCCESS) {
307
                        o = 0;
308
                        i = nbytes;
309
                        while(i > 0)
310
                        {
311
                            nbytes = i;
312
    /* This is just plain wrong.  No module should ever write directly
313
     * to the client.  For now, this works, but this is high on my list of
314
     * things to fix.  The correct line is:
315
     * if ((nbytes = ap_rwrite(buffer + o, nbytes, r)) < 0)
316
     * rbb
317
     */
318
                            rv = apr_socket_send(client_socket, buffer + o, &nbytes);
319
                            if (rv != APR_SUCCESS)
320
                                break;
321
                            o += nbytes;
322
                            i -= nbytes;
323
                        }
324
                    }
325
                    else
326
                        break;
327
                }
379
                }
328
                else if ((pollevent & APR_POLLERR) || (pollevent & APR_POLLHUP))
380
                else if ((pollevent & APR_POLLERR) || (pollevent & APR_POLLHUP)) {
329
                    break;
381
		    rv = APR_EPIPE;
382
                    ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, "proxy: CONNECT: err/hup on backconn");
383
                    }
330
            }
384
            }
331
            else if (cur->desc.s == client_socket) {
385
            else if (cur->desc.s == client_socket) {
332
                pollevent = cur->rtnevents;
386
                pollevent = cur->rtnevents;
333
                if (pollevent & APR_POLLIN) {
387
                if (pollevent & APR_POLLIN) {
334
#ifdef DEBUGGING
388
#ifdef DEBUGGING
335
                    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
389
                    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
336
                                 "proxy: CONNECT: client was set");
390
                                 "proxy: CONNECT: client was readable");
337
#endif
391
#endif
338
                    nbytes = sizeof(buffer);
392
                    rv = proxy_connect_transfer(r, c, backconn, bb, "client");
339
                    rv = apr_socket_recv(client_socket, buffer, &nbytes);
340
                    if (rv == APR_SUCCESS) {
341
                        o = 0;
342
                        i = nbytes;
343
#ifdef DEBUGGING
344
                        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
345
                                     "proxy: CONNECT: read %d from client", i);
346
#endif
347
                        while(i > 0)
348
                        {
349
                            nbytes = i;
350
                            rv = apr_socket_send(sock, buffer + o, &nbytes);
351
                            if (rv != APR_SUCCESS)
352
                                break;
353
                            o += nbytes;
354
                            i -= nbytes;
355
                        }
356
                    }
357
                    else
358
                        break;
359
                }
360
                else if ((pollevent & APR_POLLERR) || (pollevent & APR_POLLHUP)) {
361
                    rv = APR_EOF;
362
                    break;
363
                }
393
                }
364
            }
394
            }
365
            else
395
            else {
366
                break;
396
                rv = APR_EBADF;
397
                ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
398
			      "proxy: CONNECT: unknown socket in pollset");
399
            }
400
               
367
        }
401
        }
368
        if (rv != APR_SUCCESS) {
402
        if (rv != APR_SUCCESS) {
369
            break;
403
            break;
Lines 379-385 Link Here
379
     * Close the socket and clean up
413
     * Close the socket and clean up
380
     */
414
     */
381
415
382
    apr_socket_close(sock);
416
    ap_lingering_close(backconn);
417
418
    c->aborted = 1;
383
419
384
    return OK;
420
    return OK;
385
}
421
}

Return to bug 29744