Added support for authenticated proxy upstream

This commit is contained in:
goba62000374 2017-06-10 14:47:15 +01:00
parent cb6f868739
commit 902d5e4698
5 changed files with 119 additions and 12 deletions

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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:<hidden>@%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:<hidden>@%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);

View File

@ -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);