summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorrofl0r <retnyg@gmx.net>2018-02-23 20:21:32 +0000
committerrofl0r <rofl0r@users.noreply.github.com>2018-02-25 15:13:45 +0000
commitbf76aeeba1cf868ebe4d2f28976abb75c48031b0 (patch)
tree779316ce7d9bae67cbc54122d530c6f51d761289
parent4d9891e59e7c7ee77137fcdb3d02798af96811ff (diff)
implement HTTP basic auth for upstream proxies
loosely based on @valenbg1's code from PR #38 closes #38 closes #96
-rw-r--r--etc/tinyproxy.conf.in3
-rw-r--r--src/conf.c44
-rw-r--r--src/reqs.c11
-rw-r--r--src/upstream.c26
-rw-r--r--src/upstream.h6
5 files changed, 72 insertions, 18 deletions
diff --git a/etc/tinyproxy.conf.in b/etc/tinyproxy.conf.in
index c43266b..ac16efe 100644
--- a/etc/tinyproxy.conf.in
+++ b/etc/tinyproxy.conf.in
@@ -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"
diff --git a/src/conf.c b/src/conf.c
index 80bdab8..7f62172 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -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;
+
+ 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[2]);
+ 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;
diff --git a/src/reqs.c b/src/reqs.c
index 0e4e5f7..180b35a 100644
--- a/src/reqs.c
+++ b/src/reqs.c
@@ -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"
diff --git a/src/upstream.c b/src/upstream.c
index 91bf457..03a6b8e 100644
--- a/src/upstream.c
+++ b/src/upstream.c
@@ -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;
}
diff --git a/src/upstream.h b/src/upstream.h
index 7855214..9b664c8 100644
--- a/src/upstream.h
+++ b/src/upstream.h
@@ -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);