/* * The "hashofheaders" store the client's headers. */ hashofheaders = orderedmap_create (HEADER_BUCKETS); if (hashofheaders == NULL) { update_stats (STAT_BADCONN); indicate_http_error (connptr, 503, "Internal error", "detail", "An internal server error occurred while processing " "your request. Please contact the administrator.", NULL); HC_FAIL(); }
/* * Get all the headers from the client in a big hash. */ if (get_all_headers (connptr->client_fd, hashofheaders) < 0) { log_message (LOG_WARNING, "Could not retrieve all the headers from the client"); indicate_http_error (connptr, 400, "Bad Request", "detail", "Could not retrieve all the headers from " "the client.", NULL); update_stats (STAT_BADCONN); HC_FAIL(); } got_headers = 1;
staticint process_client_headers(struct conn_s *connptr, orderedmap hashofheaders) { staticconstchar *skipheaders[] = { "host", "keep-alive", "proxy-connection", "te", "trailers", "upgrade" }; int i; size_t iter; int ret = 0;
char *data, *header;
// 其它省略代码
/* * See if there is a "Content-Length" header. If so, again we need * to do a bit of processing. */ connptr->content_length.client = get_content_length (hashofheaders);
// 其它省略代码
/* * See if there is a "Connection" header. If so, we need to do a bit * of processing. :) */ remove_connection_headers (hashofheaders);
/* * Delete the headers listed in the skipheaders list */ for (i = 0; i != (sizeof (skipheaders) / sizeof (char *)); i++) { orderedmap_remove (hashofheaders, skipheaders[i]); }
/* Send, or add the Via header */ ret = write_via_header (connptr->server_fd, hashofheaders, connptr->protocol.major, connptr->protocol.minor); // 其它省略代码
/* Write the final "blank" line to signify the end of the headers */ if (safe_write (connptr->server_fd, "\r\n", 2) < 0) return-1;
/* * Spin here pulling the data from the client. */ PULL_CLIENT_DATA: if (connptr->content_length.client > 0) { ret = pull_client_data (connptr, connptr->content_length.client, 1); } elseif (connptr->content_length.client == -2) ret = pull_client_data_chunked (connptr);
for (i = 0; i != (sizeof (headers) / sizeof (char *)); ++i) { /* Look for the connection header. If it's not found, return. */ data = orderedmap_find(hashofheaders, headers[i]);
if (!data) return0;
len = strlen(data);
/* * Go through the data line and replace any special characters * with a NULL. */ ptr = data; while ((ptr = strpbrk (ptr, "()<>@,;:\\\"/[]?={} \t"))) *ptr++ = '\0';
/* * All the tokens are separated by NULLs. Now go through the * token and remove them from the hashofheaders. */ ptr = data; while (ptr < data + len) { df = 0; /* check that ptr isn't one of headers to prevent double-free (CVE-2023-49606) */ for (j = 0; j != (sizeof (headers) / sizeof (char *)); ++j) if(!strcasecmp(ptr, headers[j])) df = 1; if (!df) orderedmap_remove (hashofheaders, ptr);
/* Advance ptr to the next token */ ptr += strlen (ptr) + 1; while (ptr < data + len && *ptr == '\0') ptr++; }
/* Now remove the connection header it self. */ orderedmap_remove (hashofheaders, headers[i]); }
do { len = safe_read (connptr->client_fd, buffer, max (MAXBUFFSIZE, (unsignedlongint) length)); if (len <= 0) goto ERROR_EXIT;
if (!connptr->error_variables) { if (safe_write (connptr->server_fd, buffer, len) < 0) goto ERROR_EXIT; }
length -= len; } while (length > 0);
if (iehack) { /* * BUG FIX: Internet Explorer will leave two bytes (carriage * return and line feed) at the end of a POST message. These * need to be eaten for tinyproxy to work correctly. */ ret = socket_nonblocking (connptr->client_fd); if (ret != 0) { log_message(LOG_ERR, "Failed to set the client socket " "to non-blocking: %s", strerror(errno)); goto ERROR_EXIT; } len = recv (connptr->client_fd, buffer, 2, MSG_PEEK); ret = socket_blocking (connptr->client_fd); if (ret != 0) { log_message(LOG_ERR, "Failed to set the client socket " "to blocking: %s", strerror(errno)); goto ERROR_EXIT; } if (len < 0 && errno != EAGAIN) goto ERROR_EXIT; if ((len == 2) && CHECK_CRLF (buffer, len)) { ssize_t bytes_read; bytes_read = read (connptr->client_fd, buffer, 2); if (bytes_read == -1) { log_message (LOG_WARNING, "Could not read two bytes from POST message"); } } }