ASF Bugzilla – Attachment 18222 Details for
Bug 29744
CONNECT does not work over existing SSL connection
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Fixed patch with read loops and updated to 2.2.0
proxy_connect-fix-220.diff (text/plain), 18.37 KB, created by
Brad Boyer
on 2006-05-03 22:27:40 UTC
(
hide
)
Description:
Fixed patch with read loops and updated to 2.2.0
Filename:
MIME Type:
Creator:
Brad Boyer
Created:
2006-05-03 22:27:40 UTC
Size:
18.37 KB
patch
obsolete
>--- httpd-2.2.0/modules/proxy/mod_proxy_connect.c 2005-12-10 15:46:43.000000000 -0800 >+++ httpd-fixed/modules/proxy/mod_proxy_connect.c 2006-05-03 15:23:12.000000000 -0700 >@@ -21,9 +21,11 @@ > #include "mod_proxy.h" > #include "apr_poll.h" > >+#define CONN_BLKSZ AP_IOBUFSIZE >+ > module AP_MODULE_DECLARE_DATA proxy_connect_module; > >-/* >+/* > * This handles Netscape CONNECT method secure proxy requests. > * A connection is opened to the specified host and data is > * passed through between the WWW site and the browser. >@@ -32,8 +34,8 @@ > * "Tunneling SSL Through a WWW Proxy" currently at > * http://www.mcom.com/newsref/std/tunneling_ssl.html. > * >- * If proxyhost and proxyport are set, we send a CONNECT to >- * the specified proxy.. >+ * If proxyhost and proxyport are set, we send a CONNECT to >+ * the specified proxy.. > * > * FIXME: this doesn't log the number of bytes sent, but > * that may be okay, since the data is supposed to >@@ -52,8 +54,8 @@ > int *list = (int *) conf->allowed_connect_ports->elts; > > for(i = 0; i < conf->allowed_connect_ports->nelts; i++) { >- if(port == list[i]) >- return 1; >+ if(port == list[i]) >+ return 1; > } > return 0; > } >@@ -63,18 +65,62 @@ > { > > if (r->method_number != M_CONNECT) { >- return DECLINED; >+ return DECLINED; > } >- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, >- "proxy: CONNECT: canonicalising URL %s", url); >+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, >+ "proxy: CONNECT: canonicalising URL %s", url); > > return OK; > } > >+/* read available data (in blocks of CONN_BLKSZ) from c_i and copy to c_o */ >+static int proxy_connect_transfer(request_rec *r, conn_rec *c_i, conn_rec *c_o, >+ apr_bucket_brigade *bb, char *name) >+{ >+ int rv; >+#ifdef DEBUGGING >+ apr_off_t len; >+#endif >+ >+ do { >+ apr_brigade_cleanup(bb); >+ rv = ap_get_brigade(c_i->input_filters, bb, AP_MODE_READBYTES, >+ APR_NONBLOCK_READ, CONN_BLKSZ); >+ if (rv == APR_SUCCESS) { >+ if (APR_BRIGADE_EMPTY(bb)) >+ break; >+#ifdef DEBUGGING >+ len = -1; >+ apr_brigade_length(bb, 0, &len); >+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, >+ "proxy: CONNECT: read %" APR_OFF_T_FMT >+ " bytes from %s", len, name); >+#endif >+ rv = ap_pass_brigade(c_o->output_filters, bb); >+ if (rv == APR_SUCCESS) { >+ ap_fflush(c_o->output_filters, bb); >+ } else { >+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, >+ "proxy: CONNECT: error on %s - ap_pass_brigade", >+ name); >+ } >+ } else if (!APR_STATUS_IS_EAGAIN(rv)) { >+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, >+ "proxy: CONNECT: error on %s - ap_get_brigade", >+ name); >+ } >+ } while (rv == APR_SUCCESS); >+ >+ if (APR_STATUS_IS_EAGAIN(rv)) { >+ rv = APR_SUCCESS; >+ } >+ return rv; >+} >+ > /* CONNECT handler */ > static int proxy_connect_handler(request_rec *r, proxy_worker *worker, >- proxy_server_conf *conf, >- char *url, const char *proxyname, >+ proxy_server_conf *conf, >+ char *url, const char *proxyname, > apr_port_t proxyport) > { > apr_pool_t *p = r->pool; >@@ -84,7 +130,7 @@ > apr_bucket_brigade *bb = apr_brigade_create(p, c->bucket_alloc); > > apr_status_t err, rv; >- apr_size_t i, o, nbytes; >+ apr_size_t nbytes; > char buffer[HUGE_STRING_LEN]; > apr_socket_t *client_socket = ap_get_module_config(c->conn_config, &core_module); > int failed, rc; >@@ -101,12 +147,12 @@ > > /* is this for us? */ > if (r->method_number != M_CONNECT) { >- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, >- "proxy: CONNECT: declining URL %s", url); >- return DECLINED; >+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, >+ "proxy: CONNECT: declining URL %s", url); >+ return DECLINED; > } >- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, >- "proxy: CONNECT: serving URL %s", url); >+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, >+ "proxy: CONNECT: serving URL %s", url); > > > /* >@@ -117,50 +163,53 @@ > > /* we break the URL into host, port, uri */ > if (APR_SUCCESS != apr_uri_parse_hostinfo(p, url, &uri)) { >- return ap_proxyerror(r, HTTP_BAD_REQUEST, >+ return ap_proxyerror(r, HTTP_BAD_REQUEST, > apr_pstrcat(p, "URI cannot be parsed: ", url, NULL)); > } > >- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, >- "proxy: CONNECT: connecting %s to %s:%d", url, uri.hostname, uri.port); >+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, >+ "proxy: CONNECT: connecting %s to %s:%d", >+ url, uri.hostname, uri.port); > > /* do a DNS lookup for the destination host */ >- err = apr_sockaddr_info_get(&uri_addr, uri.hostname, APR_UNSPEC, uri.port, 0, p); >+ err = apr_sockaddr_info_get(&uri_addr, uri.hostname, APR_UNSPEC, uri.port, >+ 0, p); > > /* are we connecting directly, or via a proxy? */ > if (proxyname) { >- connectname = proxyname; >- connectport = proxyport; >+ connectname = proxyname; >+ connectport = proxyport; > err = apr_sockaddr_info_get(&connect_addr, proxyname, APR_UNSPEC, proxyport, 0, p); > } > else { >- connectname = uri.hostname; >- connectport = uri.port; >- connect_addr = uri_addr; >- } >- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, >- "proxy: CONNECT: connecting to remote proxy %s on port %d", connectname, connectport); >+ connectname = uri.hostname; >+ connectport = uri.port; >+ connect_addr = uri_addr; >+ } >+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, >+ "proxy: CONNECT: connecting to remote proxy %s on port %d", >+ connectname, connectport); > > /* check if ProxyBlock directive on this host */ > if (OK != ap_proxy_checkproxyblock(r, conf, uri_addr)) { >- return ap_proxyerror(r, HTTP_FORBIDDEN, >- "Connect to remote machine blocked"); >+ return ap_proxyerror(r, HTTP_FORBIDDEN, >+ "Connect to remote machine blocked"); > } > > /* Check if it is an allowed port */ > if (conf->allowed_connect_ports->nelts == 0) { >- /* Default setting if not overridden by AllowCONNECT */ >- switch (uri.port) { >+ /* Default setting if not overridden by AllowCONNECT */ >+ switch (uri.port) { > case APR_URI_HTTPS_DEFAULT_PORT: > case APR_URI_SNEWS_DEFAULT_PORT: >- break; >+ break; > default: >- /* XXX can we call ap_proxyerror() here to get a nice log message? */ >- return HTTP_FORBIDDEN; >- } >+ return ap_proxyerror(r, HTTP_FORBIDDEN, >+ "Connect to remote machine blocked"); >+ } > } else if(!allowed_port(conf, uri.port)) { >- /* XXX can we call ap_proxyerror() here to get a nice log message? */ >- return HTTP_FORBIDDEN; >+ return ap_proxyerror(r, HTTP_FORBIDDEN, >+ "Connect to remote machine blocked"); > } > > /* >@@ -173,7 +222,7 @@ > * until we get a successful connection > */ > if (APR_SUCCESS != err) { >- return ap_proxyerror(r, HTTP_BAD_GATEWAY, apr_pstrcat(p, >+ return ap_proxyerror(r, HTTP_BAD_GATEWAY, apr_pstrcat(p, > "DNS lookup failure for: ", > connectname, NULL)); > } >@@ -198,44 +247,63 @@ > return DECLINED; > } > else { >- return HTTP_BAD_GATEWAY; >+ return ap_proxyerror(r, HTTP_BAD_GATEWAY, apr_pstrcat(p, >+ "connect failure for: ", >+ connectname, NULL)); > } > } > >+ /* setup polling for connection */ >+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, >+ "proxy: CONNECT: setting up poll()"); >+ >+ if ((rv = apr_pollset_create(&pollset, 2, r->pool, 0)) != APR_SUCCESS) { >+ apr_socket_close(sock); >+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, >+ "proxy: CONNECT: error apr_pollset_create()"); >+ return HTTP_INTERNAL_SERVER_ERROR; >+ } >+ >+ /* Add client side to the poll */ >+ pollfd.p = r->pool; >+ pollfd.desc_type = APR_POLL_SOCKET; >+ pollfd.reqevents = APR_POLLIN; >+ pollfd.desc.s = client_socket; >+ pollfd.client_data = NULL; >+ apr_pollset_add(pollset, &pollfd); >+ >+ /* Add the server side to the poll */ >+ pollfd.desc.s = sock; >+ apr_pollset_add(pollset, &pollfd); >+ > /* > * Step Three: Send the Request > * > * Send the HTTP/1.1 CONNECT request to the remote server > */ > >- /* we are acting as a tunnel - the output filter stack should >- * be completely empty, because when we are done here we are done completely. >- * We add the NULL filter to the stack to do this... >- */ >- r->output_filters = NULL; >- > backconn = ap_run_create_connection(c->pool, r->server, sock, > c->id, c->sbh, c->bucket_alloc); > if (!backconn) { > /* peer reset */ >- ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server, >- "proxy: an error occurred creating a new connection " >- "to %pI (%s)", connect_addr, connectname); >+ ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, >+ "proxy: an error occurred creating a new connection " >+ "to %pI (%s)", connect_addr, connectname); > apr_socket_close(sock); > return HTTP_INTERNAL_SERVER_ERROR; > } > ap_proxy_ssl_disable(backconn); > rc = ap_run_pre_connection(backconn, sock); > if (rc != OK && rc != DONE) { >- backconn->aborted = 1; >- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, >- "proxy: CONNECT: pre_connection setup failed (%d)", rc); >- return HTTP_INTERNAL_SERVER_ERROR; >+ backconn->aborted = 1; >+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, >+ "proxy: CONNECT: pre_connection setup failed (%d)", rc); >+ return HTTP_INTERNAL_SERVER_ERROR; > } > >- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, >- "proxy: CONNECT: connection complete to %pI (%s)", >- connect_addr, connectname); >+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, >+ "proxy: CONNECT: connection complete to %pI (%s)", >+ connect_addr, connectname); > > > /* If we are connecting through a remote proxy, we need to pass >@@ -244,7 +312,7 @@ > if (proxyport) { > /* FIXME: Error checking ignored. > */ >- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, >+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, > "proxy: CONNECT: sending the CONNECT request to the remote proxy"); > ap_fprintf(backconn->output_filters, bb, > "CONNECT %s HTTP/1.0" CRLF, r->uri); >@@ -253,10 +321,11 @@ > ap_fflush(backconn->output_filters, bb); > } > else { >- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, >- "proxy: CONNECT: Returning 200 OK Status"); >+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, >+ "proxy: CONNECT: Returning 200 OK Status"); >+ > nbytes = apr_snprintf(buffer, sizeof(buffer), >- "HTTP/1.0 200 Connection Established" CRLF); >+ "HTTP/1.0 200 Connection Established" CRLF); > ap_xlate_proto_to_ascii(buffer, nbytes); > ap_fwrite(c->output_filters, bb, buffer, nbytes); > nbytes = apr_snprintf(buffer, sizeof(buffer), >@@ -265,7 +334,7 @@ > ap_fwrite(c->output_filters, bb, buffer, nbytes); > ap_fflush(c->output_filters, bb); > #if 0 >- /* This is safer code, but it doesn't work yet. I'm leaving it >+ /* This is safer code, but it doesn't work yet. I'm leaving it > * here so that I can fix it later. > */ > r->status = HTTP_OK; >@@ -275,46 +344,34 @@ > #endif > } > >- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, >- "proxy: CONNECT: setting up poll()"); >- > /* > * Step Four: Handle Data Transfer > * > * Handle two way transfer of data over the socket (this is a tunnel). > */ > >-/* r->sent_bodyct = 1;*/ >- >- if ((rv = apr_pollset_create(&pollset, 2, r->pool, 0)) != APR_SUCCESS) >- { >- apr_socket_close(sock); >- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, >- "proxy: CONNECT: error apr_pollset_create()"); >- return HTTP_INTERNAL_SERVER_ERROR; >- } >- >- /* Add client side to the poll */ >- pollfd.p = r->pool; >- pollfd.desc_type = APR_POLL_SOCKET; >- pollfd.reqevents = APR_POLLIN; >- pollfd.desc.s = client_socket; >- pollfd.client_data = NULL; >- apr_pollset_add(pollset, &pollfd); >+ /* we are now acting as a tunnel - the input/output filter stacks should >+ * not contain any non-connection filters. >+ */ >+ r->output_filters = c->output_filters; >+ r->proto_output_filters = c->output_filters; >+ r->input_filters = c->input_filters; >+ r->proto_input_filters = c->input_filters; > >- /* Add the server side to the poll */ >- pollfd.desc.s = sock; >- apr_pollset_add(pollset, &pollfd); >+/* r->sent_bodyct = 1;*/ > >- while (1) { /* Infinite loop until error (one side closes the connection) */ >- if ((rv = apr_pollset_poll(pollset, -1, &pollcnt, &signalled)) != APR_SUCCESS) { >- apr_socket_close(sock); >- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "proxy: CONNECT: error apr_poll()"); >+ /* Infinite loop until error (one side closes the connection) */ >+ while (1) { >+ rv = apr_pollset_poll(pollset, -1, &pollcnt, &signalled); >+ if (rv != APR_SUCCESS) { >+ apr_socket_close(sock); >+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, >+ "proxy: CONNECT: error apr_poll()"); > return HTTP_INTERNAL_SERVER_ERROR; > } > #ifdef DEBUGGING >- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, >- "proxy: CONNECT: woke from select(), i=%d", pollcnt); >+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, >+ "proxy: CONNECT: woke from poll(), i=%d", pollcnt); > #endif > > for (pi = 0; pi < pollcnt; pi++) { >@@ -322,89 +379,42 @@ > > if (cur->desc.s == sock) { > pollevent = cur->rtnevents; >- if (pollevent & APR_POLLIN) { >-#ifdef DEBUGGING >- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, >- "proxy: CONNECT: sock was set"); >-#endif >- nbytes = sizeof(buffer); >- apr_brigade_cleanup(bb); >- rv = ap_get_brigade(backconn->input_filters, bb, >- AP_MODE_READBYTES, APR_NONBLOCK_READ, >- nbytes); >- if (APR_STATUS_IS_EAGAIN(rv)) { >- rv = APR_SUCCESS; >- } else if (rv != APR_SUCCESS) { >- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, >- "proxy: CONNECT: error on backconn " >- "- ap_get_brigade"); >- break; >- } else { >- rv = ap_pass_brigade(c->output_filters, bb); >- if (rv != APR_SUCCESS) { >- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, >- "proxy: CONNECT: error on backconn " >- "- ap_pass_brigade"); >- break; >- } >- ap_fflush(c->output_filters, bb); >- } >- } > if ((pollevent & APR_POLLERR) || (pollevent & APR_POLLHUP)) { > rv = APR_EPIPE; >- ap_log_rerror(APLOG_MARK, APLOG_NOTICE, rv, r, >+ ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, > "proxy: CONNECT: err/hup on backconn"); >- break; > } >+ if (pollevent & APR_POLLIN) { >+#ifdef DEBUGGING >+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, >+ "proxy: CONNECT: sock was readable"); >+#endif >+ rv = proxy_connect_transfer(r, backconn, c, bb, "sock"); >+ } > } > else if (cur->desc.s == client_socket) { > pollevent = cur->rtnevents; >+ if ((pollevent & APR_POLLERR) || (pollevent & APR_POLLHUP)) { >+ rv = APR_EOF; >+ ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, >+ "proxy: CONNECT: err/hup on client socket"); >+ } > if (pollevent & APR_POLLIN) { > #ifdef DEBUGGING >- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, >- "proxy: CONNECT: client was set"); >+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, >+ "proxy: CONNECT: client was readable"); > #endif >- nbytes = sizeof(buffer); >- apr_brigade_cleanup(bb); >- rv = ap_get_brigade(c->input_filters, bb, >- AP_MODE_READBYTES, APR_NONBLOCK_READ, >- nbytes); >- if (rv == APR_SUCCESS) { >- i = nbytes; >-#ifdef DEBUGGING >- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, >- "proxy: CONNECT: read %d from client", i); >-#endif >- rv = ap_pass_brigade(backconn->output_filters, bb); >- if (rv != APR_SUCCESS) { >- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, >- "proxy: CONNECT: error on client " >- "ap_pass_brigade"); >- break; >- } >- ap_fflush(backconn->output_filters, bb); >- } >- else if (APR_STATUS_IS_EAGAIN(rv)) { >- rv = APR_SUCCESS; >- } >- else { >- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, >- "proxy: CONNECT: error on client " >- "- ap_get_brigade"); >- break; >- } >+ rv = proxy_connect_transfer(r, c, backconn, bb, "client"); > } >- if ((pollevent & APR_POLLERR) || (pollevent & APR_POLLHUP)) { >- rv = APR_EPIPE; >- ap_log_rerror(APLOG_MARK, APLOG_NOTICE, rv, r, >- "proxy: CONNECT: err/hup on client socket"); >- break; >- } > } > else { >- ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server, >- "proxy: CONNECT: unknown socket in pollset"); >- break; >+ rv = APR_EBADF; >+ ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, >+ "proxy: CONNECT: unknown socket in pollset"); >+ } >+ >+ if (rv != APR_SUCCESS) { >+ break; > } > } > if (rv != APR_SUCCESS) { >@@ -412,8 +422,8 @@ > } > } > >- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, >- "proxy: CONNECT: finished with poll() - cleaning up"); >+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, >+ "proxy: CONNECT: finished with poll() - cleaning up"); > > /* > * Step Five: Clean Up >@@ -423,6 +433,8 @@ > > ap_lingering_close(backconn); > >+ c->aborted = 1; >+ > return OK; > } >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 29744
:
13393
|
14066
|
16105
| 18222 |
19504
|
19723
|
20331
|
20379
|
20911
|
20946
|
21628
|
21703
|
22248
|
22877
|
23840
|
24252
|
24615
|
24616
|
26225
|
29072
|
30144