implement HTTP basic auth for upstream proxies

loosely based on @valenbg1's code from PR #38

closes #38
closes #96
This commit is contained in:
rofl0r 2018-02-23 20:21:32 +00:00 committed by rofl0r
parent 4d9891e59e
commit bf76aeeba1
5 changed files with 72 additions and 18 deletions

View File

@ -146,6 +146,9 @@ LogLevel Info
# upstream testproxy:8008 ".our_testbed.example.com"
# upstream testproxy:8008 "192.168.128.0/255.255.254.0"
#
# # upstream proxy using basic authentication
# upstream user:pass@testproxy:8008 ".test.domain.invalid"
#
# # no upstream proxy for internal websites and unqualified hosts
# no upstream ".internal.example.com"
# no upstream "www.example.com"

View File

@ -259,8 +259,11 @@ struct {
BEGIN "(no" WS "upstream)" WS STR END, handle_upstream_no, NULL
},
{
BEGIN "(upstream)" WS "(" IP "|" ALNUM ")" ":" INT "(" WS STR
")?" END, handle_upstream, NULL
BEGIN "(upstream)" WS
"(" ALNUM /*username*/ ":" ALNUM /*password*/ "@" ")?"
"(" IP "|" ALNUM ")"
":" INT "(" WS STR ")?"
END, handle_upstream, NULL
},
{
BEGIN "(upstream4)" WS "(" IP "|" ALNUM ")" ":" INT "(" WS STR
@ -1100,24 +1103,33 @@ static int _handle_upstream(struct config_s* conf, const char* line,
regmatch_t match[], proxy_type type)
{
char *ip;
int port;
char *domain;
int port, mi = 3;
char *domain = 0, *user = 0, *pass = 0;
ip = get_string_arg (line, &match[2]);
if (match[mi].rm_so != -1)
user = get_string_arg (line, &match[mi]);
mi++;
if (match[mi].rm_so != -1)
pass = get_string_arg (line, &match[mi]);
mi++;
ip = get_string_arg (line, &match[mi]);
if (!ip)
return -1;
port = (int) get_long_arg (line, &match[7]);
mi += 5;
if (match[10].rm_so != -1) {
domain = get_string_arg (line, &match[10]);
if (domain) {
upstream_add (ip, port, domain, type, &conf->upstream_list);
safefree (domain);
}
} else {
upstream_add (ip, port, NULL, type, &conf->upstream_list);
}
port = (int) get_long_arg (line, &match[mi]);
mi += 3;
if (match[mi].rm_so != -1)
domain = get_string_arg (line, &match[mi]);
upstream_add (ip, port, domain, user, pass, type, &conf->upstream_list);
safefree (user);
safefree (pass);
safefree (domain);
safefree (ip);
return 0;
@ -1146,7 +1158,7 @@ static HANDLE_FUNC (handle_upstream_no)
if (!domain)
return -1;
upstream_add (NULL, 0, domain, HTTP_TYPE, &conf->upstream_list);
upstream_add (NULL, 0, domain, 0, 0, HTTP_TYPE, &conf->upstream_list);
safefree (domain);
return 0;

View File

@ -270,6 +270,17 @@ establish_http_connection (struct conn_s *connptr, struct request_s *request)
"Connection: close\r\n",
request->method, request->path,
request->host, portbuff);
} else if (connptr->upstream_proxy &&
connptr->upstream_proxy->type == HTTP_TYPE &&
connptr->upstream_proxy->ua.authstr) {
return write_message (connptr->server_fd,
"%s %s HTTP/1.0\r\n"
"Host: %s%s\r\n"
"Connection: close\r\n"
"Proxy-Authorization: Basic %s\r\n",
request->method, request->path,
request->host, portbuff,
connptr->upstream_proxy->ua.authstr);
} else {
return write_message (connptr->server_fd,
"%s %s HTTP/1.0\r\n"

View File

@ -27,6 +27,8 @@
#include "upstream.h"
#include "heap.h"
#include "log.h"
#include "base64.h"
#include "basicauth.h"
#ifdef UPSTREAM_SUPPORT
const char *
@ -44,6 +46,7 @@ proxy_type_name(proxy_type type)
* Construct an upstream struct from input data.
*/
static struct upstream *upstream_build (const char *host, int port, const char *domain,
const char *user, const char *pass,
proxy_type type)
{
char *ptr;
@ -57,8 +60,24 @@ static struct upstream *upstream_build (const char *host, int port, const char *
}
up->type = type;
up->host = up->domain = NULL;
up->host = up->domain = up->ua.user = up->pass = NULL;
up->ip = up->mask = 0;
if (user) {
if (type == HTTP_TYPE) {
char b[BASE64ENC_BYTES((256+2)-1) + 1];
ssize_t ret;
ret = basicauth_string(user, pass, b, sizeof b);
if (ret == 0) {
log_message (LOG_ERR,
"User / pass in upstream config too long");
return NULL;
}
up->ua.authstr = safestrdup (b);
} else {
up->ua.user = safestrdup (user);
up->pass = safestrdup (pass);
}
}
if (domain == NULL) {
if (!host || host[0] == '\0' || port < 1) {
@ -121,6 +140,8 @@ static struct upstream *upstream_build (const char *host, int port, const char *
return up;
fail:
safefree (up->ua.user);
safefree (up->pass);
safefree (up->host);
safefree (up->domain);
safefree (up);
@ -132,11 +153,12 @@ fail:
* Add an entry to the upstream list
*/
void upstream_add (const char *host, int port, const char *domain,
const char *user, const char *pass,
proxy_type type, struct upstream **upstream_list)
{
struct upstream *up;
up = upstream_build (host, port, domain, type);
up = upstream_build (host, port, domain, user, pass, type);
if (up == NULL) {
return;
}

View File

@ -36,6 +36,11 @@ struct upstream {
struct upstream *next;
char *domain; /* optional */
char *host;
union {
char *user;
char *authstr;
} ua;
char *pass;
int port;
in_addr_t ip, mask;
proxy_type type;
@ -44,6 +49,7 @@ struct upstream {
#ifdef UPSTREAM_SUPPORT
const char *proxy_type_name(proxy_type type);
extern void upstream_add (const char *host, int port, const char *domain,
const char *user, const char *pass,
proxy_type type, struct upstream **upstream_list);
extern struct upstream *upstream_get (char *host, struct upstream *up);
extern void free_upstream_list (struct upstream *up);