X-Git-Url: http://www.privoxy.org/gitweb/?p=privoxy.git;a=blobdiff_plain;f=cgi.c;h=63eff5939acbc240b8dbf2c42ce9afbad84bc4d8;hp=556aa4368e05ffb35b6eb65055351f58010854c8;hb=0b8c6f3b24261180c8fe1560750d25dfa9c52206;hpb=3b9357f0f104bae9c6b8d317c31853bd3284fa55 diff --git a/cgi.c b/cgi.c index 556aa436..63eff593 100644 --- a/cgi.c +++ b/cgi.c @@ -1,4 +1,4 @@ -const char cgi_rcs[] = "$Id: cgi.c,v 1.151 2012/06/08 15:07:53 fabiankeil Exp $"; +const char cgi_rcs[] = "$Id: cgi.c,v 1.166 2017/01/23 13:02:45 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/cgi.c,v $ @@ -9,7 +9,7 @@ const char cgi_rcs[] = "$Id: cgi.c,v 1.151 2012/06/08 15:07:53 fabiankeil Exp $" * actual handler functions are declared elsewhere. * * Copyright : Written by and Copyright (C) 2001-2004, 2006-2008 - * the SourceForge Privoxy team. http://www.privoxy.org/ + * members of the Privoxy team. http://www.privoxy.org/ * * Based on the Internet Junkbuster originally written * by and Copyright (C) 1997 Anonymous Coders and @@ -100,6 +100,17 @@ static const struct cgi_dispatcher cgi_dispatchers[] = { cgi_show_version, "View the source code version numbers", TRUE }, +#ifdef FEATURE_CLIENT_TAGS + /* + * This is marked as harmless because despite the description + * used in the menu the actual toggling is done through another + * path ("/toggle-client-tag"). + */ + { "client-tags", + cgi_show_client_tags, + "View or toggle the tags that can be set based on the clients address", + TRUE }, +#endif { "show-request", cgi_show_request, "View the request headers", @@ -114,6 +125,12 @@ static const struct cgi_dispatcher cgi_dispatchers[] = { "Toggle Privoxy on or off", FALSE }, #endif /* def FEATURE_TOGGLE */ +#ifdef FEATURE_CLIENT_TAGS + { "toggle-client-tag", + cgi_toggle_client_tag, + NULL, + FALSE }, +#endif #ifdef FEATURE_CGI_EDIT_ACTIONS { "edit-actions", /* Edit the actions list */ cgi_edit_actions, @@ -346,6 +363,21 @@ struct http_response *dispatch_cgi(struct client_state *csp) return NULL; } + if (strcmpic(csp->http->gpc, "GET") + && strcmpic(csp->http->gpc, "HEAD")) + { + log_error(LOG_LEVEL_ERROR, + "CGI request with unsupported method received: %s", csp->http->gpc); + /* + * The CGI pages currently only support GET and HEAD requests. + * + * If the client used a different method, ditch any data following + * the current headers to reduce the likelihood of parse errors + * with the following request. + */ + csp->client_iob->eod = csp->client_iob->cur; + } + /* * This is a CGI call. */ @@ -480,9 +512,12 @@ static struct http_response *dispatch_known_cgi(struct client_state * csp, if (*query_args_start == '/') { *query_args_start++ = '\0'; - if ((param_list = new_map())) - { - map(param_list, "file", 1, url_decode(query_args_start), 0); + param_list = new_map(); + err = map(param_list, "file", 1, url_decode(query_args_start), 0); + if (JB_ERR_OK != err) { + free(param_list); + free(path_copy); + return cgi_error_memory(); } } else @@ -614,18 +649,9 @@ static struct map *parse_cgi_parameters(char *argstring) */ max_segments = 1; } - vector = malloc(max_segments * sizeof(char *)); + vector = malloc_or_die(max_segments * sizeof(char *)); - if (NULL == vector) - { - return NULL; - } - - if (NULL == (cgi_params = new_map())) - { - freez(vector); - return NULL; - } + cgi_params = new_map(); /* * IE 5 does, of course, violate RFC 2316 Sect 4.1 and sends @@ -637,7 +663,7 @@ static struct map *parse_cgi_parameters(char *argstring) *p = '\0'; } - pairs = ssplit(argstring, "&", vector, max_segments, 1, 1); + pairs = ssplit(argstring, "&", vector, max_segments); assert(pairs != -1); if (pairs == -1) { @@ -798,8 +824,7 @@ jb_err get_number_param(struct client_state *csp, unsigned *pvalue) { const char *param; - char ch; - unsigned value; + char *endptr; assert(csp); assert(parameters); @@ -814,36 +839,12 @@ jb_err get_number_param(struct client_state *csp, return JB_ERR_CGI_PARAMS; } - /* We don't use atoi because I want to check this carefully... */ - - value = 0; - while ((ch = *param++) != '\0') + *pvalue = (unsigned int)strtol(param, &endptr, 0); + if (*endptr != '\0') { - if ((ch < '0') || (ch > '9')) - { - return JB_ERR_CGI_PARAMS; - } - - ch = (char)(ch - '0'); - - /* Note: - * - * defines UINT_MAX - * - * (UINT_MAX - ch) / 10 is the largest number that - * can be safely multiplied by 10 then have ch added. - */ - if (value > ((UINT_MAX - (unsigned)ch) / 10U)) - { - return JB_ERR_CGI_PARAMS; - } - - value = value * 10 + (unsigned)ch; + return JB_ERR_CGI_PARAMS; } - /* Success */ - *pvalue = value; - return JB_ERR_OK; } @@ -968,6 +969,9 @@ struct http_response *error_response(struct client_state *csp, case SOCKS_5: socks_type = "socks5-"; break; + case SOCKS_5T: + socks_type = "socks5t-"; + break; default: log_error(LOG_LEVEL_FATAL, "Unknown socks type: %d.", fwd->type); } @@ -1186,11 +1190,7 @@ jb_err cgi_error_no_template(const struct client_state *csp, rsp->head_length = 0; rsp->is_static = 0; - rsp->body = malloc(body_size); - if (rsp->body == NULL) - { - return JB_ERR_MEMORY; - } + rsp->body = malloc_or_die(body_size); strlcpy(rsp->body, body_prefix, body_size); strlcat(rsp->body, template_name, body_size); strlcat(rsp->body, body_suffix, body_size); @@ -1266,11 +1266,7 @@ jb_err cgi_error_unknown(const struct client_state *csp, rsp->is_static = 0; rsp->crunch_reason = INTERNAL_ERROR; - rsp->body = malloc(body_size); - if (rsp->body == NULL) - { - return JB_ERR_MEMORY; - } + rsp->body = malloc_or_die(body_size); snprintf(rsp->body, body_size, "%s%d%s", body_prefix, error_to_report, body_suffix); @@ -1391,7 +1387,7 @@ char *add_help_link(const char *item, } else { - string_append(&result, "http://"); + string_append(&result, "https://"); string_append(&result, CGI_SITE_2_HOST); string_append(&result, "/user-manual/"); } @@ -1528,12 +1524,7 @@ char *compress_buffer(char *buffer, size_t *buffer_length, int compression_level /* Let zlib figure out the maximum length of the compressed data */ new_length = compressBound((uLongf)*buffer_length); - compressed_buffer = malloc(new_length); - if (NULL == compressed_buffer) - { - log_error(LOG_LEVEL_FATAL, - "Out of memory allocation compression buffer."); - } + compressed_buffer = malloc_or_die(new_length); if (Z_OK != compress2((Bytef *)compressed_buffer, &new_length, (Bytef *)buffer, *buffer_length, compression_level)) @@ -1573,7 +1564,7 @@ char *compress_buffer(char *buffer, size_t *buffer_length, int compression_level * On error, free()s rsp and returns cgi_error_memory() * *********************************************************************/ -struct http_response *finish_http_response(const struct client_state *csp, struct http_response *rsp) +struct http_response *finish_http_response(struct client_state *csp, struct http_response *rsp) { char buf[BUFFER_SIZE]; jb_err err; @@ -1623,6 +1614,11 @@ struct http_response *finish_http_response(const struct client_state *csp, struc if (!err) { snprintf(buf, sizeof(buf), "Content-Length: %d", (int)rsp->content_length); + /* + * Signal serve() that the client will be able to figure out + * the end of the response without having to close the connection. + */ + csp->flags |= CSP_FLAG_SERVER_CONTENT_LENGTH_SET; err = enlist(rsp->headers, buf); } @@ -1732,7 +1728,8 @@ struct http_response *finish_http_response(const struct client_state *csp, struc if (!err) err = enlist_unique_header(rsp->headers, "Pragma", "no-cache"); } - if (!err && !(csp->flags & CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE)) + if (!err && (!(csp->flags & CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE) + || (csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED))) { err = enlist_unique_header(rsp->headers, "Connection", "close"); } @@ -2156,10 +2153,6 @@ struct map *default_exports(const struct client_state *csp, const char *caller) assert(csp); exports = new_map(); - if (exports == NULL) - { - return NULL; - } if (csp->config->hostname) {