current jcc.c,1.447,1.448
Fabian Keil <[email protected]> Sat, 24 Dec 2016 15:58:51 +0000
| Newsgroups | gmane.comp.web.privoxy.cvs |
|---|---|
| Message-ID | <[email protected]> |
Update of /cvsroot/ijbswa/current
In directory sfp-cvs-1.v30.ch3.sourceforge.com:/tmp/cvs-serv24978
Modified Files:
jcc.c
Log Message:
Factor handle_established_connection() out of chat()
... to make fuzzing it more convenient.
Index: jcc.c
===================================================================
RCS file: /cvsroot/ijbswa/current/jcc.c,v
retrieving revision 1.447
retrieving revision 1.448
diff -C2 -d -r1.447 -r1.448
*** jcc.c 27 Sep 2016 22:48:28 -0000 1.447
--- jcc.c 24 Dec 2016 15:58:49 -0000 1.448
***************
*** 1807,1825 ****
/*********************************************************************
*
! * Function : chat
! *
! * Description : Once a connection from the client has been accepted,
! * this function is called (via serve()) to handle the
! * main business of the communication. This function
! * returns after dealing with a single request. It can
! * be called multiple times with the same client socket
! * if the client is keeping the connection alive.
! *
! * The decision whether or not a client connection will
! * be kept alive is up to the caller which also must
! * close the client socket when done.
*
! * FIXME: chat is nearly thousand lines long.
! * Ridiculous.
*
* Parameters :
--- 1807,1814 ----
/*********************************************************************
*
! * Function : handle_established_connection
*
! * Description : Shuffle data between client and server once the
! * connection has been established.
*
* Parameters :
***************
*** 1829,1833 ****
*
*********************************************************************/
! static void chat(struct client_state *csp)
{
char buf[BUFFER_SIZE];
--- 1818,1823 ----
*
*********************************************************************/
! static void handle_established_connection(struct client_state *csp,
! const struct forward_spec *fwd)
{
char buf[BUFFER_SIZE];
***************
*** 1840,1844 ****
int ms_iis5_hack = 0;
unsigned long long byte_count = 0;
- const struct forward_spec *fwd;
struct http_request *http;
long len = 0; /* for buffer sizes (and negative error codes) */
--- 1830,1833 ----
***************
*** 1856,2107 ****
http = csp->http;
- if (receive_client_request(csp) != JB_ERR_OK)
- {
- return;
- }
- if (parse_client_request(csp) != JB_ERR_OK)
- {
- return;
- }
-
- /* decide how to route the HTTP request */
- fwd = forward_url(csp, http);
- if (NULL == fwd)
- {
- log_error(LOG_LEVEL_FATAL, "gateway spec is NULL!?!? This can't happen!");
- /* Never get here - LOG_LEVEL_FATAL causes program exit */
- return;
- }
-
- /*
- * build the http request to send to the server
- * we have to do one of the following:
- *
- * create = use the original HTTP request to create a new
- * HTTP request that has either the path component
- * without the http://domainspec (w/path) or the
- * full orininal URL (w/url)
- * Note that the path and/or the HTTP version may
- * have been altered by now.
- *
- * connect = Open a socket to the host:port of the server
- * and short-circuit server and client socket.
- *
- * pass = Pass the request unchanged if forwarding a CONNECT
- * request to a parent proxy. Note that we'll be sending
- * the CFAIL message ourselves if connecting to the parent
- * fails, but we won't send a CSUCCEED message if it works,
- * since that would result in a double message (ours and the
- * parent's). After sending the request to the parent, we simply
- * tunnel.
- *
- * here's the matrix:
- * SSL
- * 0 1
- * +--------+--------+
- * | | |
- * 0 | create | connect|
- * | w/path | |
- * Forwarding +--------+--------+
- * | | |
- * 1 | create | pass |
- * | w/url | |
- * +--------+--------+
- *
- */
-
- if (http->ssl && connect_port_is_forbidden(csp))
- {
- const char *acceptable_connect_ports =
- csp->action->string[ACTION_STRING_LIMIT_CONNECT];
- assert(NULL != acceptable_connect_ports);
- log_error(LOG_LEVEL_INFO, "Request from %s marked for blocking. "
- "limit-connect{%s} doesn't allow CONNECT requests to %s",
- csp->ip_addr_str, acceptable_connect_ports, csp->http->hostport);
- csp->action->flags |= ACTION_BLOCK;
- http->ssl = 0;
- }
-
- if (http->ssl == 0)
- {
- freez(csp->headers->first->str);
- build_request_line(csp, fwd, &csp->headers->first->str);
- }
-
- /*
- * We have a request. Check if one of the crunchers wants it.
- */
- if (crunch_response_triggered(csp, crunchers_all))
- {
- /*
- * Yes. The client got the crunch response and we're done here.
- */
- return;
- }
-
- log_applied_actions(csp->action);
- log_error(LOG_LEVEL_GPC, "%s%s", http->hostport, http->path);
-
- if (fwd->forward_host)
- {
- log_error(LOG_LEVEL_CONNECT, "via [%s]:%d to: %s",
- fwd->forward_host, fwd->forward_port, http->hostport);
- }
- else
- {
- log_error(LOG_LEVEL_CONNECT, "to %s", http->hostport);
- }
-
- /* here we connect to the server, gateway, or the forwarder */
-
- #ifdef FEATURE_CONNECTION_KEEP_ALIVE
- if ((csp->server_connection.sfd != JB_INVALID_SOCKET)
- && socket_is_still_alive(csp->server_connection.sfd)
- && connection_destination_matches(&csp->server_connection, http, fwd))
- {
- log_error(LOG_LEVEL_CONNECT,
- "Reusing server socket %d connected to %s. Total requests: %u.",
- csp->server_connection.sfd, csp->server_connection.host,
- csp->server_connection.requests_sent_total);
- }
- else
- {
- if (csp->server_connection.sfd != JB_INVALID_SOCKET)
- {
- #ifdef FEATURE_CONNECTION_SHARING
- if (csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING)
- {
- remember_connection(&csp->server_connection);
- }
- else
- #endif /* def FEATURE_CONNECTION_SHARING */
- {
- log_error(LOG_LEVEL_CONNECT,
- "Closing server socket %d connected to %s. Total requests: %u.",
- csp->server_connection.sfd, csp->server_connection.host,
- csp->server_connection.requests_sent_total);
- close_socket(csp->server_connection.sfd);
- }
- mark_connection_closed(&csp->server_connection);
- }
- #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
-
- csp->server_connection.sfd = forwarded_connect(fwd, http, csp);
-
- if (csp->server_connection.sfd == JB_INVALID_SOCKET)
- {
- if ((fwd->type != SOCKS_NONE) && (fwd->type != FORWARD_WEBSERVER))
- {
- /* Socks error. */
- rsp = error_response(csp, "forwarding-failed");
- }
- else if (errno == EINVAL)
- {
- rsp = error_response(csp, "no-such-domain");
- }
- else
- {
- rsp = error_response(csp, "connect-failed");
- }
-
- /* Write the answer to the client */
- if (rsp != NULL)
- {
- send_crunch_response(csp, rsp);
- }
-
- /*
- * Temporary workaround to prevent already-read client
- * bodies from being parsed as new requests. For now we
- * err on the safe side and throw all the following
- * requests under the bus, even if no client body has been
- * buffered. A compliant client will repeat the dropped
- * requests on an untainted connection.
- *
- * The proper fix is to discard the no longer needed
- * client body in the buffer (if there is one) and to
- * continue parsing the bytes that follow.
- */
- drain_and_close_socket(csp->cfd);
- csp->cfd = JB_INVALID_SOCKET;
-
- return;
- }
- #ifdef FEATURE_CONNECTION_KEEP_ALIVE
- save_connection_destination(csp->server_connection.sfd,
- http, fwd, &csp->server_connection);
- csp->server_connection.keep_alive_timeout =
- (unsigned)csp->config->keep_alive_timeout;
- }
- #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
-
- csp->server_connection.requests_sent_total++;
-
- if ((fwd->type == SOCKS_5T) && (NULL == csp->headers->first))
- {
- /* Client headers have been sent optimistically */
- assert(csp->headers->last == NULL);
- }
- else if (fwd->forward_host || (http->ssl == 0))
- {
- int write_failure;
- hdr = list_to_text(csp->headers);
- if (hdr == NULL)
- {
- /* FIXME Should handle error properly */
- log_error(LOG_LEVEL_FATAL, "Out of memory parsing client header");
- }
- list_remove_all(csp->headers);
-
- /*
- * Write the client's (modified) header to the server
- * (along with anything else that may be in the buffer)
- */
- write_failure = 0 != write_socket(csp->server_connection.sfd, hdr, strlen(hdr));
- freez(hdr);
-
- if (write_failure)
- {
- log_error(LOG_LEVEL_CONNECT,
- "Failed sending request headers to: %s: %E", http->hostport);
- }
- else if (((csp->flags & CSP_FLAG_PIPELINED_REQUEST_WAITING) == 0)
- && (flush_socket(csp->server_connection.sfd, csp->client_iob) < 0))
- {
- write_failure = 1;
- log_error(LOG_LEVEL_CONNECT,
- "Failed sending request body to: %s: %E", http->hostport);
- }
-
- if (write_failure)
- {
- rsp = error_response(csp, "connect-failed");
- if (rsp)
- {
- send_crunch_response(csp, rsp);
- }
- return;
- }
- }
- else
- {
- /*
- * We're running an SSL tunnel and we're not forwarding,
- * so just ditch the client headers, send the "connect succeeded"
- * message to the client, flush the rest, and get out of the way.
- */
- list_remove_all(csp->headers);
- if (write_socket(csp->cfd, CSUCCEED, strlen(CSUCCEED)))
- {
- return;
- }
- clear_iob(csp->client_iob);
- }
-
- log_error(LOG_LEVEL_CONNECT, "to %s successful", http->hostport);
-
- /* XXX: should the time start earlier for optimistically sent data? */
- csp->server_connection.request_sent = time(NULL);
-
maxfd = (csp->cfd > csp->server_connection.sfd) ?
csp->cfd : csp->server_connection.sfd;
--- 1845,1848 ----
***************
*** 2799,2802 ****
--- 2540,2831 ----
}
+ /*********************************************************************
+ *
+ * Function : chat
+ *
+ * Description : Once a connection from the client has been accepted,
+ * this function is called (via serve()) to handle the
+ * main business of the communication. This function
+ * returns after dealing with a single request. It can
+ * be called multiple times with the same client socket
+ * if the client is keeping the connection alive.
+ *
+ * The decision whether or not a client connection will
+ * be kept alive is up to the caller which also must
+ * close the client socket when done.
+ *
+ * FIXME: chat is nearly thousand lines long.
+ * Ridiculous.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : Nothing.
+ *
+ *********************************************************************/
+ static void chat(struct client_state *csp)
+ {
+ char buf[BUFFER_SIZE];
+ char *hdr;
+ const struct forward_spec *fwd;
+ struct http_request *http;
+ /* Skeleton for HTTP response, if we should intercept the request */
+ struct http_response *rsp;
+
+ memset(buf, 0, sizeof(buf));
+
+ http = csp->http;
+
+ if (receive_client_request(csp) != JB_ERR_OK)
+ {
+ return;
+ }
+ if (parse_client_request(csp) != JB_ERR_OK)
+ {
+ return;
+ }
+
+ /* decide how to route the HTTP request */
+ fwd = forward_url(csp, http);
+ if (NULL == fwd)
+ {
+ log_error(LOG_LEVEL_FATAL, "gateway spec is NULL!?!? This can't happen!");
+ /* Never get here - LOG_LEVEL_FATAL causes program exit */
+ return;
+ }
+
+ /*
+ * build the http request to send to the server
+ * we have to do one of the following:
+ *
+ * create = use the original HTTP request to create a new
+ * HTTP request that has either the path component
+ * without the http://domainspec (w/path) or the
+ * full orininal URL (w/url)
+ * Note that the path and/or the HTTP version may
+ * have been altered by now.
+ *
+ * connect = Open a socket to the host:port of the server
+ * and short-circuit server and client socket.
+ *
+ * pass = Pass the request unchanged if forwarding a CONNECT
+ * request to a parent proxy. Note that we'll be sending
+ * the CFAIL message ourselves if connecting to the parent
+ * fails, but we won't send a CSUCCEED message if it works,
+ * since that would result in a double message (ours and the
+ * parent's). After sending the request to the parent, we simply
+ * tunnel.
+ *
+ * here's the matrix:
+ * SSL
+ * 0 1
+ * +--------+--------+
+ * | | |
+ * 0 | create | connect|
+ * | w/path | |
+ * Forwarding +--------+--------+
+ * | | |
+ * 1 | create | pass |
+ * | w/url | |
+ * +--------+--------+
+ *
+ */
+
+ if (http->ssl && connect_port_is_forbidden(csp))
+ {
+ const char *acceptable_connect_ports =
+ csp->action->string[ACTION_STRING_LIMIT_CONNECT];
+ assert(NULL != acceptable_connect_ports);
+ log_error(LOG_LEVEL_INFO, "Request from %s marked for blocking. "
+ "limit-connect{%s} doesn't allow CONNECT requests to %s",
+ csp->ip_addr_str, acceptable_connect_ports, csp->http->hostport);
+ csp->action->flags |= ACTION_BLOCK;
+ http->ssl = 0;
+ }
+
+ if (http->ssl == 0)
+ {
+ freez(csp->headers->first->str);
+ build_request_line(csp, fwd, &csp->headers->first->str);
+ }
+
+ /*
+ * We have a request. Check if one of the crunchers wants it.
+ */
+ if (crunch_response_triggered(csp, crunchers_all))
+ {
+ /*
+ * Yes. The client got the crunch response and we're done here.
+ */
+ return;
+ }
+
+ log_applied_actions(csp->action);
+ log_error(LOG_LEVEL_GPC, "%s%s", http->hostport, http->path);
+
+ if (fwd->forward_host)
+ {
+ log_error(LOG_LEVEL_CONNECT, "via [%s]:%d to: %s",
+ fwd->forward_host, fwd->forward_port, http->hostport);
+ }
+ else
+ {
+ log_error(LOG_LEVEL_CONNECT, "to %s", http->hostport);
+ }
+
+ /* here we connect to the server, gateway, or the forwarder */
+
+ #ifdef FEATURE_CONNECTION_KEEP_ALIVE
+ if ((csp->server_connection.sfd != JB_INVALID_SOCKET)
+ && socket_is_still_alive(csp->server_connection.sfd)
+ && connection_destination_matches(&csp->server_connection, http, fwd))
+ {
+ log_error(LOG_LEVEL_CONNECT,
+ "Reusing server socket %d connected to %s. Total requests: %u.",
+ csp->server_connection.sfd, csp->server_connection.host,
+ csp->server_connection.requests_sent_total);
+ }
+ else
+ {
+ if (csp->server_connection.sfd != JB_INVALID_SOCKET)
+ {
+ #ifdef FEATURE_CONNECTION_SHARING
+ if (csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING)
+ {
+ remember_connection(&csp->server_connection);
+ }
+ else
+ #endif /* def FEATURE_CONNECTION_SHARING */
+ {
+ log_error(LOG_LEVEL_CONNECT,
+ "Closing server socket %d connected to %s. Total requests: %u.",
+ csp->server_connection.sfd, csp->server_connection.host,
+ csp->server_connection.requests_sent_total);
+ close_socket(csp->server_connection.sfd);
+ }
+ mark_connection_closed(&csp->server_connection);
+ }
+ #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
+
+ csp->server_connection.sfd = forwarded_connect(fwd, http, csp);
+
+ if (csp->server_connection.sfd == JB_INVALID_SOCKET)
+ {
+ if (fwd->type != SOCKS_NONE)
+ {
+ /* Socks error. */
+ rsp = error_response(csp, "forwarding-failed");
+ }
+ else if (errno == EINVAL)
+ {
+ rsp = error_response(csp, "no-such-domain");
+ }
+ else
+ {
+ rsp = error_response(csp, "connect-failed");
+ }
+
+ /* Write the answer to the client */
+ if (rsp != NULL)
+ {
+ send_crunch_response(csp, rsp);
+ }
+
+ /*
+ * Temporary workaround to prevent already-read client
+ * bodies from being parsed as new requests. For now we
+ * err on the safe side and throw all the following
+ * requests under the bus, even if no client body has been
+ * buffered. A compliant client will repeat the dropped
+ * requests on an untainted connection.
+ *
+ * The proper fix is to discard the no longer needed
+ * client body in the buffer (if there is one) and to
+ * continue parsing the bytes that follow.
+ */
+ drain_and_close_socket(csp->cfd);
+ csp->cfd = JB_INVALID_SOCKET;
+
+ return;
+ }
+ #ifdef FEATURE_CONNECTION_KEEP_ALIVE
+ save_connection_destination(csp->server_connection.sfd,
+ http, fwd, &csp->server_connection);
+ csp->server_connection.keep_alive_timeout =
+ (unsigned)csp->config->keep_alive_timeout;
+ }
+ #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
+
+ csp->server_connection.requests_sent_total++;
+
+ if ((fwd->type == SOCKS_5T) && (NULL == csp->headers->first))
+ {
+ /* Client headers have been sent optimistically */
+ assert(csp->headers->last == NULL);
+ }
+ else if (fwd->forward_host || (http->ssl == 0))
+ {
+ int write_failure;
+ hdr = list_to_text(csp->headers);
+ if (hdr == NULL)
+ {
+ /* FIXME Should handle error properly */
+ log_error(LOG_LEVEL_FATAL, "Out of memory parsing client header");
+ }
+ list_remove_all(csp->headers);
+
+ /*
+ * Write the client's (modified) header to the server
+ * (along with anything else that may be in the buffer)
+ */
+ write_failure = 0 != write_socket(csp->server_connection.sfd, hdr, strlen(hdr));
+ freez(hdr);
+
+ if (write_failure)
+ {
+ log_error(LOG_LEVEL_CONNECT,
+ "Failed sending request headers to: %s: %E", http->hostport);
+ }
+ else if (((csp->flags & CSP_FLAG_PIPELINED_REQUEST_WAITING) == 0)
+ && (flush_socket(csp->server_connection.sfd, csp->client_iob) < 0))
+ {
+ write_failure = 1;
+ log_error(LOG_LEVEL_CONNECT,
+ "Failed sending request body to: %s: %E", http->hostport);
+ }
+
+ if (write_failure)
+ {
+ rsp = error_response(csp, "connect-failed");
+ if (rsp)
+ {
+ send_crunch_response(csp, rsp);
+ }
+ return;
+ }
+ }
+ else
+ {
+ /*
+ * We're running an SSL tunnel and we're not forwarding,
+ * so just ditch the client headers, send the "connect succeeded"
+ * message to the client, flush the rest, and get out of the way.
+ */
+ list_remove_all(csp->headers);
+ if (write_socket(csp->cfd, CSUCCEED, strlen(CSUCCEED)))
+ {
+ return;
+ }
+ clear_iob(csp->client_iob);
+ }
+
+ log_error(LOG_LEVEL_CONNECT, "to %s successful", http->hostport);
+
+ /* XXX: should the time start earlier for optimistically sent data? */
+ csp->server_connection.request_sent = time(NULL);
+
+ handle_established_connection(csp, fwd);
+ }
+
#ifdef FEATURE_CONNECTION_KEEP_ALIVE
------------------------------------------------------------------------------
Developer Access Program for Intel Xeon Phi Processors
Access to Intel Xeon Phi processor-based developer platforms.
With one year of Intel Parallel Studio XE.
Training and support from Colfax.
Order your platform today.http://sdm.link/intel