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

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

Return to bug 29744