X-Git-Url: http://www.privoxy.org/gitweb/?p=privoxy.git;a=blobdiff_plain;f=jcc.c;h=86f4a70baac1cd050751662935fbb763357550f0;hp=e4584ecc5c28384e59889628387d0bcc8871a64d;hb=c3eca0beea485ff71af9136d777ac8d5c122c07c;hpb=628a8a88931fa0f2eb0bd250a17348d3a0426942 diff --git a/jcc.c b/jcc.c index e4584ecc..86f4a70b 100644 --- a/jcc.c +++ b/jcc.c @@ -1,4 +1,4 @@ -const char jcc_rcs[] = "$Id: jcc.c,v 1.430 2014/07/25 11:56:54 fabiankeil Exp $"; +const char jcc_rcs[] = "$Id: jcc.c,v 1.436 2015/03/27 12:40:08 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/jcc.c,v $ @@ -1333,7 +1333,7 @@ enum chunk_status * * Function : chunked_body_is_complete * - * Description : Figures out wheter or not a chunked body is complete. + * Description : Figures out whether or not a chunked body is complete. * * Currently it always starts at the beginning of the * buffer which is somewhat wasteful and prevents Privoxy @@ -1388,12 +1388,15 @@ static enum chunk_status chunked_body_is_complete(struct iob *iob, size_t *lengt { return CHUNK_STATUS_PARSE_ERROR; } - /* - * Skip "\r\n", the chunk data and another "\r\n". - * Moving p to either the beginning of the next chunk-size - * or one byte beyond the end of the chunked data. - */ - p += 2 + chunksize + 2; + /* Move beyond the chunkdata. */ + p += 2 + chunksize; + + /* There should be another "\r\n" to skip */ + if (memcmp(p, "\r\n", 2)) + { + return CHUNK_STATUS_PARSE_ERROR; + } + p += 2; } while (chunksize > 0U); *length = (size_t)(p - iob->cur); @@ -1462,6 +1465,70 @@ static jb_err receive_chunked_client_request_body(struct client_state *csp) } + +#ifdef FEATURE_FORCE_LOAD +/********************************************************************* + * + * Function : force_required + * + * Description : Checks a request line to see if it contains + * the FORCE_PREFIX. If it does, it is removed + * unless enforcing requests has beend disabled. + * + * Parameters : + * 1 : request_line = HTTP request line + * + * Returns : TRUE if force is required, FALSE otherwise. + * + *********************************************************************/ +static int force_required(const struct client_state *csp, char *request_line) +{ + char *p; + + p = strstr(request_line, "http://"); + if (p != NULL) + { + /* Skip protocol */ + p += strlen("http://"); + } + else + { + /* Intercepted request usually don't specify the protocol. */ + p = request_line; + } + + /* Go to the beginning of the path */ + p = strstr(p, "/"); + if (p == NULL) + { + /* + * If the path is missing the request line is invalid and we + * are done here. The client-visible rejection happens later on. + */ + return 0; + } + + if (0 == strncmpic(p, FORCE_PREFIX, strlen(FORCE_PREFIX) - 1)) + { + if (!(csp->config->feature_flags & RUNTIME_FEATURE_ENFORCE_BLOCKS)) + { + /* XXX: Should clean more carefully */ + strclean(request_line, FORCE_PREFIX); + log_error(LOG_LEVEL_FORCE, + "Enforcing request: \"%s\".", request_line); + + return 1; + } + log_error(LOG_LEVEL_FORCE, + "Ignored force prefix in request: \"%s\".", request_line); + } + + return 0; + +} +#endif /* def FEATURE_FORCE_LOAD */ + + /********************************************************************* * * Function : receive_client_request @@ -1509,23 +1576,9 @@ static jb_err receive_client_request(struct client_state *csp) } #ifdef FEATURE_FORCE_LOAD - /* - * If this request contains the FORCE_PREFIX and blocks - * aren't enforced, get rid of it and set the force flag. - */ - if (strstr(req, FORCE_PREFIX)) + if (force_required(csp, req)) { - if (csp->config->feature_flags & RUNTIME_FEATURE_ENFORCE_BLOCKS) - { - log_error(LOG_LEVEL_FORCE, - "Ignored force prefix in request: \"%s\".", req); - } - else - { - strclean(req, FORCE_PREFIX); - log_error(LOG_LEVEL_FORCE, "Enforcing request: \"%s\".", req); - csp->flags |= CSP_FLAG_FORCED; - } + csp->flags |= CSP_FLAG_FORCED; } #endif /* def FEATURE_FORCE_LOAD */ @@ -1953,6 +2006,21 @@ static void chat(struct client_state *csp) 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 @@ -3497,7 +3565,7 @@ int main(int argc, char **argv) cgi_init_error_messages(); /* - * If runnig on unix and without the --nodaemon + * If running on unix and without the --no-daemon * option, become a daemon. I.e. fork, detach * from tty and get process group leadership */ @@ -3916,7 +3984,9 @@ static void listen_loop(void) } csp = &csp_list->csp; - log_error(LOG_LEVEL_CONNECT, "Listening for new connections ... "); + log_error(LOG_LEVEL_CONNECT, + "Waiting for the next client connection. Currently active threads: %d", + active_threads); if (!accept_connection(csp, bfds)) { @@ -4170,7 +4240,8 @@ static void listen_loop(void) * XXX: If you assume ... */ log_error(LOG_LEVEL_ERROR, - "Unable to take any additional connections: %E"); + "Unable to take any additional connections: %E. Active threads: %d", + active_threads); write_socket(csp->cfd, TOO_MANY_CONNECTIONS_RESPONSE, strlen(TOO_MANY_CONNECTIONS_RESPONSE)); close_socket(csp->cfd);