Beispiel #1
0
/*
 * Get the file appropriate for a given error.
 */
static char *get_html_file (unsigned int errornum)
{
        hashmap_iter result_iter;
        char errornbuf[ERRORNUM_BUFSIZE];
        char *key;
        static char *val;

        assert (errornum >= 100 && errornum < 1000);

        if (!config.errorpages)
                return (config.errorpage_undef);

        snprintf (errornbuf, ERRORNUM_BUFSIZE, "%u", errornum);

        result_iter = hashmap_find (config.errorpages, errornbuf);

        if (hashmap_is_end (config.errorpages, result_iter))
                return (config.errorpage_undef);

        if (hashmap_return_entry (config.errorpages, result_iter,
                                  &key, (void **) &val) < 0)
                return (config.errorpage_undef);

        return (val);
}
Beispiel #2
0
/*
 * Look up the value for a variable.
 */
static char *lookup_variable (struct conn_s *connptr, const char *varname)
{
        hashmap_iter result_iter;
        char *key;
        static char *data;

        result_iter = hashmap_find (connptr->error_variables, varname);

        if (hashmap_is_end (connptr->error_variables, result_iter))
                return (NULL);

        if (hashmap_return_entry (connptr->error_variables, result_iter,
                                  &key, (void **) &data) < 0)
                return (NULL);

        return (data);
}
Beispiel #3
0
/*
 * Loop through all the headers (including the response code) from the
 * server.
 */
static int
process_server_headers(struct conn_s *connptr)
{
	static char *skipheaders[] = {
		"keep-alive",
		"proxy-authenticate",
		"proxy-authorization",
		"proxy-connection",
		"transfer-encoding",
	};

	char *response_line;

	hashmap_t hashofheaders;
	hashmap_iter iter;
	char *data, *header;
	ssize_t len;
	int i;
	int ret;

	/* FIXME: Remember to handle a "simple_req" type */

	/* Get the response line from the remote server. */
      retry:
	len = readline(connptr->server_fd, &response_line);
	if (len <= 0)
		return -1;

	/*
	 * Strip the new line and character return from the string.
	 */
	if (chomp(response_line, len) == len) {
		/*
		 * If the number of characters removed is the same as the
		 * length then it was a blank line. Free the buffer and
		 * try again (since we're looking for a request line.)
		 */
		safefree(response_line);
		goto retry;
	}

	hashofheaders = hashmap_create(HEADER_BUCKETS);
	if (!hashofheaders) {
		safefree(response_line);
		return -1;
	}

	/*
	 * Get all the headers from the remote server in a big hash
	 */
	if (get_all_headers(connptr->server_fd, hashofheaders) < 0) {
		log_message(LOG_WARNING, "Could not retrieve all the headers from the remote server.");
		hashmap_delete(hashofheaders);
		safefree(response_line);

		indicate_http_error(connptr, 503, "Could not retrieve all the headers",
				    "detail", PACKAGE " was unable to retrieve and process headers from the remote web server.",
				    NULL);
		return -1;
	}

	/* Send the saved response line first */
	ret = write_message(connptr->client_fd, "%s\r\n", response_line);
	safefree(response_line);
	if (ret < 0)
		goto ERROR_EXIT;

	/*
	 * If there is a "Content-Length" header, retrieve the information
	 * from it for later use.
	 */
	connptr->content_length.server = get_content_length(hashofheaders);

	/*
	 * See if there is a connection header.  If so, we need to to 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++) {
		hashmap_remove(hashofheaders, skipheaders[i]);
	}

	/* Send, or add the Via header */
	ret = write_via_header(connptr->client_fd, hashofheaders,
			       connptr->protocol.major,
			       connptr->protocol.minor);
	if (ret < 0)
		goto ERROR_EXIT;

	/*
	 * All right, output all the remaining headers to the client.
	 */
	iter = hashmap_first(hashofheaders);
	if (iter >= 0) {
		for ( ; !hashmap_is_end(hashofheaders, iter); ++iter) {
			hashmap_return_entry(hashofheaders,
					     iter,
					     &data,
					     (void **)&header);

			ret = write_message(connptr->client_fd,
						  "%s: %s\r\n",
						  data, header);
			if (ret < 0)
				goto ERROR_EXIT;
		}
	}
	hashmap_delete(hashofheaders);

	/* Write the final blank line to signify the end of the headers */
	if (safe_write(connptr->client_fd, "\r\n", 2) < 0)
		return -1;

	return 0;

  ERROR_EXIT:
	hashmap_delete(hashofheaders);
	return -1;
}
Beispiel #4
0
/*
 * Here we loop through all the headers the client is sending. If we
 * are running in anonymous mode, we will _only_ send the headers listed
 * (plus a few which are required for various methods).
 *	- rjkaes
 */
static int
process_client_headers(struct conn_s *connptr, hashmap_t hashofheaders)
{
	static char *skipheaders[] = {
		"host",
		"keep-alive",
		"proxy-authenticate",
		"proxy-authorization",
		"proxy-connection",
		"te",
		"trailers",
		"transfer-encoding",
		"upgrade"
	};
	int i;
	hashmap_iter iter;
	int ret = 0;

	char *data, *header;

	/*
	 * Don't send headers if there's already an error, if the request was
	 * a stats request, or if this was a CONNECT method (unless upstream
	 * proxy is in use.)
	 */
	if (connptr->server_fd == -1 || connptr->show_stats
	    || (connptr->connect_method && (connptr->upstream_proxy == NULL))) {
		log_message(LOG_INFO, "Not sending client headers to remote machine");
		return 0;
	}

	/*
	 * 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++) {
		hashmap_remove(hashofheaders, skipheaders[i]);
	}

	/* Send, or add the Via header */
	ret = write_via_header(connptr->server_fd, hashofheaders,
			       connptr->protocol.major,
			       connptr->protocol.minor);
	if (ret < 0) {
		indicate_http_error(connptr, 503,
				    "Could not send data to remote server",
				    "detail", "A network error occurred while trying to write data to the remote web server.",
				    NULL);
		goto PULL_CLIENT_DATA;
	}

	/*
	 * Output all the remaining headers to the remote machine.
	 */
	iter = hashmap_first(hashofheaders);
	if (iter >= 0) {
		for ( ; !hashmap_is_end(hashofheaders, iter); ++iter) {
			hashmap_return_entry(hashofheaders,
					     iter,
					     &data,
					     (void**)&header);

			if (!is_anonymous_enabled() || anonymous_search(data) > 0) {
				ret = write_message(connptr->server_fd,
						    "%s: %s\r\n",
						    data, header);
				if (ret < 0) {
					indicate_http_error(connptr, 503,
							    "Could not send data to remote server",
							    "detail", "A network error occurred while trying to write data to the remote web server.",
							    NULL);
					goto PULL_CLIENT_DATA;
				}
			}
		}
	}

#if defined(XTINYPROXY_ENABLE)
	if (config.my_domain)
		add_xtinyproxy_header(connptr);
#endif
	
	/* 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)
		return pull_client_data(connptr,
					connptr->content_length.client);
	else
		return ret;
}