From 902d5e4698f38b69ab93768a31462ca6f2427d83 Mon Sep 17 00:00:00 2001 From: goba62000374 Date: Sat, 10 Jun 2017 14:47:15 +0100 Subject: [PATCH] Added support for authenticated proxy upstream --- etc/tinyproxy.conf.in | 3 +++ src/conf.c | 42 ++++++++++++++++++++++++++++++++--- src/reqs.c | 51 +++++++++++++++++++++++++++++++++++++++++++ src/upstream.c | 31 +++++++++++++++++++------- src/upstream.h | 4 +++- 5 files changed, 119 insertions(+), 12 deletions(-) diff --git a/etc/tinyproxy.conf.in b/etc/tinyproxy.conf.in index e24ad4a..68928f8 100644 --- a/etc/tinyproxy.conf.in +++ b/etc/tinyproxy.conf.in @@ -158,6 +158,9 @@ LogLevel Info # # default upstream is internet firewall # upstream firewall.internal.example.com:80 # +# # connection through testproxy with authentication +# upstream user:password@testproxy:8008 ".test.domain.invalid" +# # The LAST matching rule wins the route decision. As you can see, you # can use a host, or a domain: # name matches host exactly diff --git a/src/conf.c b/src/conf.c index c003627..0c32a91 100644 --- a/src/conf.c +++ b/src/conf.c @@ -47,6 +47,7 @@ * given directive. */ #define WS "[[:space:]]+" +#define ANY "(.+)" #define STR "\"([^\"]+)\"" #define BOOL "(yes|on|no|off)" #define INT "((0x)?[[:digit:]]+)" @@ -160,6 +161,7 @@ static HANDLE_FUNC (handle_xtinyproxy); #ifdef UPSTREAM_SUPPORT static HANDLE_FUNC (handle_upstream); +static HANDLE_FUNC (handle_upstream_auth); static HANDLE_FUNC (handle_upstream_no); #endif @@ -257,6 +259,10 @@ struct { BEGIN "(upstream)" WS "(" IP "|" ALNUM ")" ":" INT "(" WS STR ")?" END, handle_upstream, NULL }, + { + BEGIN "(upstream)" WS ALNUM ":" ANY "@(" IP "|" ALNUM ")" ":" INT "(" WS STR + ")?" END, handle_upstream_auth, NULL + }, #endif /* loglevel */ STDCONF ("loglevel", "(critical|error|warning|notice|connect|info)", @@ -1084,11 +1090,41 @@ static HANDLE_FUNC (handle_upstream) if (match[10].rm_so != -1) { domain = get_string_arg (line, &match[10]); if (domain) { - upstream_add (ip, port, domain, &conf->upstream_list); + upstream_add (NULL, NULL, ip, port, domain, &conf->upstream_list); safefree (domain); } } else { - upstream_add (ip, port, NULL, &conf->upstream_list); + upstream_add (NULL, NULL, ip, port, NULL, &conf->upstream_list); + } + + safefree (ip); + + return 0; +} + +static HANDLE_FUNC (handle_upstream_auth) +{ + char *user; + char *pass; + char *ip; + int port; + char *domain; + + ip = get_string_arg (line, &match[4]); + if (!ip) + return -1; + user = get_string_arg (line, &match[2]); + pass = get_string_arg (line, &match[3]); + port = (int) get_long_arg (line, &match[9]); + + if (match[10].rm_so != -1) { + domain = get_string_arg (line, &match[12]); + if (domain) { + upstream_add (user, pass, ip, port, domain, &conf->upstream_list); + safefree (domain); + } + } else { + upstream_add (user, pass, ip, port, NULL, &conf->upstream_list); } safefree (ip); @@ -1104,7 +1140,7 @@ static HANDLE_FUNC (handle_upstream_no) if (!domain) return -1; - upstream_add (NULL, 0, domain, &conf->upstream_list); + upstream_add (NULL, NULL, NULL, 0, domain, &conf->upstream_list); safefree (domain); return 0; diff --git a/src/reqs.c b/src/reqs.c index 990152a..26c67ef 100644 --- a/src/reqs.c +++ b/src/reqs.c @@ -61,6 +61,41 @@ #ifdef UPSTREAM_SUPPORT # define UPSTREAM_CONFIGURED() (config.upstream_list != NULL) # define UPSTREAM_HOST(host) upstream_get(host, config.upstream_list) +static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static void encode_base_64(char* src, char* dest, int max_len) { + int n, l, i; + l = strlen(src); + max_len = (max_len - 1) / 4; + for (i = 0; i < max_len; i++, src += 3, l -= 3) { + switch (l) { + case 0: + break; + case 1: + n = src[0] << 16; + *dest++ = base64[(n >> 18) & 077]; + *dest++ = base64[(n >> 12) & 077]; + *dest++ = '='; + *dest++ = '='; + break; + case 2: + n = src[0] << 16 | src[1] << 8; + *dest++ = base64[(n >> 18) & 077]; + *dest++ = base64[(n >> 12) & 077]; + *dest++ = base64[(n >> 6) & 077]; + *dest++ = '='; + break; + default: + n = src[0] << 16 | src[1] << 8 | src[2]; + *dest++ = base64[(n >> 18) & 077]; + *dest++ = base64[(n >> 12) & 077]; + *dest++ = base64[(n >> 6) & 077]; + *dest++ = base64[n & 077]; + } + if (l < 3) break; + } + *dest++ = 0; +} #else # define UPSTREAM_CONFIGURED() (0) # define UPSTREAM_HOST(host) (NULL) @@ -1498,6 +1533,22 @@ void handle_connection (int fd) connptr->upstream_proxy = UPSTREAM_HOST (request->host); if (connptr->upstream_proxy != NULL) { + if (connptr->upstream_proxy->user) + { + char proxy_auth[200] = ""; + char src[256]; + char dst2[512]; + strcpy(src, connptr->upstream_proxy->user); + strcat(src, ":"); + strcat(src, connptr->upstream_proxy->pass); + encode_base_64(src, dst2, 512); + strcat(proxy_auth, "Basic "); + strcat(proxy_auth, dst2); + + hashmap_insert (hashofheaders, + "Proxy-Authorization", + proxy_auth, strlen (proxy_auth) + 1); + } if (connect_to_upstream (connptr, request) < 0) { goto fail; } diff --git a/src/upstream.c b/src/upstream.c index 6b25f9b..d019ead 100644 --- a/src/upstream.c +++ b/src/upstream.c @@ -32,7 +32,7 @@ /** * Construct an upstream struct from input data. */ -static struct upstream *upstream_build (const char *host, int port, const char *domain) +static struct upstream *upstream_build (const char *user, const char *pass, const char *host, int port, const char *domain) { char *ptr; struct upstream *up; @@ -44,9 +44,18 @@ static struct upstream *upstream_build (const char *host, int port, const char * return NULL; } - up->host = up->domain = NULL; + up->user = up->pass = up->host = up->domain = NULL; up->ip = up->mask = 0; + if (user != NULL) { + up->user = safestrdup(user); + } + + if (pass != NULL) { + up->pass = safestrdup(pass); + } + + if (domain == NULL) { if (!host || host[0] == '\0' || port < 1) { log_message (LOG_WARNING, @@ -57,8 +66,8 @@ static struct upstream *upstream_build (const char *host, int port, const char * up->host = safestrdup (host); up->port = port; - log_message (LOG_INFO, "Added upstream %s:%d for [default]", - host, port); + log_message (LOG_INFO, "Added upstream %s:@%s:%d for [default]", + user, host, port); } else if (host == NULL) { if (!domain || domain[0] == '\0') { log_message (LOG_WARNING, @@ -101,13 +110,15 @@ static struct upstream *upstream_build (const char *host, int port, const char * up->port = port; up->domain = safestrdup (domain); - log_message (LOG_INFO, "Added upstream %s:%d for %s", - host, port, domain); + log_message (LOG_INFO, "Added upstream %s:@%s:%d for %s", + user, host, port, domain); } return up; fail: + safefree (up->user); + safefree (up->pass); safefree (up->host); safefree (up->domain); safefree (up); @@ -118,12 +129,12 @@ fail: /* * Add an entry to the upstream list */ -void upstream_add (const char *host, int port, const char *domain, +void upstream_add (const char *user, const char *pass, const char *host, int port, const char *domain, struct upstream **upstream_list) { struct upstream *up; - up = upstream_build (host, port, domain); + up = upstream_build (user, pass, host, port, domain); if (up == NULL) { return; } @@ -154,6 +165,8 @@ void upstream_add (const char *host, int port, const char *domain, return; upstream_cleanup: + safefree (up->user); + safefree (up->pass); safefree (up->host); safefree (up->domain); safefree (up); @@ -215,6 +228,8 @@ void free_upstream_list (struct upstream *up) while (up) { struct upstream *tmp = up; up = up->next; + safefree (tmp->user); + safefree (tmp->pass); safefree (tmp->domain); safefree (tmp->host); safefree (tmp); diff --git a/src/upstream.h b/src/upstream.h index 34dad68..7b6d031 100644 --- a/src/upstream.h +++ b/src/upstream.h @@ -35,12 +35,14 @@ struct upstream { struct upstream *next; char *domain; /* optional */ char *host; + char *user; + char *pass; int port; in_addr_t ip, mask; }; #ifdef UPSTREAM_SUPPORT -extern void upstream_add (const char *host, int port, const char *domain, +extern void upstream_add (const char *user, const char *pass, const char *host, int port, const char *domain, struct upstream **upstream_list); extern struct upstream *upstream_get (char *host, struct upstream *up); extern void free_upstream_list (struct upstream *up);