-const char jcc_rcs[] = "$Id: jcc.c,v 1.429 2014/07/25 11:55:11 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 $
*
* 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
{
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);
}
+
+#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
}
#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 */
enlist(csp->headers, http->cmd);
/* Append the previously read headers */
- list_append_list_unique(csp->headers, headers);
+ err = list_append_list_unique(csp->headers, headers);
destroy_list(headers);
- return JB_ERR_OK;
+ return err;
}
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
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
*/
}
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))
{
* 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);