From e91e48dd60f91fe3b65d869de5cb0793d2a98106 Mon Sep 17 00:00:00 2001 From: rofl0r Date: Wed, 21 Jul 2021 14:29:20 +0100 Subject: [PATCH 01/71] add an issue template (#387) as it's unproductive to be getting the same bug report for old tinyproxy versions over and over, and people not even stating which version they're using, this new issue template makes people aware of what information to include when filing an issue request. --- .../new-issue--bug-report--question.md | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/new-issue--bug-report--question.md diff --git a/.github/ISSUE_TEMPLATE/new-issue--bug-report--question.md b/.github/ISSUE_TEMPLATE/new-issue--bug-report--question.md new file mode 100644 index 00000000..32d49956 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/new-issue--bug-report--question.md @@ -0,0 +1,20 @@ +--- +name: New Issue, Bug report, Question +about: New Issue, Bug report, Question +title: '' +labels: '' +assignees: '' + +--- + +# IMPORTANT NOTICE + +Before filing an issue here PLEASE keep in mind that **tinyproxy 1.10.0 and older are no longer supported**. +Do not report issues with 1.10.0 or older, first try latest release 1.11.0, or even better, git master, and see whether the issue is already fixed. + +## Tinyproxy version +State the tinyproxy version you're using; whether git master or 1.11.0 stable. + +## Issue +Fill in your Issue text here. +A good issue report is detailed and includes full error messages from tinyproxy's output, not "X doesn't work". From 39d7bf6c70f661bc6bc69794d288361eea07178c Mon Sep 17 00:00:00 2001 From: rofl0r Date: Fri, 23 Jul 2021 20:17:18 +0100 Subject: [PATCH 02/71] improve error message for "Error reading readable client_fd" maybe this helps to track down the cause of #383. --- src/reqs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/reqs.c b/src/reqs.c index 03d25990..dcbdd830 100644 --- a/src/reqs.c +++ b/src/reqs.c @@ -1464,8 +1464,8 @@ get_request_entity(struct conn_s *connptr) nread = read_buffer (connptr->client_fd, connptr->cbuffer); if (nread < 0) { log_message (LOG_ERR, - "Error reading readable client_fd %d", - connptr->client_fd); + "Error reading readable client_fd %d (%s)", + connptr->client_fd, strerror(errno)); ret = -1; } else { log_message (LOG_INFO, From c1023f68217b708b3c1c5f1849f7a4a680e1e012 Mon Sep 17 00:00:00 2001 From: rofl0r Date: Mon, 23 Aug 2021 13:46:42 +0000 Subject: [PATCH 03/71] fix regression failing to parse dotted netmask in upstream introduced in 979c737f9b811c5441ae0573a90b72dc1e44e142. when refactoring the "site-spec" parsing code i failed to realize that the code dealing with acl allow/deny directives didn't provide the option to specify netmasks in dotted ipv4 notation, unlike the code in the upstream parser. since both scenarios now use the same parsing, both dotted notation and CIDR slash-notation are possible. while at it, removed the len parameter from fill_netmask_array() which provided the illusion the array length could be of variable size. fixes #394 --- src/hostspec.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/hostspec.c b/src/hostspec.c index adbad538..1f956f2b 100644 --- a/src/hostspec.c +++ b/src/hostspec.c @@ -3,6 +3,15 @@ #include "heap.h" #include "network.h" +static int dotted_mask(char *bitmask_string, unsigned char array[]) +{ + unsigned char v4bits[4]; + if (1 != inet_pton (AF_INET, bitmask_string, v4bits)) return -1; + memset (array, 0xff, IPV6_LEN-4); + memcpy (array + IPV6_LEN-4, v4bits, 4); + return 0; +} + /* * Fills in the netmask array given a numeric value. * @@ -13,13 +22,17 @@ */ static int fill_netmask_array (char *bitmask_string, int v6, - unsigned char array[], size_t len) + unsigned char array[]) { unsigned int i; unsigned long int mask; char *endptr; errno = 0; /* to distinguish success/failure after call */ + if (strchr (bitmask_string, '.')) { + if (v6) return -1; /* ipv6 doesn't supported dotted netmasks */ + return dotted_mask(bitmask_string, array); + } mask = strtoul (bitmask_string, &endptr, 10); /* check for various conversion errors */ @@ -35,11 +48,11 @@ fill_netmask_array (char *bitmask_string, int v6, } /* check valid range for a bit mask */ - if (mask > (8 * len)) + if (mask > (8 * IPV6_LEN)) return -1; /* we have a valid range to fill in the array */ - for (i = 0; i != len; ++i) { + for (i = 0; i != IPV6_LEN; ++i) { if (mask >= 8) { array[i] = 0xff; mask -= 8; @@ -88,7 +101,7 @@ int hostspec_parse(char *location, struct hostspec *h) { v6 = 0; if (fill_netmask_array - (mask, v6, &(h->address.ip.mask[0]), IPV6_LEN) + (mask, v6, &(h->address.ip.mask[0])) < 0) goto err; From 207f7903140f280a6e32ebb1d92c01194ef606cb Mon Sep 17 00:00:00 2001 From: "Aaron M. Ucko" Date: Tue, 21 Sep 2021 21:46:40 -0400 Subject: [PATCH 04/71] Fix FTBFS on hurd-i386: run_tests.sh duplicates build path. --- tests/scripts/run_tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/scripts/run_tests.sh b/tests/scripts/run_tests.sh index eb1d3c42..d64ea6ae 100755 --- a/tests/scripts/run_tests.sh +++ b/tests/scripts/run_tests.sh @@ -18,7 +18,7 @@ # this program; if not, see . -SCRIPTS_DIR=$(pwd)/$(dirname $0) +SCRIPTS_DIR=$(cd $(dirname $0) && pwd) BASEDIR=$SCRIPTS_DIR/../.. TESTS_DIR=$SCRIPTS_DIR/.. TESTENV_DIR=$TESTS_DIR/env From f0c291e1daa78ac6dbc9c27bff75f09d46153b51 Mon Sep 17 00:00:00 2001 From: rofl0r Date: Wed, 22 Sep 2021 12:07:33 +0000 Subject: [PATCH 05/71] README.md: freenode is dead, long live libera since freenode.net doesn't even serve a website anymore, it's safe to finally announce the switch. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bba85dcd..83eb99be 100644 --- a/README.md +++ b/README.md @@ -89,4 +89,4 @@ and create a [pull request](https://github.com/tinyproxy/tinyproxy/pulls). You can meet developers and users to discuss development, patches and deployment issues in the `#tinyproxy` IRC channel on -Freenode (`irc.freenode.net`). +libera (`irc.libera.chat`). From d3d8943fe45e53a39864070b74fdfa95dd93f1f0 Mon Sep 17 00:00:00 2001 From: rofl0r Date: Wed, 22 Sep 2021 12:14:58 +0000 Subject: [PATCH 06/71] update website footer re: freenode --- docs/web/tp.html.foot | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/web/tp.html.foot b/docs/web/tp.html.foot index d080bac1..90654f9c 100644 --- a/docs/web/tp.html.foot +++ b/docs/web/tp.html.foot @@ -3,7 +3,7 @@
  • Feel free to report a new bug or suggest features via github issues.
  • -
  • Tinyproxy developers hang out in #tinyproxy on irc.freenode.net.
  • +
  • Tinyproxy developers hang out in #tinyproxy on irc.libera.chat.
From 79d0b0fa79249a714cbb1992d597e21adc30b16e Mon Sep 17 00:00:00 2001 From: rofl0r Date: Thu, 20 Jan 2022 20:25:42 +0000 Subject: [PATCH 07/71] fix timeout not being applied to outgoing connections the fix in 0b9a74c29036f9215b2b97a301b7b25933054302 was incomplete, as it applied the socket timeout only to the socket received from accept(), but not to sockets created for outgoing connections. --- src/reqs.c | 11 ++++------- src/sock.c | 12 ++++++++++++ src/sock.h | 2 ++ 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/reqs.c b/src/reqs.c index dcbdd830..2be8e241 100644 --- a/src/reqs.c +++ b/src/reqs.c @@ -1517,6 +1517,9 @@ static void handle_connection_failure(struct conn_s *connptr, int got_headers) * when we start the relay portion. This makes most of the original * tinyproxy code, which was confusing, redundant. Hail progress. * - rjkaes + + * this function is called directly from child_thread() with the newly + * received fd from accept(). */ void handle_connection (struct conn_s *connptr, union sockaddr_union* addr) { @@ -1528,7 +1531,6 @@ void handle_connection (struct conn_s *connptr, union sockaddr_union* addr) int got_headers = 0, fd = connptr->client_fd; size_t i; struct request_s *request = NULL; - struct timeval tv; orderedmap hashofheaders = NULL; char sock_ipaddr[IP_LENGTH]; @@ -1550,12 +1552,7 @@ void handle_connection (struct conn_s *connptr, union sockaddr_union* addr) return; } - tv.tv_usec = 0; - tv.tv_sec = config->idletimeout; - setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (void*) &tv, sizeof(tv)); - tv.tv_usec = 0; - tv.tv_sec = config->idletimeout; - setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (void*) &tv, sizeof(tv)); + set_socket_timeout(fd); if (connection_loops (addr)) { log_message (LOG_CONN, diff --git a/src/sock.c b/src/sock.c index 70169a68..427221c0 100644 --- a/src/sock.c +++ b/src/sock.c @@ -108,6 +108,16 @@ bind_socket_list (int sockfd, sblist *addresses, int family) return -1; } +void set_socket_timeout(int fd) { + struct timeval tv; + tv.tv_usec = 0; + tv.tv_sec = config->idletimeout; + setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (void*) &tv, sizeof(tv)); + tv.tv_usec = 0; + tv.tv_sec = config->idletimeout; + setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (void*) &tv, sizeof(tv)); +} + /* * Open a connection to a remote host. It's been re-written to use * the getaddrinfo() library function, which allows for a protocol @@ -163,6 +173,8 @@ int opensock (const char *host, int port, const char *bind_to) } } + set_socket_timeout(sockfd); + if (connect (sockfd, res->ai_addr, res->ai_addrlen) == 0) { union sockaddr_union *p = (void*) res->ai_addr, u; int af = res->ai_addr->sa_family; diff --git a/src/sock.h b/src/sock.h index aee5bf59..70c44739 100644 --- a/src/sock.h +++ b/src/sock.h @@ -56,6 +56,8 @@ extern int listen_sock (const char *addr, uint16_t port, sblist* listen_fds); extern int socket_nonblocking (int sock); extern int socket_blocking (int sock); +extern void set_socket_timeout(int fd); + extern int getsock_ip (int fd, char *ipaddr); extern void getpeer_information (union sockaddr_union *addr, char *ipaddr, size_t ipaddr_len); From 17d3733be36b0daabda1bdb19a3c4452a360d8f9 Mon Sep 17 00:00:00 2001 From: rofl0r Date: Wed, 26 Jan 2022 12:13:22 +0000 Subject: [PATCH 08/71] main: fix logging being disabled after reload conf fails fixes #417 --- src/main.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/main.c b/src/main.c index 13092844..e8c9c071 100644 --- a/src/main.c +++ b/src/main.c @@ -254,7 +254,7 @@ change_user (const char *program) */ int reload_config (int reload_logging) { - int ret; + int ret, ret2; struct config_s *c_next = get_next_config(); log_message (LOG_NOTICE, "Reloading config file"); @@ -263,18 +263,19 @@ int reload_config (int reload_logging) ret = reload_config_file (config_file, c_next); - if (ret != 0) { - goto done; + if (ret == 0) { + if(config) free_config (config); + config = c_next; } - if(config) free_config (config); - config = c_next; + if (reload_logging) ret2 = setup_logging (); - if (reload_logging) ret = setup_logging (); - log_message (LOG_NOTICE, "Reloading config file finished"); + if (ret != 0) + log_message (LOG_WARNING, "Reloading config file failed!"); + else + log_message (LOG_NOTICE, "Reloading config file finished"); -done: - return ret; + return ret ? ret : ret2; } static void setup_sig(int sig, signal_func *sigh, From eced6822f8b2947e2001da6092fc147c0f7b6687 Mon Sep 17 00:00:00 2001 From: rofl0r Date: Sun, 13 Feb 2022 21:11:37 +0000 Subject: [PATCH 09/71] properly deal with client sending chunked data this fixes OPTIONS requests sent from apache SVN client using their native HTTP proxy support. closes #421 tested with `svn info http://svnmir.bme.freebsd.org/ports/` --- src/reqs.c | 108 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 78 insertions(+), 30 deletions(-) diff --git a/src/reqs.c b/src/reqs.c index 2be8e241..cdc3b618 100644 --- a/src/reqs.c +++ b/src/reqs.c @@ -523,7 +523,7 @@ static struct request_s *process_request (struct conn_s *connptr, * server headers can be processed. * - rjkaes */ -static int pull_client_data (struct conn_s *connptr, long int length) +static int pull_client_data (struct conn_s *connptr, long int length, int iehack) { char *buffer; ssize_t len; @@ -548,39 +548,75 @@ static int pull_client_data (struct conn_s *connptr, long int length) length -= len; } while (length > 0); - /* - * 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; + 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"); + } + } } - len = recv (connptr->client_fd, buffer, 2, MSG_PEEK); + safefree (buffer); + return 0; - 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; - } +ERROR_EXIT: + safefree (buffer); + return -1; +} - if (len < 0 && errno != EAGAIN) - goto ERROR_EXIT; +/* pull chunked client data */ +static int pull_client_data_chunked (struct conn_s *connptr) { + char *buffer = 0; + ssize_t len; + long chunklen; + + while(1) { + if (buffer) safefree(buffer); + len = readline (connptr->client_fd, &buffer); - if ((len == 2) && CHECK_CRLF (buffer, len)) { - ssize_t bytes_read; + if (len <= 0) + goto ERROR_EXIT; - bytes_read = read (connptr->client_fd, buffer, 2); - if (bytes_read == -1) { - log_message - (LOG_WARNING, - "Could not read two bytes from POST message"); + if (!connptr->error_variables) { + if (safe_write (connptr->server_fd, buffer, len) < 0) + goto ERROR_EXIT; } + + chunklen = strtol (buffer, (char**)0, 16); + + if (pull_client_data (connptr, chunklen+2, 0) < 0) + goto ERROR_EXIT; + + if(!chunklen) break; } safefree (buffer); @@ -787,7 +823,7 @@ static int remove_connection_headers (orderedmap hashofheaders) /* * If there is a Content-Length header, then return the value; otherwise, return - * a negative number. + * -1. */ static long get_content_length (orderedmap hashofheaders) { @@ -802,6 +838,13 @@ static long get_content_length (orderedmap hashofheaders) return content_length; } +static int is_chunked_transfer (orderedmap hashofheaders) +{ + char *data; + data = orderedmap_find (hashofheaders, "transfer-encoding"); + return data ? !strcmp (data, "chunked") : 0; +} + /* * Search for Via header in a hash of headers and either write a new Via * header, or append our information to the end of an existing Via header. @@ -896,6 +939,10 @@ process_client_headers (struct conn_s *connptr, orderedmap hashofheaders) */ connptr->content_length.client = get_content_length (hashofheaders); + /* Check whether client sends chunked data. */ + if (connptr->content_length.client == -1 && is_chunked_transfer (hashofheaders)) + connptr->content_length.client = -2; + /* * See if there is a "Connection" header. If so, we need to do a bit * of processing. :) @@ -960,8 +1007,9 @@ process_client_headers (struct conn_s *connptr, orderedmap hashofheaders) PULL_CLIENT_DATA: if (connptr->content_length.client > 0) { ret = pull_client_data (connptr, - connptr->content_length.client); - } + connptr->content_length.client, 1); + } else if (connptr->content_length.client == -2) + ret = pull_client_data_chunked (connptr); return ret; } From 1576ee279f03dad56808acb6bb3e3b30b4706c31 Mon Sep 17 00:00:00 2001 From: "Malte S. Stretz" Date: Sat, 20 Nov 2021 17:39:21 +0100 Subject: [PATCH 10/71] Return 5xx when upstream is unreachable Currently a 404 is returned for a misconfigured or unavailable upstream server. Since that's a server error it should be a 5xx instead; a 404 is confusing when used as a forward proxy and might even be harmful when used as a reverse proxy. It is debatable if another 5xx code might be better; the misconfigured situation might better be a 500 whereas the connection issue could be a 503 instead (as used eg. in haproxy). --- etc/tinyproxy.conf.in | 2 +- src/reqs.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/etc/tinyproxy.conf.in b/etc/tinyproxy.conf.in index 06f5480a..ce27f7ec 100644 --- a/etc/tinyproxy.conf.in +++ b/etc/tinyproxy.conf.in @@ -56,8 +56,8 @@ Timeout 600 # /usr/share/tinyproxy # /etc/tinyproxy # -#ErrorFile 404 "@pkgdatadir@/404.html" #ErrorFile 400 "@pkgdatadir@/400.html" +#ErrorFile 502 "@pkgdatadir@/502.html" #ErrorFile 503 "@pkgdatadir@/503.html" #ErrorFile 403 "@pkgdatadir@/403.html" #ErrorFile 408 "@pkgdatadir@/408.html" diff --git a/src/reqs.c b/src/reqs.c index cdc3b618..50f69144 100644 --- a/src/reqs.c +++ b/src/reqs.c @@ -1424,7 +1424,7 @@ connect_to_upstream (struct conn_s *connptr, struct request_s *request) log_message (LOG_WARNING, "No upstream proxy defined for %s.", request->host); - indicate_http_error (connptr, 404, + indicate_http_error (connptr, 502, "Unable to connect to upstream proxy."); return -1; } @@ -1436,7 +1436,7 @@ connect_to_upstream (struct conn_s *connptr, struct request_s *request) if (connptr->server_fd < 0) { log_message (LOG_WARNING, "Could not connect to upstream proxy."); - indicate_http_error (connptr, 404, + indicate_http_error (connptr, 502, "Unable to connect to upstream proxy", "detail", "A network error occurred while trying to " From 479df8ecec5c5f52a61d9a1295dd51a1933226cc Mon Sep 17 00:00:00 2001 From: "Malte S. Stretz" Date: Sat, 20 Nov 2021 17:55:21 +0100 Subject: [PATCH 11/71] Add test case for unavailable upstream --- tests/scripts/run_tests.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/scripts/run_tests.sh b/tests/scripts/run_tests.sh index d64ea6ae..5a8ecd8f 100755 --- a/tests/scripts/run_tests.sh +++ b/tests/scripts/run_tests.sh @@ -83,6 +83,7 @@ DefaultErrorFile "$TINYPROXY_DATA_DIR/debug.html" ErrorFile 400 "$TINYPROXY_DATA_DIR/debug.html" ErrorFile 403 "$TINYPROXY_DATA_DIR/debug.html" ErrorFile 501 "$TINYPROXY_DATA_DIR/debug.html" +ErrorFile 502 "$TINYPROXY_DATA_DIR/debug.html" StatFile "$TINYPROXY_DATA_DIR/stats.html" Logfile "$TINYPROXY_LOG_FILE" PidFile "$TINYPROXY_PID_FILE" @@ -99,6 +100,7 @@ XTinyproxy Yes AddHeader "X-My-Header1" "Powered by Tinyproxy" AddHeader "X-My-Header2" "Powered by Tinyproxy" AddHeader "X-My-Header3" "Powered by Tinyproxy" +Upstream http 255.255.255.255:65535 ".invalid" EOF cat << 'EOF' > $TINYPROXY_FILTER_FILE @@ -244,6 +246,10 @@ test "x$?" = "x0" || FAILED=$((FAILED + 1)) echo -n "requesting connect method to denied port..." run_failure_webclient_request 403 --method=CONNECT "$TINYPROXY_IP:$TINYPROXY_PORT" "localhost:12345" test "x$?" = "x0" || FAILED=$((FAILED + 1)) + +echo -n "testing unavailable backend..." +run_failure_webclient_request 502 "$TINYPROXY_IP:$TINYPROXY_PORT" "http://bogus.invalid" +test "x$?" = "x0" || FAILED=$((FAILED + 1)) } basic_test From 9718be09c16ea4b4fb3cd5cb2b53c33055a4361f Mon Sep 17 00:00:00 2001 From: rofl0r Date: Wed, 16 Feb 2022 02:28:11 +0000 Subject: [PATCH 12/71] reload_logging: fix returning possibly uninitialized value introduced in 17d3733be36b0daabda1bdb19a3c4452a360d8f9 may fix #422 --- src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.c b/src/main.c index e8c9c071..7ea55408 100644 --- a/src/main.c +++ b/src/main.c @@ -268,7 +268,7 @@ int reload_config (int reload_logging) config = c_next; } - if (reload_logging) ret2 = setup_logging (); + ret2 = reload_logging ? setup_logging () : 0; if (ret != 0) log_message (LOG_WARNING, "Reloading config file failed!"); From c63028d6758a01326f43707f7e5fe29e302ddc5f Mon Sep 17 00:00:00 2001 From: rofl0r Date: Tue, 1 Mar 2022 15:17:32 +0000 Subject: [PATCH 13/71] bind_socket(): improve log output bind_socket most often fails due to having wrong address family, so it's helpful to see which one was used. --- src/sock.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/sock.c b/src/sock.c index 427221c0..b3b0920d 100644 --- a/src/sock.c +++ b/src/sock.c @@ -47,6 +47,16 @@ static const char * get_gai_error (int n) return gai_strerror (n); } +static const char * family_string (int af) +{ + switch(af) { + case AF_UNSPEC: return "AF_UNSPEC"; + case AF_INET: return "AF_INET"; + case AF_INET6: return "AF_INET6"; + } + return "unknown"; +} + /* * Bind the given socket to the supplied address. The socket is * returned if the bind succeeded. Otherwise, -1 is returned @@ -69,7 +79,7 @@ bind_socket (int sockfd, const char *addr, int family) n = getaddrinfo (addr, NULL, &hints, &res); if (n != 0) { log_message (LOG_INFO, - "bind_socket: getaddrinfo failed for %s: %s", addr, get_gai_error (n)); + "bind_socket: getaddrinfo failed for %s: %s (af: %s)", addr, get_gai_error (n), family_string(family)); return -1; } From 14d31ed63fceb733e219ed2a290f0c2b87749953 Mon Sep 17 00:00:00 2001 From: dr|z3d Date: Fri, 22 Apr 2022 05:27:47 +0000 Subject: [PATCH 14/71] Prettify stats.html --- data/templates/stats.html | 162 ++++++++++++++++++++++---------------- 1 file changed, 94 insertions(+), 68 deletions(-) diff --git a/data/templates/stats.html b/data/templates/stats.html index 71798592..a8c3e074 100644 --- a/data/templates/stats.html +++ b/data/templates/stats.html @@ -1,69 +1,95 @@ - - - - - - -{package} version {version} run-time statistics - - - - - - - - -

{package} version {version} run-time statistics

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameValue
Number of open connections{opens}
Number of requests{reqs}
Number of bad connections{badconns}
Number of denied connections{deniedconns}
Number of refused connections due to high load{refusedconns}
- -
- -

Generated by {package} version {version}.

- - - + + + + + Stats [{package} v{version}] + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{package} v{version} statistics
Open connections{opens}
Bad connections{badconns}
Denied connections{deniedconns}
Refused (high load){refusedconns}
Total requests{reqs}
+
+
+ From 26db3f6cc95c2eae533234b6140c23233284a404 Mon Sep 17 00:00:00 2001 From: Tristan Stenner Date: Fri, 29 Apr 2022 15:32:53 +0200 Subject: [PATCH 15/71] Allow "XTinyProxy No" with xtinyproxy disabled --- src/conf.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/conf.c b/src/conf.c index 4e6d19ea..7033661a 100644 --- a/src/conf.c +++ b/src/conf.c @@ -707,6 +707,8 @@ static HANDLE_FUNC (handle_xtinyproxy) #ifdef XTINYPROXY_ENABLE return set_bool_arg (&conf->add_xtinyproxy, line, &match[2]); #else + if(!get_bool_arg(line, &match[2])) + return 0; fprintf (stderr, "XTinyproxy NOT Enabled! Recompile with --enable-xtinyproxy\n"); return 1; From 235b1c10a76a02f4837febcf84efd9b7edcd020e Mon Sep 17 00:00:00 2001 From: rofl0r Date: Mon, 10 May 2021 00:28:54 +0100 Subject: [PATCH 16/71] implement filtertype keyword and fnmatch-based filtering as suggested in #212, it seems the majority of people don't understand that input was expected to be in regex format and people were using filter lists containing plain hostnames, e.g. `www.google.com`. apart from that, using fnmatch() for matching is actually a lot less computationally expensive and allows to use big blacklists without incurring a huge performance hit. the config file now understands a new option `FilterType` which can be one of `bre`, `ere` and `fnmatch`. The `FilterExtended` option was deprecated in favor of it. It still works, but will be removed in the release after the next. --- docs/man5/tinyproxy.conf.txt.in | 23 +++++++++++-- etc/tinyproxy.conf.in | 5 ++- src/conf-tokens.c | 1 + src/conf-tokens.gperf | 1 + src/conf-tokens.h | 1 + src/conf.c | 46 +++++++++++++++++++++---- src/conf.h | 4 +-- src/filter.c | 59 ++++++++++++++++++--------------- src/filter.h | 18 ++++++---- src/reqs.c | 18 ++++------ 10 files changed, 117 insertions(+), 59 deletions(-) diff --git a/docs/man5/tinyproxy.conf.txt.in b/docs/man5/tinyproxy.conf.txt.in index 758382cf..1e1ee3ef 100644 --- a/docs/man5/tinyproxy.conf.txt.in +++ b/docs/man5/tinyproxy.conf.txt.in @@ -267,7 +267,7 @@ domains. This option specifies the location of the file containing the filter rules, one rule per line. Rules are specified as POSIX basic regular expressions (BRE), unless -FilterExtended is activated. +another FilterType is specified. Comment lines start with a `#` character. Example filter file contents: @@ -287,6 +287,20 @@ Example filter file contents: # filter any domain that starts with adserver ^adserver +=item B + +This option can be set to one of `bre`, `ere`, or `fnmatch`. +If `bre` is set, the rules specified in the filter file are matched +using POSIX basic regular expressions, when set to `ere`, using +POSIX extended regular expressions, and when set to `fnmatch` using +the `fnmatch` function as specified in the manpage `man 3p fnmatch`. +`fnmatch` matching is identical to what's used in the shell to match +filenames, so for example `*.google.com` matches everything that +ends with `.google.com`. +If you don't know what regular expressions are or you're using filter +lists from 3rd party sources, `fnmatch` is probably what you want. +It's also the fastest matching method of the three. + =item B If this boolean option is set to `Yes` or `On`, filtering is @@ -300,6 +314,7 @@ recommended not to use this option. =item B +Deprecated. Use `FilterType ere` instead. If this boolean option is set to `Yes`, then extended POSIX regular expressions are used for matching the filter rules. The default is to use basic POSIX regular expressions. @@ -308,7 +323,11 @@ The default is to use basic POSIX regular expressions. If this boolean option is set to `Yes`, then the filter rules are matched in a case sensitive manner. The default is to -match case-insensitively. +match case-insensitively, unfortunately. +If you set this to `Yes`, then your matching will be almost +twice as fast. +This setting affects only `bre` and `ere` FilterTypes, fnmatch +is always case sensitive. =item B diff --git a/etc/tinyproxy.conf.in b/etc/tinyproxy.conf.in index ce27f7ec..d2687093 100644 --- a/etc/tinyproxy.conf.in +++ b/etc/tinyproxy.conf.in @@ -240,10 +240,9 @@ ViaProxyName "tinyproxy" #FilterURLs On # -# FilterExtended: Use POSIX Extended regular expressions rather than -# basic. +# FilterType: Use bre (default), ere, or fnmatch for filtering. # -#FilterExtended On +#FilterType fnmatch # # FilterCaseSensitive: Use case sensitive regular expressions. diff --git a/src/conf-tokens.c b/src/conf-tokens.c index bad70136..2a1ddbe8 100644 --- a/src/conf-tokens.c +++ b/src/conf-tokens.c @@ -34,6 +34,7 @@ config_directive_find (register const char *str, register size_t len) {"defaulterrorfile", CD_defaulterrorfile}, {"startservers", CD_startservers}, {"filtercasesensitive", CD_filtercasesensitive}, + {"filtertype", CD_filtertype}, {"filterurls", CD_filterurls}, {"filter", CD_filter}, {"reversemagic", CD_reversemagic}, diff --git a/src/conf-tokens.gperf b/src/conf-tokens.gperf index ef93245c..f027a23b 100644 --- a/src/conf-tokens.gperf +++ b/src/conf-tokens.gperf @@ -51,6 +51,7 @@ filterurls, CD_filterurls filterextended, CD_filterextended filterdefaultdeny, CD_filterdefaultdeny filtercasesensitive, CD_filtercasesensitive +filtertype, CD_filtertype reversebaseurl, CD_reversebaseurl reverseonly, CD_reverseonly reversemagic, CD_reversemagic diff --git a/src/conf-tokens.h b/src/conf-tokens.h index d9f03cd7..a6338f8f 100644 --- a/src/conf-tokens.h +++ b/src/conf-tokens.h @@ -33,6 +33,7 @@ CD_errorfile, CD_addheader, CD_filter, CD_filterurls, +CD_filtertype, CD_filterextended, CD_filterdefaultdeny, CD_filtercasesensitive, diff --git a/src/conf.c b/src/conf.c index 7033661a..7f94b654 100644 --- a/src/conf.c +++ b/src/conf.c @@ -135,6 +135,7 @@ static HANDLE_FUNC (handle_filtercasesensitive); static HANDLE_FUNC (handle_filterdefaultdeny); static HANDLE_FUNC (handle_filterextended); static HANDLE_FUNC (handle_filterurls); +static HANDLE_FUNC (handle_filtertype); #endif static HANDLE_FUNC (handle_group); static HANDLE_FUNC (handle_listen); @@ -234,6 +235,7 @@ struct { STDCONF (filterextended, BOOL, handle_filterextended), STDCONF (filterdefaultdeny, BOOL, handle_filterdefaultdeny), STDCONF (filtercasesensitive, BOOL, handle_filtercasesensitive), + STDCONF (filtertype, "(bre|ere|fnmatch)", handle_filtertype), #endif #ifdef REVERSE_SUPPORT /* Reverse proxy arguments */ @@ -952,6 +954,11 @@ static HANDLE_FUNC (handle_basicauth) } #ifdef FILTER_ENABLE + +static void warn_deprecated(const char *arg, unsigned long lineno) { + CP_WARN ("deprecated option %s", arg); +} + static HANDLE_FUNC (handle_filter) { return set_string_arg (&conf->filter, line, &match[2]); @@ -959,26 +966,53 @@ static HANDLE_FUNC (handle_filter) static HANDLE_FUNC (handle_filterurls) { - return set_bool_arg (&conf->filter_url, line, &match[2]); + conf->filter_opts |= + get_bool_arg (line, &match[2]) * FILTER_OPT_URL; + return 0; } static HANDLE_FUNC (handle_filterextended) { - return set_bool_arg (&conf->filter_extended, line, &match[2]); + warn_deprecated("FilterExtended, use FilterType", lineno); + conf->filter_opts |= + get_bool_arg (line, &match[2]) * FILTER_OPT_TYPE_ERE; + return 0; } static HANDLE_FUNC (handle_filterdefaultdeny) { assert (match[2].rm_so != -1); - - if (get_bool_arg (line, &match[2])) - filter_set_default_policy (FILTER_DEFAULT_DENY); + conf->filter_opts |= + get_bool_arg (line, &match[2]) * FILTER_OPT_DEFAULT_DENY; return 0; } static HANDLE_FUNC (handle_filtercasesensitive) { - return set_bool_arg (&conf->filter_casesensitive, line, &match[2]); + conf->filter_opts |= + get_bool_arg (line, &match[2]) * FILTER_OPT_CASESENSITIVE; + return 0; +} + +static HANDLE_FUNC (handle_filtertype) +{ + static const struct { unsigned short flag; char type[8]; } + ftmap[] = { + {FILTER_OPT_TYPE_ERE, "ere"}, + {FILTER_OPT_TYPE_BRE, "bre"}, + {FILTER_OPT_TYPE_FNMATCH, "fnmatch"}, + }; + char *type; + unsigned i; + type = get_string_arg(line, &match[2]); + if (!type) return -1; + + for(i=0;ifilter_opts |= ftmap[i].flag; + + safefree (type); + return 0; } #endif diff --git a/src/conf.h b/src/conf.h index 99140492..0a0f06f7 100644 --- a/src/conf.h +++ b/src/conf.h @@ -50,9 +50,7 @@ struct config_s { sblist *listen_addrs; #ifdef FILTER_ENABLE char *filter; - unsigned int filter_url; /* boolean */ - unsigned int filter_extended; /* boolean */ - unsigned int filter_casesensitive; /* boolean */ + unsigned int filter_opts; /* enum filter_options */ #endif /* FILTER_ENABLE */ #ifdef XTINYPROXY_ENABLE unsigned int add_xtinyproxy; /* boolean */ diff --git a/src/filter.c b/src/filter.c index b9b50661..0dbc93d2 100644 --- a/src/filter.c +++ b/src/filter.c @@ -25,6 +25,7 @@ #include "main.h" #include +#include #include "filter.h" #include "heap.h" #include "log.h" @@ -37,15 +38,17 @@ static int err; struct filter_list { - regex_t cpatb; + union { + regex_t cpatb; + char *pattern; + } u; }; static sblist *fl = NULL; static int already_init = 0; -static filter_policy_t default_policy = FILTER_DEFAULT_ALLOW; /* - * Initializes a linked list of strings containing hosts/urls to be filtered + * Initializes a list of strings containing hosts/urls to be filtered */ void filter_init (void) { @@ -66,10 +69,8 @@ void filter_init (void) } cflags = REG_NEWLINE | REG_NOSUB; - if (config->filter_extended) - cflags |= REG_EXTENDED; - if (!config->filter_casesensitive) - cflags |= REG_ICASE; + cflags |= (REG_EXTENDED * !!(config->filter_opts & FILTER_OPT_TYPE_ERE)); + cflags |= (REG_ICASE * !(config->filter_opts & FILTER_OPT_CASESENSITIVE)); while (fgets (buf, FILTER_BUFFER_LEN, fd)) { ++lineno; @@ -107,13 +108,19 @@ void filter_init (void) if (!fl) fl = sblist_new(sizeof(struct filter_list), 4096/sizeof(struct filter_list)); - err = regcomp (&fe.cpatb, s, cflags); - if (err != 0) { - if (err == REG_ESPACE) goto oom; - fprintf (stderr, - "Bad regex in %s: line %d - %s\n", - config->filter, lineno, s); - exit (EX_DATAERR); + if (config->filter_opts & FILTER_OPT_TYPE_FNMATCH) { + fe.u.pattern = safestrdup(s); + if (!fe.u.pattern) goto oom; + } else { + + err = regcomp (&fe.u.cpatb, s, cflags); + if (err != 0) { + if (err == REG_ESPACE) goto oom; + fprintf (stderr, + "Bad regex in %s: line %d - %s\n", + config->filter, lineno, s); + exit (EX_DATAERR); + } } if (!sblist_add(fl, &fe)) { oom:; @@ -142,7 +149,10 @@ void filter_destroy (void) if (fl) { for (i = 0; i < sblist_getsize(fl); ++i) { p = sblist_get(fl, i); - regfree (&p->cpatb); + if (config->filter_opts & FILTER_OPT_TYPE_FNMATCH) + safefree(p->u.pattern); + else + regfree (&p->u.cpatb); } sblist_free(fl); } @@ -175,11 +185,14 @@ int filter_run (const char *str) for (i = 0; i < sblist_getsize(fl); ++i) { p = sblist_get(fl, i); - result = - regexec (&p->cpatb, str, (size_t) 0, (regmatch_t *) 0, 0); + if (config->filter_opts & FILTER_OPT_TYPE_FNMATCH) + result = fnmatch (p->u.pattern, str, 0); + else + result = + regexec (&p->u.cpatb, str, (size_t) 0, (regmatch_t *) 0, 0); if (result == 0) { - if (default_policy == FILTER_DEFAULT_ALLOW) + if (!(config->filter_opts & FILTER_OPT_DEFAULT_DENY)) return 1; else return 0; @@ -187,16 +200,8 @@ int filter_run (const char *str) } COMMON_EXIT: - if (default_policy == FILTER_DEFAULT_ALLOW) + if (!(config->filter_opts & FILTER_OPT_DEFAULT_DENY)) return 0; else return 1; } - -/* - * Set the default filtering policy - */ -void filter_set_default_policy (filter_policy_t policy) -{ - default_policy = policy; -} diff --git a/src/filter.h b/src/filter.h index 8a7575bf..e5f34687 100644 --- a/src/filter.h +++ b/src/filter.h @@ -21,16 +21,22 @@ #ifndef _TINYPROXY_FILTER_H_ #define _TINYPROXY_FILTER_H_ -typedef enum { - FILTER_DEFAULT_ALLOW, - FILTER_DEFAULT_DENY -} filter_policy_t; +enum filter_options { + FILTER_OPT_CASESENSITIVE = 1 << 0, + FILTER_OPT_URL = 1 << 1, + FILTER_OPT_DEFAULT_DENY = 1 << 2, + + FILTER_OPT_TYPE_BRE = 1 << 8, + FILTER_OPT_TYPE_ERE = 1 << 9, + FILTER_OPT_TYPE_FNMATCH = 1 << 10, +}; + +#define FILTER_TYPE_MASK \ + (FILTER_OPT_TYPE_BRE | FILTER_OPT_TYPE_ERE | FILTER_OPT_TYPE_FNMATCH) extern void filter_init (void); extern void filter_destroy (void); extern void filter_reload (void); extern int filter_run (const char *str); -extern void filter_set_default_policy (filter_policy_t policy); - #endif diff --git a/src/reqs.c b/src/reqs.c index 50f69144..a6289a4d 100644 --- a/src/reqs.c +++ b/src/reqs.c @@ -471,22 +471,16 @@ static struct request_s *process_request (struct conn_s *connptr, * Filter restricted domains/urls */ if (config->filter) { - if (config->filter_url) - ret = filter_run (url); - else - ret = filter_run (request->host); + int fu = config->filter_opts & FILTER_OPT_URL; + ret = filter_run (fu ? url : request->host); if (ret) { update_stats (STAT_DENIED); - if (config->filter_url) - log_message (LOG_NOTICE, - "Proxying refused on filtered url \"%s\"", - url); - else - log_message (LOG_NOTICE, - "Proxying refused on filtered domain \"%s\"", - request->host); + log_message (LOG_NOTICE, + "Proxying refused on filtered %s \"%s\"", + fu ? "url" : "domain", + fu ? url : request->host); indicate_http_error (connptr, 403, "Filtered", "detail", From 7d1e86ccaef27d135c77d2c7a03a15cd957e41d6 Mon Sep 17 00:00:00 2001 From: rofl0r Date: Mon, 2 May 2022 14:50:42 +0000 Subject: [PATCH 17/71] don't try to send 408 error to closed client socket read_request_line() is exercised on the client's fd, and it fails when the client closed the connection. therefore it's wrong to send an error message to the client in this situation. additionally, the error message states that the server closed the connection. might fix #383 --- src/reqs.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/reqs.c b/src/reqs.c index a6289a4d..50aaec64 100644 --- a/src/reqs.c +++ b/src/reqs.c @@ -1622,11 +1622,7 @@ void handle_connection (struct conn_s *connptr, union sockaddr_union* addr) if (read_request_line (connptr) < 0) { update_stats (STAT_BADCONN); - indicate_http_error (connptr, 408, "Timeout", - "detail", - "Server timeout waiting for the HTTP request " - "from the client.", NULL); - HC_FAIL(); + goto done; } /* From 77cd87efef26e0adf277ed8a16b442a818ecec9b Mon Sep 17 00:00:00 2001 From: rofl0r Date: Fri, 27 May 2022 12:48:41 +0000 Subject: [PATCH 18/71] print error message if errorfile is configured but can't be opened also, don't use fopen(NULL) if usage of errorfiles is not configured. --- src/html-error.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/html-error.c b/src/html-error.c index 998a6ee7..ccafc59b 100644 --- a/src/html-error.c +++ b/src/html-error.c @@ -30,6 +30,7 @@ #include "network.h" #include "utils.h" #include "conf.h" +#include "log.h" #include @@ -188,8 +189,12 @@ int send_http_error_message (struct conn_s *connptr) connptr->error_string, add); error_file = get_html_file (connptr->error_number); - if (!(infile = fopen (error_file, "r"))) { - char *detail = lookup_variable (connptr->error_variables, "detail"); + if (!error_file || !(infile = fopen (error_file, "r"))) { + char *detail; + if (error_file) log_message (LOG_ERR, + "Error opening error file '%s' (%s)", + error_file, strerror (errno)); + detail = lookup_variable (connptr->error_variables, "detail"); return (write_message (connptr->client_fd, fallback_error, connptr->error_number, connptr->error_string, From d9e38babb77ce3827835e6983ed3248a0e0c5c16 Mon Sep 17 00:00:00 2001 From: rofl0r Date: Fri, 27 May 2022 13:29:04 +0000 Subject: [PATCH 19/71] add gperf generated files to make dist --- src/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index d132a75f..a7fef4ee 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -67,5 +67,5 @@ conf-tokens-gperf.inc: conf-tokens.gperf $(GPERF) $< > $@ endif -EXTRA_DIST = conf-tokens.gperf +EXTRA_DIST = conf-tokens.gperf conf-tokens-gperf.inc From d6ee3835f0c0466ff58db1c6a6913c554e1c67a7 Mon Sep 17 00:00:00 2001 From: rofl0r Date: Fri, 27 May 2022 13:37:49 +0000 Subject: [PATCH 20/71] configure: use release tarball provided gperf file --- configure.ac | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index d904c788..51bbd5d8 100644 --- a/configure.ac +++ b/configure.ac @@ -194,20 +194,21 @@ fi #manpage_support_enabled AM_CONDITIONAL(HAVE_POD2MAN, test "x$POD2MAN" != "x" -a "x$POD2MAN" != "xno") AC_PATH_PROG(GPERF, gperf, no) -AM_CONDITIONAL(HAVE_GPERF, test "x$GPERF" != "x" -a "x$GPERF" != "xno") AH_TEMPLATE([HAVE_GPERF], [Whether you have gperf installed for faster config parsing.]) +tmp_gperf=false if test "x$GPERF" != "x" -a "x$GPERF" != "xno" ; then AS_ECHO_N(["checking whether gperf is recent enough... "]) if "$GPERF" < src/conf-tokens.gperf >/dev/null 2>&1 ; then AS_ECHO("yes") AC_DEFINE(HAVE_GPERF) + tmp_gperf=true else - AM_CONDITIONAL(HAVE_GPERF, false) AS_ECHO("no") fi fi +AM_CONDITIONAL(HAVE_GPERF, $tmp_gperf) AC_CONFIG_FILES([ Makefile @@ -244,3 +245,7 @@ if test "x$POD2MAN" = "xno" ; then touch docs/man8/tinyproxy.8 fi fi + +if test "x$HAVE_GPERF" = "xno" && test -e src/conf-tokens-gperf.inc ; then + touch src/conf-tokens-gperf.inc +fi From ea75e79609391fbe2f57b827871ad9bede33db88 Mon Sep 17 00:00:00 2001 From: rofl0r Date: Fri, 27 May 2022 13:12:47 +0000 Subject: [PATCH 21/71] CI: add github workflow to build release tarball --- .github/workflows/release_tarball.yml | 61 +++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 .github/workflows/release_tarball.yml diff --git a/.github/workflows/release_tarball.yml b/.github/workflows/release_tarball.yml new file mode 100644 index 00000000..99ef49e0 --- /dev/null +++ b/.github/workflows/release_tarball.yml @@ -0,0 +1,61 @@ +name: Generate Source Tarball + +# Trigger whenever a release is created +on: + release: + types: + - created + +jobs: + build: + name: build + runs-on: ubuntu-latest + steps: + + - uses: actions/checkout@v2 + with: + submodules: recursive + + - name: archive + id: archive + run: | + sudo apt install -y gperf + rm -rf .git + autoreconf -i + VERSION=$(cat VERSION) + PKGNAME="tinyproxy-$VERSION" + ./configure + make dist + echo "::set-output name=tarball_xz::${PKGNAME}.tar.xz" + echo "::set-output name=tarball_gz::${PKGNAME}.tar.gz" + echo "::set-output name=tarball_bz2::${PKGNAME}.tar.bz2" + + - name: upload tarball_xz + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ github.event.release.upload_url }} + asset_path: ./${{ steps.archive.outputs.tarball_xz }} + asset_name: ${{ steps.archive.outputs.tarball_xz }} + asset_content_type: application/x-xz + + - name: upload tarball_gz + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ github.event.release.upload_url }} + asset_path: ./${{ steps.archive.outputs.tarball_gz }} + asset_name: ${{ steps.archive.outputs.tarball_gz }} + asset_content_type: application/x-gzip + + - name: upload tarball_bz2 + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ github.event.release.upload_url }} + asset_path: ./${{ steps.archive.outputs.tarball_bz2 }} + asset_name: ${{ steps.archive.outputs.tarball_bz2 }} + asset_content_type: application/x-bzip2 From 90adf28663874e6d34d3eebeae6279906443aea5 Mon Sep 17 00:00:00 2001 From: rofl0r Date: Fri, 27 May 2022 14:08:03 +0000 Subject: [PATCH 22/71] release 1.11.1 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 1cac385c..720c7384 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.11.0 +1.11.1 From 8b373f804e210e9ee2b8a17ba852f1b78716827e Mon Sep 17 00:00:00 2001 From: rofl0r Date: Mon, 30 May 2022 19:10:27 +0000 Subject: [PATCH 23/71] update html documentation, add quickstart section --- docs/web/tp.html.head | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/docs/web/tp.html.head b/docs/web/tp.html.head index 6ce2b0b1..351564ce 100644 --- a/docs/web/tp.html.head +++ b/docs/web/tp.html.head @@ -41,25 +41,27 @@

Tinyproxy requires only a minimal POSIX environment to build and operate. It can use additional libraries to add functionality though.

-

Tinyproxy allows forwarding of HTTPS connections without modifying traffic in any way through the CONNECT method (see the ConnectPort directive).

+

Tinyproxy allows forwarding of HTTPS connections without modifying traffic in any way through the CONNECT method (see the ConnectPort directive, which you should disable, unless you want to restrict the users).

Tinyproxy supports being configured as a transparent proxy, so that a proxy can be used without requiring any client-side configuration. You can also use it as a reverse proxy front-end to your websites.

-

Using the AddHeader directive, you can add/insert HTTP headers to outgoing traffic.

+

Using the AddHeader directive, you can add/insert HTTP headers to outgoing traffic (HTTP only).

If you're looking to build a custom web proxy, Tinyproxy is easy to modify to your custom needs. The source is straightforward, adhering to the KISS principle. As such, it can be used as a foundation for anything you may need a web proxy to do.

-

Tinyproxy has privacy features which can let you configure which HTTP headers should be allowed through, and which should be blocked. This allows you to restrict both what data comes to your web browser from the HTTP server (e.g., cookies), and to restrict what data is allowed through from your web browser to the HTTP server (e.g., version information).

+

Tinyproxy has privacy features which can let you configure which HTTP headers should be allowed through, and which should be blocked. This allows you to restrict both what data comes to your web browser from the HTTP server (e.g., cookies), and to restrict what data is allowed through from your web browser to the HTTP server (e.g., version information). Note that these features do not affect HTTPS connections.

Using the remote monitoring facility, you can access proxy statistics from afar, letting you know exactly how busy the proxy is.

You can configure Tinyproxy to control access by only allowing requests from a certain subnet, or from a certain interface, thus ensuring that random, unauthorized people will not be using your proxy.

-

With a bit of configuration (specifically, making Tinyproxy created files owned by a non-root user and running it on a port greater than 1024), Tinyproxy can be made to run without any special privileges, thus minimizing the chance of system compromise. Furthermore, it was designed with an eye towards preventing buffer overflows. The simplicity of the code ensures it remains easy to spot such bugs.

+

With a bit of configuration (specifically, making Tinyproxy created files owned by a non-root user and running it on a port greater than 1024), Tinyproxy can be made to run without any special privileges, thus minimizing the chance of system compromise. In fact, it is recommended to run it as a regular/restricted user. Furthermore, it was designed with an eye towards preventing buffer overflows. The simplicity of the code ensures it remains easy to spot such bugs.

Downloads

+

Note that many distributions ship horribly outdated versions of tinyproxy, therefore it is recommended to compile it from source.

+
  • On Red Hat Enterprise Linux, or its derivatives such as CentOS, install Tinyproxy from the EPEL repository by running yum install tinyproxy.
  • On Fedora, install Tinyproxy by running yum install tinyproxy.
  • @@ -70,7 +72,7 @@
  • Mac OS X users can check MacPorts to see if the Tinyproxy port there is recent enough.
-

If you feel that the Tinyproxy binary package in your operating system is not recent, please contact the package maintainer for that particular operating system. If this fails, you can always compile the latest stable version from source code.

+

If you feel that the Tinyproxy binary package in your operating system is not recent (likely), please contact the package maintainer for that particular operating system. If this fails, you can always compile the latest stable, or even better, the latest git master version, from source code.

We distribute Tinyproxy in source code form, and it has to be compiled in order to be used on your system. Please see the INSTALL file in the source code tree for build instructions. The current stable version of Tinyproxy is available on the releases page. The Tinyproxy NEWS file contains the release notes. You can verify the tarball using its PGP signature. You can also browse the older releases of Tinyproxy.

@@ -78,5 +80,19 @@

git clone https://github.com/tinyproxy/tinyproxy.git

+

+Quickstart

+ +

The quickest way to get started is using a minimal config file like the below:

+ +

+Port 8888
+Listen 127.0.0.1
+Timeout 600
+Allow 127.0.0.1
+
+ +

And then simply run tinyproxy -d -c tinyproxy.conf as your current user. This starts tinyproxy in foreground mode with tinyproxy.conf as its config, while logging to stdout. Now, all programs supporting a HTTP proxy can use 127.0.0.1:8888 as a proxy. You can try it out using http_proxy=127.0.0.1:8888 curl example.com.

+

Documentation

From 121be4a74e1c917f49d54a0cd34f7e20fb58123d Mon Sep 17 00:00:00 2001 From: rofl0r Date: Fri, 15 Jul 2022 23:43:13 +0000 Subject: [PATCH 24/71] echo http protocol version on CONNECT request response while at it, the function doing it was renamed from the misleading ssl name to what it actually does. also inlined the strings that were previously defined as macros. addressing #152 --- src/reqs.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/src/reqs.c b/src/reqs.c index 50aaec64..fcc0dbf2 100644 --- a/src/reqs.c +++ b/src/reqs.c @@ -301,21 +301,16 @@ establish_http_connection (struct conn_s *connptr, struct request_s *request) } /* - * These two defines are for the SSL tunnelling. + * Send the appropriate response to the client to establish a + * connection via CONNECT method. */ -#define SSL_CONNECTION_RESPONSE "HTTP/1.0 200 Connection established" -#define PROXY_AGENT "Proxy-agent: " PACKAGE "/" VERSION - -/* - * Send the appropriate response to the client to establish a SSL - * connection. - */ -static int send_ssl_response (struct conn_s *connptr) +static int send_connect_method_response (struct conn_s *connptr) { return write_message (connptr->client_fd, - "%s\r\n" - "%s\r\n" - "\r\n", SSL_CONNECTION_RESPONSE, PROXY_AGENT); + "HTTP/1.%u 200 Connection established\r\n" + "Proxy-agent: " PACKAGE "/" VERSION "\r\n" + "\r\n", connptr->protocol.major != 1 ? 0 : + connptr->protocol.minor); } /* @@ -1762,10 +1757,10 @@ void handle_connection (struct conn_s *connptr, union sockaddr_union* addr) HC_FAIL(); } } else { - if (send_ssl_response (connptr) < 0) { + if (send_connect_method_response (connptr) < 0) { log_message (LOG_ERR, - "handle_connection: Could not send SSL greeting " - "to client."); + "handle_connection: Could not send CONNECT" + " method greeting to client."); update_stats (STAT_BADCONN); HC_FAIL(); } From 84f203fb1c4733608c7283bbe794005a469c4b00 Mon Sep 17 00:00:00 2001 From: rofl0r Date: Sat, 20 Aug 2022 14:43:24 +0000 Subject: [PATCH 25/71] fix reversepath directive using https url giving misleading error it's not possible to use a https url in a ReversePath directive, without removing the security provided by https, and would require adding a dependency on a TLS library like openssl and a lot of code complexity to fetch the requested resource via https and relay it back to the client. in case the reversepath directive kicked in, but the protocol wasn't recognized, and support for transparent proxying built-in, the code wrongfully tried to turn the request into a trans request, leading to a bogus rewritten url like http://localhost:8888https://www.endpoint.com and an error message that we're trying to connect to the machine the proxy runs on. now instead use the generic code that signals an invalid protocol/url was used. closes #419 --- src/reqs.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/reqs.c b/src/reqs.c index fcc0dbf2..bce69819 100644 --- a/src/reqs.c +++ b/src/reqs.c @@ -322,9 +322,11 @@ static struct request_s *process_request (struct conn_s *connptr, { char *url; struct request_s *request; - int ret; + int ret, skip_trans; size_t request_len; + skip_trans = 0; + /* NULL out all the fields so frees don't cause segfaults. */ request = (struct request_s *) safecalloc (1, sizeof (struct request_s)); @@ -397,6 +399,7 @@ static struct request_s *process_request (struct conn_s *connptr, } safefree (url); url = reverse_url; + skip_trans = 1; } else if (config->reverseonly) { log_message (LOG_ERR, "Bad request, no mapping for '%s' found", @@ -446,11 +449,13 @@ static struct request_s *process_request (struct conn_s *connptr, connptr->connect_method = TRUE; } else { #ifdef TRANSPARENT_PROXY - if (!do_transparent_proxy - (connptr, hashofheaders, request, config, &url)) { - goto fail; - } -#else + if (!skip_trans) { + if (!do_transparent_proxy + (connptr, hashofheaders, request, config, &url)) + goto fail; + } else +#endif + { indicate_http_error (connptr, 501, "Not Implemented", "detail", "Unknown method or unsupported protocol.", @@ -458,7 +463,7 @@ static struct request_s *process_request (struct conn_s *connptr, log_message (LOG_INFO, "Unknown method (%s) or protocol (%s)", request->method, url); goto fail; -#endif + } } #ifdef FILTER_ENABLE From 3764b8551463b900b5b4e3ec0cd9bb9182191cb7 Mon Sep 17 00:00:00 2001 From: rofl0r Date: Thu, 8 Sep 2022 15:18:04 +0000 Subject: [PATCH 26/71] prevent junk from showing up in error page in invalid requests fixes #457 --- src/reqs.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/reqs.c b/src/reqs.c index bce69819..45db118d 100644 --- a/src/reqs.c +++ b/src/reqs.c @@ -343,8 +343,12 @@ static struct request_s *process_request (struct conn_s *connptr, goto fail; } + /* zero-terminate the strings so they don't contain junk in error page */ + request->method[0] = url[0] = request->protocol[0] = 0; + ret = sscanf (connptr->request_line, "%[^ ] %[^ ] %[^ ]", request->method, url, request->protocol); + if (ret == 2 && !strcasecmp (request->method, "GET")) { request->protocol[0] = 0; From 6ffd9af2c7b88a43be8865cc8e1d450643786b1d Mon Sep 17 00:00:00 2001 From: rofl0r Date: Wed, 1 Feb 2023 13:16:58 +0000 Subject: [PATCH 27/71] hsearch: fix potential UB (pointer arithmetics on nullptr) closes #471 addresses #470 --- src/hsearch.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/hsearch.c b/src/hsearch.c index be0434c2..dfe1404a 100644 --- a/src/hsearch.c +++ b/src/hsearch.c @@ -80,9 +80,10 @@ static int resize(struct htab *htab, size_t nel) { size_t newsize; size_t i, j; + size_t oldmask = htab->mask; struct elem *e, *newe; struct elem *oldtab = htab->elems; - struct elem *oldend = htab->elems + htab->mask + 1; + struct elem *oldend; if (nel > MAXSIZE) nel = MAXSIZE; @@ -95,6 +96,8 @@ static int resize(struct htab *htab, size_t nel) htab->mask = newsize - 1; if (!oldtab) return 1; + + oldend = oldtab + oldmask + 1; for (e = oldtab; e < oldend; e++) if (e->item.key) { for (i=e->hash,j=1; ; i+=j++) { From 470cc0863d276c339db0e84b64055523823c2587 Mon Sep 17 00:00:00 2001 From: rofl0r Date: Wed, 1 Feb 2023 13:32:45 +0000 Subject: [PATCH 28/71] conf: fix potential crash with invalid input data closes #474 --- src/conf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/conf.c b/src/conf.c index 7f94b654..257cafe3 100644 --- a/src/conf.c +++ b/src/conf.c @@ -427,7 +427,7 @@ static int config_parse (struct config_s *conf, FILE * f) while(isspace(*p))p++; if(!*p) continue; q = p; - while(!isspace(*q))q++; + while(*q && !isspace(*q))q++; c = *q; *q = 0; e = config_directive_find(p, strlen(p)); From 31339cb1615765f2fbb4ec7779400535bad6da46 Mon Sep 17 00:00:00 2001 From: rofl0r Date: Wed, 1 Feb 2023 15:46:58 +0000 Subject: [PATCH 29/71] tinyproxy.conf.5: update text for bind directive the existing text was sort of misleading as it was written in a pre-HTTPS era. addressing #475 --- docs/man5/tinyproxy.conf.txt.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/man5/tinyproxy.conf.txt.in b/docs/man5/tinyproxy.conf.txt.in index 1e1ee3ef..23f72a47 100644 --- a/docs/man5/tinyproxy.conf.txt.in +++ b/docs/man5/tinyproxy.conf.txt.in @@ -57,7 +57,7 @@ only on one specific address. =item B This allows you to specify which address Tinyproxy will bind -to for outgoing connections to web servers or upstream proxies. +to for outgoing connections. This parameter may be specified multiple times, then Tinyproxy will try all the specified addresses in order. From ef60434b392f9efe85510a1086be5ea1e24fd2a1 Mon Sep 17 00:00:00 2001 From: rofl0r Date: Mon, 20 Mar 2023 20:35:58 +0000 Subject: [PATCH 30/71] docs: typo fix closes #487 --- etc/tinyproxy.conf.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etc/tinyproxy.conf.in b/etc/tinyproxy.conf.in index d2687093..d9598d3e 100644 --- a/etc/tinyproxy.conf.in +++ b/etc/tinyproxy.conf.in @@ -3,7 +3,7 @@ ## ## This example tinyproxy.conf file contains example settings ## with explanations in comments. For decriptions of all -## parameters, see the tinproxy.conf(5) manual page. +## parameters, see the tinyproxy.conf(5) manual page. ## # From 2bec15ee40dd26920e4f275acd3a7c84a1b6012c Mon Sep 17 00:00:00 2001 From: Mario-Klebsch <62026480+Mario-Klebsch@users.noreply.github.com> Date: Tue, 23 May 2023 15:04:48 +0200 Subject: [PATCH 31/71] Allow configuring IPv6 address for upstream proxy (#492) * Added support to configure IPv6 upstream proxy servers using bracket syntax. * Added regular expression for IPv6 scope identifier to re for IPv6 address. --- src/conf.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/conf.c b/src/conf.c index 257cafe3..002d2ff9 100644 --- a/src/conf.c +++ b/src/conf.c @@ -66,9 +66,10 @@ #define PASSWORD "([^@]*)" #define IP "((([0-9]{1,3})\\.){3}[0-9]{1,3})" #define IPMASK "(" IP "(/" DIGIT "+)?)" +#define IPV6SCOPE "((%[^ \t\\/]{1,16})?)" #define IPV6 "(" \ - "(([0-9a-f:]{2,39}))|" \ - "(([0-9a-f:]{0,29}:" IP "))" \ + "([0-9a-f:]{2,39})" IPV6SCOPE "|" \ + "([0-9a-f:]{0,29}:" IP ")" IPV6SCOPE \ ")" #define IPV6MASK "(" IPV6 "(/" DIGIT "+)?)" @@ -80,7 +81,7 @@ * number. Given the usual structure of the configuration file, sixteen * substring matches should be plenty. */ -#define RE_MAX_MATCHES 24 +#define RE_MAX_MATCHES 33 #define CP_WARN(FMT, ...) \ log_message (LOG_WARNING, "line %lu: " FMT, lineno, __VA_ARGS__) @@ -249,7 +250,7 @@ struct { "(" "(none)" WS STR ")|" \ "(" "(http|socks4|socks5)" WS \ "(" USERNAME /*username*/ ":" PASSWORD /*password*/ "@" ")?" - "(" IP "|" ALNUM ")" + "(" IP "|" "\\[(" IPV6 ")\\]" "|" ALNUM ")" ":" INT "(" WS STR ")?" ")", handle_upstream), #endif /* loglevel */ @@ -1114,10 +1115,13 @@ static HANDLE_FUNC (handle_upstream) pass = get_string_arg (line, &match[mi]); mi++; - ip = get_string_arg (line, &match[mi]); + if (match[mi+4].rm_so != -1) /* IPv6 address in square brackets */ + ip = get_string_arg (line, &match[mi+4]); + else + ip = get_string_arg (line, &match[mi]); if (!ip) return -1; - mi += 5; + mi += 16; port = (int) get_long_arg (line, &match[mi]); mi += 3; From 1e615e66a9944d3169f5cbba62a85c125693b7cf Mon Sep 17 00:00:00 2001 From: ivanwick Date: Wed, 24 May 2023 07:06:15 -0700 Subject: [PATCH 32/71] tinyproxy.conf.5: document config strings that require double quotes (#493) * tinyproxy.conf.5: document config strings that require double quotes String config values matched by the STR regex must be enclosed in double quotes Edit descriptions for brevity conf.c: move boolean arguments comment before BOOL group addresses #491 * Revert conf.c: move boolean arguments comment before BOOL group --- docs/man5/tinyproxy.conf.txt.in | 47 +++++++++++++++++---------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/docs/man5/tinyproxy.conf.txt.in b/docs/man5/tinyproxy.conf.txt.in index 23f72a47..28f4ab9f 100644 --- a/docs/man5/tinyproxy.conf.txt.in +++ b/docs/man5/tinyproxy.conf.txt.in @@ -22,8 +22,8 @@ configuration file. The Tinyproxy configuration file contains key-value pairs, one per line. Lines starting with `#` and empty lines are comments and are ignored. Keywords are case-insensitive, whereas values are -case-sensitive. Values may be enclosed in double-quotes (") if they -contain spaces. +case-sensitive. Some string values must be enclosed in double +quotes (") as noted below. The possible keywords and their descriptions are as follows: @@ -76,29 +76,29 @@ allowed to have before it is closed by Tinyproxy. This parameter controls which HTML file Tinyproxy returns when a given HTTP error occurs. It takes two arguments, the error number -and the location of the HTML error file. +and the location of the HTML error file. Enclose the file location +in double quotes. =item B -This parameter controls the HTML template file returned when an -error occurs for which no specific error file has been set. +The HTML template file returned when an error occurs for which no +specific error file has been set. Enclose in double quotes. =item B -This configures the host name or IP address that is treated -as the `stat host`: Whenever a request for this host is received, -Tinyproxy will return an internal statistics page instead of -forwarding the request to that host. The template for this -page can be configured with the `StatFile` configuration option. -The default value of `StatHost` is `@TINYPROXY_STATHOST@`. +The host name or IP address that is treated as the `stat host`. +Enclose in double quotes. Whenever Tinyproxy receives a request for +the `stat host` it returns an internal statistics page instead of +forwarding the request to that host. The template for this page can be +configured with the `StatFile` configuration option. The default value +of `StatHost` is `@TINYPROXY_STATHOST@`. =item B -This configures the HTML file that Tinyproxy sends when -a request for the stathost is received. If this parameter is -not set, Tinyproxy returns a hard-coded basic statistics page. -See the STATHOST section in the L manual page -for details. +The HTML file that Tinyproxy sends in response to a request for the +`stat host`. Enclose in double quotes. If this parameter is not set, +Tinyproxy returns a hard-coded basic statistics page. See the STATHOST +section in the L manual page for details. Note that the StatFile and the error files configured with ErrorFile and DefaultErrorFile are template files that can contain a few @@ -109,9 +109,9 @@ manual page contains a description of all template variables. =item B -This controls the location of the file to which Tinyproxy -writes its debug output. Alternatively, Tinyproxy can log -to syslog -- see the Syslog option. +The location of the file to which Tinyproxy writes its debug output. +Enclose in double quotes. Alternatively, Tinyproxy can log to syslog +-- see the Syslog option. =item B @@ -144,8 +144,8 @@ and below would be suppressed. Allowed values are: =item B -This option controls the location of the file where the main -Tinyproxy process stores its process ID for signaling purposes. +The location of the file where the main Tinyproxy process stores its +process ID for signaling purposes. Enclose in double quotes. =item B @@ -250,7 +250,8 @@ RFC 2616 requires proxies to add a `Via` header to the HTTP requests, but using the real host name can be a security concern. If the `ViaProxyname` option is present, then its string value will be used as the host name in the Via header. -Otherwise, the server's host name will be used. +Otherwise, the server's host name will be used. Enclose in double +quotes. =item B @@ -344,7 +345,7 @@ If an `Anonymous` keyword is present, then anonymous proxying is enabled. The headers listed with `Anonymous` are allowed through, while all others are denied. If no Anonymous keyword is present, then all headers are allowed through. You must -include quotes around the headers. +include double quotes around the headers. Most sites require cookies to be enabled for them to work correctly, so you will need to allow cookies through if you access those sites. From d7c20e663f3f85238665fed52b0bb35bcc3fc942 Mon Sep 17 00:00:00 2001 From: rofl0r Date: Thu, 25 May 2023 19:42:02 +0000 Subject: [PATCH 33/71] tinyproxy.conf.5: document syntax for upstream IPv6 addresses follow-up to 2bec15ee40dd26920e4f275acd3a7c84a1b6012c --- docs/man5/tinyproxy.conf.txt.in | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/man5/tinyproxy.conf.txt.in b/docs/man5/tinyproxy.conf.txt.in index 28f4ab9f..ed137e2b 100644 --- a/docs/man5/tinyproxy.conf.txt.in +++ b/docs/man5/tinyproxy.conf.txt.in @@ -179,6 +179,10 @@ connection is done directly. =back +It's recommended to use raw IP addresses to specify the upstream host, so +no costly DNS lookup has to be done everytime it is used. +IPv6 addresses need to be enclosed in square brackets. + The site can be specified in various forms as a hostname, domain name or as an IP range: From 2935519eb7f0d1d740fc1c89a3dc2279c9c80208 Mon Sep 17 00:00:00 2001 From: rofl0r Date: Wed, 7 Jun 2023 18:57:05 +0000 Subject: [PATCH 34/71] fix omission to reset socklen parameter for accept() since accept() uses the socklen parameter as in/out, after processing an IPv4 the socklen fed to it waiting for the next client was only the length of sockaddr_in, so if a connection from an IPv6 came in the client sockaddr was only partially filled in. this caused wrongly printed ipv6 addresses in log, and failure to match them correctly against the acl. closes #495 --- src/child.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/child.c b/src/child.c index 985357da..8bae89b2 100644 --- a/src/child.c +++ b/src/child.c @@ -81,7 +81,7 @@ void child_main_loop (void) int connfd; union sockaddr_union cliaddr_storage; struct sockaddr *cliaddr = (void*) &cliaddr_storage; - socklen_t clilen = sizeof(cliaddr_storage); + socklen_t clilen; int nfds = sblist_getsize(listen_fds); pollfd_struct *fds = safecalloc(nfds, sizeof *fds); ssize_t i; @@ -167,6 +167,7 @@ void child_main_loop (void) * Continue handling this connection. */ + clilen = sizeof(cliaddr_storage); connfd = accept (listenfd, cliaddr, &clilen); From 1289d8afc8b50fb95cbfee37d3d394e119fe4832 Mon Sep 17 00:00:00 2001 From: rofl0r Date: Fri, 13 Oct 2023 19:54:26 +0000 Subject: [PATCH 35/71] conf: use case-independent match for Filtertype parameter --- src/conf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/conf.c b/src/conf.c index 002d2ff9..01162e67 100644 --- a/src/conf.c +++ b/src/conf.c @@ -1009,7 +1009,7 @@ static HANDLE_FUNC (handle_filtertype) if (!type) return -1; for(i=0;ifilter_opts |= ftmap[i].flag; safefree (type); From c83407396852e2300940c9b3da4d57841e256ede Mon Sep 17 00:00:00 2001 From: rofl0r Date: Sun, 15 Oct 2023 10:50:48 +0000 Subject: [PATCH 36/71] fix CI by running apt update --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 43541078..f077b192 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -27,8 +27,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - name: install valgrind - run: sudo apt-get install --assume-yes valgrind + - run: sudo apt update + - run: sudo apt install --assume-yes valgrind - run: ./autogen.sh - run: ./configure --enable-debug --enable-transparent --enable-reverse - run: make From 84285b640de76508e4deddbc6cbad751628769ae Mon Sep 17 00:00:00 2001 From: Victor Kislov Date: Thu, 2 Nov 2023 21:24:42 +0200 Subject: [PATCH 37/71] BasicAuth: Accept special chars in username and password (#516) Co-authored-by: Victor Kislov --- src/conf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/conf.c b/src/conf.c index 01162e67..4b5f33a8 100644 --- a/src/conf.c +++ b/src/conf.c @@ -225,7 +225,7 @@ struct { handle_deny), STDCONF (bind, "(" IP "|" IPV6 ")", handle_bind), /* other */ - STDCONF (basicauth, ALNUM WS ALNUM, handle_basicauth), + STDCONF (basicauth, USERNAME WS PASSWORD, handle_basicauth), STDCONF (errorfile, INT WS STR, handle_errorfile), STDCONF (addheader, STR WS STR, handle_addheader), From c4df45b7e416dc1a26bb4e4511e1e7de08fd49af Mon Sep 17 00:00:00 2001 From: strongleong Date: Tue, 7 Nov 2023 13:55:01 +1100 Subject: [PATCH 38/71] BasicAuth: Added logging for failed login attemps closes #514 --- src/reqs.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/reqs.c b/src/reqs.c index 45db118d..58c97a88 100644 --- a/src/reqs.c +++ b/src/reqs.c @@ -1688,6 +1688,10 @@ void handle_connection (struct conn_s *connptr, union sockaddr_union* addr) if(failure) { e401: update_stats (STAT_DENIED); + log_message (LOG_INFO, + "Failed auth attempt (file descriptor: %d), ip %s", + connptr->client_fd, + connptr->client_ip_addr); indicate_http_error (connptr, 401, "Unauthorized", "detail", "The administrator of this proxy has not configured " From 92289d5a4c1bc53fa19fcf4dcc06e3e633134edb Mon Sep 17 00:00:00 2001 From: rofl0r Date: Wed, 1 May 2024 23:48:37 +0000 Subject: [PATCH 39/71] main: print filename of config file used on (re)load --- src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.c b/src/main.c index 7ea55408..268255f1 100644 --- a/src/main.c +++ b/src/main.c @@ -257,7 +257,7 @@ int reload_config (int reload_logging) int ret, ret2; struct config_s *c_next = get_next_config(); - log_message (LOG_NOTICE, "Reloading config file"); + log_message (LOG_NOTICE, "Reloading config file (%s)", config_file); if (reload_logging) shutdown_logging (); From 12a8484265f7b00591293da492bb3c9987001956 Mon Sep 17 00:00:00 2001 From: rofl0r Date: Sun, 5 May 2024 10:37:29 +0000 Subject: [PATCH 40/71] fix potential UAF in header handling (CVE-2023-49606) https://talosintelligence.com/vulnerability_reports/TALOS-2023-1889 this bug was brought to my attention today by the debian tinyproxy package maintainer. the above link states that the issue was known since last year and that maintainers have been contacted, but if that is even true then it probably was done via a private email to a potentially outdated email address of one of the maintainers, not through the channels described clearly on the tinyproxy homepage: > Feel free to report a new bug or suggest features via github issues. > Tinyproxy developers hang out in #tinyproxy on irc.libera.chat. no github issue was filed, and nobody mentioned a vulnerability on the mentioned IRC chat. if the issue had been reported on github or IRC, the bug would have been fixed within a day. --- src/reqs.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/reqs.c b/src/reqs.c index 58c97a88..a65ed54d 100644 --- a/src/reqs.c +++ b/src/reqs.c @@ -779,7 +779,7 @@ static int remove_connection_headers (orderedmap hashofheaders) char *data; char *ptr; ssize_t len; - int i; + int i,j,df; for (i = 0; i != (sizeof (headers) / sizeof (char *)); ++i) { /* Look for the connection header. If it's not found, return. */ @@ -804,7 +804,12 @@ static int remove_connection_headers (orderedmap hashofheaders) */ ptr = data; while (ptr < data + len) { - orderedmap_remove (hashofheaders, ptr); + 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; From e69788b761dd6dad99facebe094a86009a0c1fe1 Mon Sep 17 00:00:00 2001 From: rofl0r Date: Sun, 5 May 2024 20:56:17 +0200 Subject: [PATCH 41/71] Add SECURITY.md given the catastrophic way TALOS Intelligence "communicated" with upstream (i.e. by probably sending a single mail to an unused email address), it's probably best to explicitly document how to approach upstream when a security issue is discovered. --- SECURITY.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..93ef8148 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,28 @@ +# Security Policy + +## Supported Versions + +| Version | Supported | +| --------- | ------------------ | +| 1.11.x | :white_check_mark: | +| <= 1.10.x | :x: | + +## Reporting a Vulnerability + +Open a public issue on github. The issue will most likely be fixed +within a day, unless all maintainers happen to just be taking a +vacation at the same time, which is unlikely. + +Even then, having the bug publicly known will allow competent people +to come up with custom patches for distros, most likely quicker +than black hats can craft a remote execution exploit. + +If you really really do not want to make the issue public, come +to the tinyproxy IRC channel and ask for a maintainer, which you +can then contact via private messages. + +Do not, however, like ["TALOS Intelligence"](https://talosintelligence.com/vulnerability_reports/TALOS-2023-1889) +pull a random email address out of git log, then send an email +nobody reads or responds to, and wait for 6 months for publication. +this only gives black hats plenty time to sell, use and circulate +zero days and get the best possible ROI. From dd49e975a04a66c2a32e6d2fc7cd7ddf0cb9fe33 Mon Sep 17 00:00:00 2001 From: rofl0r Date: Wed, 8 May 2024 18:22:52 +0000 Subject: [PATCH 42/71] release 1.11.2 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 720c7384..ca717669 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.11.1 +1.11.2 From 942d0c6b03673ad816c42176422d7fe691143064 Mon Sep 17 00:00:00 2001 From: Mohamed Akram Date: Sun, 2 Jun 2024 18:52:59 +0400 Subject: [PATCH 43/71] Use appropriate installation path variables --- configure.ac | 4 +++- docs/man8/Makefile.am | 11 +++++++++++ docs/man8/tinyproxy.txt.in | 6 +++++- etc/Makefile.am | 1 + etc/tinyproxy.conf.in | 5 +---- 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index 51bbd5d8..37e7d276 100644 --- a/configure.ac +++ b/configure.ac @@ -173,6 +173,9 @@ fi dnl dnl Substitute the variables into the various Makefiles dnl +# runstatedir isn't available for Autoconf < 2.70 +AS_IF([test -z "${runstatedir}"], [runstatedir='${localstatedir}/run']) +AC_SUBST([runstatedir]) AC_SUBST(CFLAGS) AC_SUBST(LDFLAGS) AC_SUBST(CPPFLAGS) @@ -220,7 +223,6 @@ docs/Makefile docs/man5/Makefile docs/man5/tinyproxy.conf.txt docs/man8/Makefile -docs/man8/tinyproxy.txt m4macros/Makefile tests/Makefile tests/scripts/Makefile diff --git a/docs/man8/Makefile.am b/docs/man8/Makefile.am index d2d7e19b..17281cd3 100644 --- a/docs/man8/Makefile.am +++ b/docs/man8/Makefile.am @@ -9,6 +9,17 @@ M_NAME=TINYPROXY man_MANS = \ $(MAN8_FILES:.txt=.8) +edit = sed \ + -e 's|@localstatedir[@]|$(localstatedir)|g' \ + -e 's|@runstatedir[@]|$(runstatedir)|g' \ + -e 's|@sysconfdir[@]|$(sysconfdir)|g' \ + -e 's|@TINYPROXY_STATHOST[@]|$(TINYPROXY_STATHOST)|g' + +tinyproxy.txt: $(top_srcdir)/docs/man8/tinyproxy.txt.in Makefile + @rm -f $@ $@.tmp + $(AM_V_GEN) $(edit) $(top_srcdir)/docs/man8/$@.in > $@.tmp + @mv $@.tmp $@ + .txt.8: if HAVE_POD2MAN $(AM_V_GEN) $(POD2MAN) --center="Tinyproxy manual" \ diff --git a/docs/man8/tinyproxy.txt.in b/docs/man8/tinyproxy.txt.in index 7fa420f6..9cf2d426 100644 --- a/docs/man8/tinyproxy.txt.in +++ b/docs/man8/tinyproxy.txt.in @@ -156,7 +156,11 @@ configuration variable `StatFile`. =head1 FILES -`/etc/tinyproxy/tinyproxy.conf`, `/var/run/tinyproxy/tinyproxy.pid`, `/var/log/tinyproxy/tinyproxy.log` +F<@sysconfdir@/tinyproxy/tinyproxy.conf> + +F<@runstatedir@/tinyproxy/tinyproxy.pid> + +F<@localstatedir@/log/tinyproxy/tinyproxy.log> =head1 BUGS diff --git a/etc/Makefile.am b/etc/Makefile.am index 57a5c010..045baac3 100644 --- a/etc/Makefile.am +++ b/etc/Makefile.am @@ -12,6 +12,7 @@ edit = sed \ -e 's|@datarootdir[@]|$(datarootdir)|g' \ -e 's|@pkgsysconfdir[@]|$(pkgsysconfdir)|g' \ -e 's|@localstatedir[@]|$(localstatedir)|g' \ + -e 's|@runstatedir[@]|$(runstatedir)|g' \ -e 's|@pkgdatadir[@]|$(pkgdatadir)|g' \ -e 's|@prefix[@]|$(prefix)|g' \ -e 's|@TINYPROXY_STATHOST[@]|$(TINYPROXY_STATHOST)|g' diff --git a/etc/tinyproxy.conf.in b/etc/tinyproxy.conf.in index d9598d3e..af91d039 100644 --- a/etc/tinyproxy.conf.in +++ b/etc/tinyproxy.conf.in @@ -124,7 +124,7 @@ LogLevel Info # can be used for signalling purposes. # If not specified, no pidfile will be written. # -#PidFile "@localstatedir@/run/tinyproxy/tinyproxy.pid" +#PidFile "@runstatedir@/tinyproxy/tinyproxy.pid" # # XTinyproxy: Tell Tinyproxy to include the X-Tinyproxy header, which @@ -320,6 +320,3 @@ ViaProxyName "tinyproxy" # If not set then no rewriting occurs. # #ReverseBaseURL "http://localhost:8888/" - - - From 72b93f6d4b598a1f809f4e5ff383757c52fa9765 Mon Sep 17 00:00:00 2001 From: rofl0r Date: Sun, 16 Jun 2024 12:02:26 +0000 Subject: [PATCH 44/71] CI: update release workflow to non-deprecated actions github continues to deprecate actions and idioms in their CI system. hopefully these changes will last for a while and maintaining a simple CI task doesn't turn into a neverending story. --- .github/workflows/release_tarball.yml | 41 +++++++-------------------- 1 file changed, 10 insertions(+), 31 deletions(-) diff --git a/.github/workflows/release_tarball.yml b/.github/workflows/release_tarball.yml index 99ef49e0..7999f179 100644 --- a/.github/workflows/release_tarball.yml +++ b/.github/workflows/release_tarball.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: submodules: recursive @@ -26,36 +26,15 @@ jobs: PKGNAME="tinyproxy-$VERSION" ./configure make dist - echo "::set-output name=tarball_xz::${PKGNAME}.tar.xz" - echo "::set-output name=tarball_gz::${PKGNAME}.tar.gz" - echo "::set-output name=tarball_bz2::${PKGNAME}.tar.bz2" + echo "tarball_xz=${PKGNAME}.tar.xz" >> "$GITHUB_OUTPUT" + echo "tarball_gz=${PKGNAME}.tar.gz" >> "$GITHUB_OUTPUT" + echo "tarball_bz2=${PKGNAME}.tar.bz2" >> "$GITHUB_OUTPUT" - - name: upload tarball_xz - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: upload tarballs + uses: softprops/action-gh-release@v2 with: - upload_url: ${{ github.event.release.upload_url }} - asset_path: ./${{ steps.archive.outputs.tarball_xz }} - asset_name: ${{ steps.archive.outputs.tarball_xz }} - asset_content_type: application/x-xz + files: | + ${{ steps.archive.outputs.tarball_xz }} + ${{ steps.archive.outputs.tarball_gz }} + ${{ steps.archive.outputs.tarball_bz2 }} - - name: upload tarball_gz - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ github.event.release.upload_url }} - asset_path: ./${{ steps.archive.outputs.tarball_gz }} - asset_name: ${{ steps.archive.outputs.tarball_gz }} - asset_content_type: application/x-gzip - - - name: upload tarball_bz2 - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ github.event.release.upload_url }} - asset_path: ./${{ steps.archive.outputs.tarball_bz2 }} - asset_name: ${{ steps.archive.outputs.tarball_bz2 }} - asset_content_type: application/x-bzip2 From d652ed85386675c4f59b5b511cb059a084d18f6d Mon Sep 17 00:00:00 2001 From: James McKinney <26463+jpmckinney@users.noreply.github.com> Date: Thu, 20 Jun 2024 04:51:29 -0400 Subject: [PATCH 45/71] Omit the version number from headers and HTML responses (#543) Omit the version number from headers, HTML responses, and templates --- data/templates/debug.html | 5 +---- data/templates/default.html | 2 +- data/templates/stats.html | 4 ++-- src/html-error.c | 8 ++++---- src/reqs.c | 11 +++++------ src/stats.c | 10 +++++----- src/utils.c | 2 +- tests/scripts/webclient.pl | 3 +-- tests/scripts/webserver.pl | 3 +-- 9 files changed, 21 insertions(+), 27 deletions(-) diff --git a/data/templates/debug.html b/data/templates/debug.html index 6ee33674..0e7f0549 100644 --- a/data/templates/debug.html +++ b/data/templates/debug.html @@ -30,9 +30,6 @@

{cause}

clienthost
{clienthost}
-
version
-
{version}
-
package
{package}
@@ -49,7 +46,7 @@

{cause}


-

Generated by {package} version {version}.

+

Generated by {package}.

diff --git a/data/templates/default.html b/data/templates/default.html index 67354b7a..8a9c8f6c 100644 --- a/data/templates/default.html +++ b/data/templates/default.html @@ -16,7 +16,7 @@

{cause}


-

Generated by {package} version {version}.

+

Generated by {package}.

diff --git a/data/templates/stats.html b/data/templates/stats.html index a8c3e074..f039c970 100644 --- a/data/templates/stats.html +++ b/data/templates/stats.html @@ -2,7 +2,7 @@ - Stats [{package} v{version}] + Stats [{package}]