From 67632125b235891a578acd268f540cd1ac07e98e Mon Sep 17 00:00:00 2001 From: Fabian Keil Date: Fri, 25 Jul 2014 11:55:11 +0000 Subject: [PATCH] Reject requests with unsupported Expect header values This changes the test status for the following Co-Advisor tests from "Violation" to "Success": rfc2616/unsuppExpect-0100-continue rfc2616/unsuppExpect-100-continueing rfc2616/unsuppExpect-expect=params rfc2616/unsuppExpect-expect=quoted-100c For RFC 2616 rejecting such requests was a MUST, but RFC 7230 downgraded this to a MAY. --- jcc.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++- parsers.c | 38 +++++++++++++++++++++++++++++++++++++- project.h | 6 +++++- 3 files changed, 89 insertions(+), 3 deletions(-) diff --git a/jcc.c b/jcc.c index d9960f7c..ef8c77f1 100644 --- a/jcc.c +++ b/jcc.c @@ -1,4 +1,4 @@ -const char jcc_rcs[] = "$Id: jcc.c,v 1.427 2014/06/02 06:22:21 fabiankeil Exp $"; +const char jcc_rcs[] = "$Id: jcc.c,v 1.428 2014/06/03 10:25:57 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/jcc.c,v $ @@ -279,6 +279,13 @@ static const char CLIENT_BODY_PARSE_ERROR_RESPONSE[] = "Connection: close\r\n\r\n" "Failed parsing or buffering the chunk-encoded client body.\r\n"; +static const char UNSUPPORTED_CLIENT_EXPECTATION_ERROR_RESPONSE[] = + "HTTP/1.1 417 Expecting too much\r\n" + "Proxy-Agent: Privoxy " VERSION "\r\n" + "Content-Type: text/plain\r\n" + "Connection: close\r\n\r\n" + "Privoxy detected an unsupported Expect header value.\r\n"; + /* A function to crunch a response */ typedef struct http_response *(*crunch_func_ptr)(struct client_state *); @@ -437,6 +444,40 @@ static int client_protocol_is_unsupported(const struct client_state *csp, char * } +/********************************************************************* + * + * Function : client_has_unsupported_expectations + * + * Description : Checks if the client used an unsupported expectation + * in which case an error message is delivered. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : TRUE if an error response has been generated, or + * FALSE if the request doesn't look invalid. + * + *********************************************************************/ +static int client_has_unsupported_expectations(const struct client_state *csp) +{ + if ((csp->flags & CSP_FLAG_UNSUPPORTED_CLIENT_EXPECTATION)) + { + log_error(LOG_LEVEL_ERROR, + "Rejecting request from client %s with unsupported Expect header value", + csp->ip_addr_str); + log_error(LOG_LEVEL_CLF, + "%s - - [%T] \"%s\" 417 0", csp->ip_addr_str, csp->http->cmd); + write_socket(csp->cfd, UNSUPPORTED_CLIENT_EXPECTATION_ERROR_RESPONSE, + strlen(UNSUPPORTED_CLIENT_EXPECTATION_ERROR_RESPONSE)); + + return TRUE; + } + + return FALSE; + +} + + /********************************************************************* * * Function : get_request_destination_elsewhere @@ -1693,6 +1734,11 @@ static jb_err parse_client_request(struct client_state *csp) return JB_ERR_PARSE; } + if (client_has_unsupported_expectations(csp)) + { + return JB_ERR_PARSE; + } + return JB_ERR_OK; } diff --git a/parsers.c b/parsers.c index 3d02d95b..6dae382f 100644 --- a/parsers.c +++ b/parsers.c @@ -1,4 +1,4 @@ -const char parsers_rcs[] = "$Id: parsers.c,v 1.285 2014/04/21 12:04:01 fabiankeil Exp $"; +const char parsers_rcs[] = "$Id: parsers.c,v 1.286 2014/06/12 13:10:21 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/parsers.c,v $ @@ -116,6 +116,7 @@ static jb_err client_if_none_match (struct client_state *csp, char **header static jb_err crunch_client_header (struct client_state *csp, char **header); static jb_err client_x_filter (struct client_state *csp, char **header); static jb_err client_range (struct client_state *csp, char **header); +static jb_err client_expect (struct client_state *csp, char **header); static jb_err server_set_cookie (struct client_state *csp, char **header); static jb_err server_connection (struct client_state *csp, char **header); static jb_err server_content_type (struct client_state *csp, char **header); @@ -203,6 +204,7 @@ static const struct parsers client_patterns[] = { #if 0 { "Transfer-Encoding:", 18, client_transfer_encoding }, #endif + { "Expect:", 7, client_expect }, { "*", 0, crunch_client_header }, { "*", 0, filter_header }, { NULL, 0, NULL } @@ -2006,6 +2008,40 @@ jb_err client_transfer_encoding(struct client_state *csp, char **header) } +/********************************************************************* + * + * Function : client_expect + * + * Description : Raise the CSP_FLAG_UNSUPPORTED_CLIENT_EXPECTATION + * if the Expect header value is unsupported. + * + * Rejecting unsupported expectations is a RFC 7231 5.1.1 + * MAY and a RFC 2616 (obsolete) MUST. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * 2 : header = On input, pointer to header to modify. + * On output, pointer to the modified header, or NULL + * to remove the header. This function frees the + * original string if necessary. + * + * Returns : JB_ERR_OK on success, or + * + *********************************************************************/ +jb_err client_expect(struct client_state *csp, char **header) +{ + if (0 != strcmpic(*header, "Expect: 100-continue")) + { + csp->flags |= CSP_FLAG_UNSUPPORTED_CLIENT_EXPECTATION; + log_error(LOG_LEVEL_HEADER, + "Unsupported client expectaction: %s", *header); + } + + return JB_ERR_OK; + +} + + /********************************************************************* * * Function : crumble diff --git a/project.h b/project.h index 2abf0fcf..2b0c6069 100644 --- a/project.h +++ b/project.h @@ -1,7 +1,7 @@ #ifndef PROJECT_H_INCLUDED #define PROJECT_H_INCLUDED /** Version string. */ -#define PROJECT_H_VERSION "$Id: project.h,v 1.205 2014/06/02 06:19:06 fabiankeil Exp $" +#define PROJECT_H_VERSION "$Id: project.h,v 1.206 2014/06/02 06:22:21 fabiankeil Exp $" /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/project.h,v $ @@ -848,6 +848,10 @@ struct reusable_connection */ #define CSP_FLAG_CHUNKED_CLIENT_BODY 0x01000000U +/** + * Flag for csp->flags: Set if the client set the Expect header + */ +#define CSP_FLAG_UNSUPPORTED_CLIENT_EXPECTATION 0x02000000U /* * Flags for use in return codes of child processes -- 2.39.2