X-Git-Url: http://www.privoxy.org/gitweb/%40user-manual%40%40actions-help-prefix%40HIDE-FROM-HEADER?a=blobdiff_plain;f=jcc.c;h=056a6c1e9b1af98786ccd072ac4d47acec0e87a5;hb=2c224bc9ed07e2507e1ad66a41e98f66e9af96c9;hp=1cf56e40883b5f53f659f9d4bfe3786dcb7d24da;hpb=071dda21b7dbb77b3b8a36fd882f187b2fd5d698;p=privoxy.git diff --git a/jcc.c b/jcc.c index 1cf56e40..056a6c1e 100644 --- a/jcc.c +++ b/jcc.c @@ -1,4 +1,4 @@ -const char jcc_rcs[] = "$Id: jcc.c,v 1.121 2007/01/27 10:52:56 fabiankeil Exp $"; +const char jcc_rcs[] = "$Id: jcc.c,v 1.127 2007/03/20 13:53:17 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/jcc.c,v $ @@ -33,6 +33,37 @@ const char jcc_rcs[] = "$Id: jcc.c,v 1.121 2007/01/27 10:52:56 fabiankeil Exp $" * * Revisions : * $Log: jcc.c,v $ + * Revision 1.127 2007/03/20 13:53:17 fabiankeil + * Log the source address for ACL-related connection drops. + * + * Revision 1.126 2007/03/17 15:20:05 fabiankeil + * New config option: enforce-blocks. + * + * Revision 1.125 2007/03/09 14:12:00 fabiankeil + * - Move null byte check into separate function. + * - Don't confuse the client with error pages + * if a CONNECT request was already confirmed. + * + * Revision 1.124 2007/02/23 14:59:54 fabiankeil + * Speed up NULL byte escaping and only log the complete + * NULL byte requests with header debugging enabled. + * + * Revision 1.123 2007/02/21 18:42:10 fabiankeil + * Answer requests that contain NULL bytes with + * a custom response instead of waiting for more + * data until the client eventually hangs up. + * + * Revision 1.122 2007/02/07 11:12:02 fabiankeil + * - Move delivery and logging of crunched responses + * from chat() into send_crunch_response(). + * - Display the reason for generating http_responses. + * - Log the content length for LOG_LEVEL_CLF correctly + * (still incorrect for some fixed responses). + * - Reword an incorrect comment about + * treat-forbidden-connects-like-blocks violating + * the specs. + * - Add some log messages. + * * Revision 1.121 2007/01/27 10:52:56 fabiankeil * Move mutex initialization into separate * function and exit in case of errors. @@ -957,6 +988,13 @@ const char NO_SERVER_DATA_RESPONSE[] = "Empty server or forwarder response.\r\n" "The connection was closed without sending any data.\r\n"; +/* XXX: should be a template */ +const char NULL_BYTE_RESPONSE[] = + "HTTP/1.0 400 Bad request received from browser\r\n" + "Proxy-Agent: Privoxy " VERSION "\r\n" + "Connection: close\r\n\r\n" + "Bad request. Null byte(s) before end of request.\r\n"; + #if !defined(_WIN32) && !defined(__OS2__) && !defined(AMIGA) /********************************************************************* * @@ -1373,6 +1411,65 @@ void send_crunch_response(struct client_state *csp, struct http_response *rsp) } +/********************************************************************* + * + * Function : request_contains_null_bytes + * + * Description : Checks for NULL bytes in the request and sends + * an error message to the client if any were found. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * 2 : buf = Data from the client's request to check. + * 3 : len = The data length. + * + * Returns : TRUE if the request contained one or more NULL bytes, or + * FALSE otherwise. + * + *********************************************************************/ +int request_contains_null_bytes(const struct client_state *csp, char *buf, int len) +{ + size_t c_len; /* Request lenght when treated as C string */ + + c_len = strlen(buf); + + if (c_len < len) + { + /* + * Null byte(s) found. Log the request, + * return an error response and hang up. + */ + size_t tmp_len = c_len; + + do + { + /* + * Replace NULL byte(s) with '°' characters + * so the request can be logged as string. + * XXX: Is there a better replacement character? + */ + buf[tmp_len]='°'; + tmp_len += strlen(buf+tmp_len); + } while (tmp_len < len); + + log_error(LOG_LEVEL_ERROR, "%s\'s request contains at least one NULL byte " + "(length=%d, strlen=%d).", csp->ip_addr_str, len, c_len); + log_error(LOG_LEVEL_HEADER, + "Offending request data with NULL bytes turned into \'°\' characters: %s", buf); + + strcpy(buf, NULL_BYTE_RESPONSE); + write_socket(csp->cfd, buf, strlen(buf)); + + /* XXX: Log correct size */ + log_error(LOG_LEVEL_CLF, "%s - - [%T] \"Invalid request\" 400 0", csp->ip_addr_str); + + return TRUE; + } + + return FALSE; +} + + /********************************************************************* * * Function : chat @@ -1454,6 +1551,8 @@ static void chat(struct client_state *csp) http = csp->http; + memset(buf, 0, sizeof(buf)); + /* * Read the client's request. Note that since we're not using select() we * could get blocked here if a client connected, then didn't say anything! @@ -1461,10 +1560,16 @@ static void chat(struct client_state *csp) for (;;) { - len = read_socket(csp->cfd, buf, sizeof(buf)); + len = read_socket(csp->cfd, buf, sizeof(buf)-1); if (len <= 0) break; /* error! */ - + + if (request_contains_null_bytes(csp, buf, len)) + { + /* NULL bytes found and dealt with, just hang up. */ + return; + } + /* * If there is no memory left for buffering the * request, there is nothing we can do but hang up @@ -1498,15 +1603,23 @@ static void chat(struct client_state *csp) } #ifdef FEATURE_FORCE_LOAD - /* If this request contains the FORCE_PREFIX, - * better get rid of it now and set the force flag --oes + /* + * 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)) { - strclean(req, FORCE_PREFIX); - log_error(LOG_LEVEL_FORCE, "Enforcing request \"%s\".\n", req); - csp->flags |= CSP_FLAG_FORCED; + 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; + } } #endif /* def FEATURE_FORCE_LOAD */ @@ -1530,7 +1643,7 @@ static void chat(struct client_state *csp) strcpy(buf, CHEADER); write_socket(csp->cfd, buf, strlen(buf)); /* XXX: Use correct size */ - log_error(LOG_LEVEL_CLF, "%s - - [%T] \" \" 400 0", csp->ip_addr_str); + log_error(LOG_LEVEL_CLF, "%s - - [%T] \"Invalid request\" 400 0", csp->ip_addr_str); log_error(LOG_LEVEL_ERROR, "Invalid header received from %s.", csp->ip_addr_str); free_http_request(http); @@ -1902,9 +2015,6 @@ static void chat(struct client_state *csp) * so just send the "connect succeeded" message to the * client, flush the rest, and get out of the way. */ - log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 200 0", - csp->ip_addr_str, http->ocmd); - if (write_socket(csp->cfd, CSUCCEED, sizeof(CSUCCEED)-1)) { freez(hdr); @@ -1985,6 +2095,18 @@ static void chat(struct client_state *csp) { log_error(LOG_LEVEL_ERROR, "read from: %s failed: %E", http->host); + if (http->ssl && (fwd->forward_host == NULL)) + { + /* + * Just hang up. We already confirmed the client's CONNECT + * request with status code 200 and unencrypted content is + * no longer welcome. + */ + log_error(LOG_LEVEL_ERROR, + "CONNECT already confirmed. Unable to tell the client about the problem."); + return; + } + rsp = error_response(csp, "connect-failed", errno); if(rsp) @@ -3084,7 +3206,7 @@ static void listen_loop(void) #ifdef FEATURE_ACL if (block_acl(NULL,csp)) { - log_error(LOG_LEVEL_CONNECT, "Connection dropped due to ACL"); + log_error(LOG_LEVEL_CONNECT, "Connection from %s dropped due to ACL", csp->ip_addr_str); close_socket(csp->cfd); freez(csp); continue;