summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--etc/tinyproxy.conf.in5
-rw-r--r--src/Makefile.am1
-rw-r--r--src/basicauth.c122
-rw-r--r--src/basicauth.h31
-rw-r--r--src/conf.c25
-rw-r--r--src/conf.h1
-rw-r--r--src/reqs.c25
7 files changed, 210 insertions, 0 deletions
diff --git a/etc/tinyproxy.conf.in b/etc/tinyproxy.conf.in
index bca638a..c43266b 100644
--- a/etc/tinyproxy.conf.in
+++ b/etc/tinyproxy.conf.in
@@ -215,6 +215,11 @@ MaxRequestsPerChild 0
#
Allow 127.0.0.1
+# BasicAuth: HTTP "Basic Authentication" for accessing the proxy.
+# If there are any entries specified, access is only granted for authenticated
+# users.
+#BasicAuth user password
+
#
# AddHeader: Adds the specified headers to outgoing HTTP requests that
# Tinyproxy makes. Note that this option will not work for HTTPS
diff --git a/src/Makefile.am b/src/Makefile.am
index c42b0dd..60fda2c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -47,6 +47,7 @@ tinyproxy_SOURCES = \
utils.c utils.h \
vector.c vector.h \
upstream.c upstream.h \
+ basicauth.c basicauth.h \
connect-ports.c connect-ports.h
EXTRA_tinyproxy_SOURCES = filter.c filter.h \
diff --git a/src/basicauth.c b/src/basicauth.c
new file mode 100644
index 0000000..ddc6e6e
--- /dev/null
+++ b/src/basicauth.c
@@ -0,0 +1,122 @@
+/* tinyproxy - A fast light-weight HTTP proxy
+ * This file: Copyright (C) 2016-2017 rofl0r
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "main.h"
+#include "basicauth.h"
+
+#include "conns.h"
+#include "heap.h"
+#include "html-error.h"
+#include "log.h"
+#include "conf.h"
+
+/* calculates number of bytes base64-encoded stream of N bytes will take. */
+#define BASE64ENC_BYTES(N) (((N+2)/3)*4)
+
+static const char base64_tbl[64] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+/* my own base64 impl (taken from libulz) */
+static void base64enc(char *dst, const void* src, size_t count)
+{
+ unsigned const char *s = src;
+ char* d = dst;
+ while(count) {
+ int i = 0, n = *s << 16;
+ s++;
+ count--;
+ if(count) {
+ n |= *s << 8;
+ s++;
+ count--;
+ i++;
+ }
+ if(count) {
+ n |= *s;
+ s++;
+ count--;
+ i++;
+ }
+ *d++ = base64_tbl[(n >> 18) & 0x3f];
+ *d++ = base64_tbl[(n >> 12) & 0x3f];
+ *d++ = i ? base64_tbl[(n >> 6) & 0x3f] : '=';
+ *d++ = i == 2 ? base64_tbl[n & 0x3f] : '=';
+ }
+ *d = 0;
+}
+
+/*
+ * Add entry to the basicauth list
+ */
+void basicauth_add (vector_t authlist,
+ const char *user, const char *pass)
+{
+ char tmp[256+2];
+ char b[BASE64ENC_BYTES((sizeof tmp)-1) + 1];
+ int l;
+ size_t bl;
+
+ if (user == NULL || pass == NULL) {
+ log_message (LOG_WARNING,
+ "Illegal basicauth rule: missing user or pass");
+ return;
+ }
+
+ l = snprintf(tmp, sizeof tmp, "%s:%s", user, pass);
+
+ if(l >= (ssize_t) sizeof tmp) {
+ log_message (LOG_WARNING,
+ "User / pass in basicauth rule too long");
+ return;
+ }
+
+ base64enc(b, tmp, l);
+ bl = BASE64ENC_BYTES(l) + 1;
+
+ if (vector_append(authlist, b, bl) == -ENOMEM) {
+ log_message (LOG_ERR,
+ "Unable to allocate memory in basicauth_add()");
+ return;
+ }
+
+ log_message (LOG_INFO,
+ "Added basic auth user : %s", user);
+}
+
+/*
+ * Check if a user/password combination (encoded as base64)
+ * is in the basicauth list.
+ * return 1 on success, 0 on failure.
+ */
+int basicauth_check (vector_t authlist, const char *authstring)
+{
+ ssize_t vl, i;
+ size_t al, el;
+ const char* entry;
+
+ vl = vector_length (authlist);
+ if (vl == -EINVAL) return 0;
+
+ al = strlen (authstring);
+ for (i = 0; i < vl; i++) {
+ entry = vector_getentry (authlist, i, &el);
+ if (strncmp (authstring, entry, al) == 0)
+ return 1;
+ }
+ return 0;
+}
diff --git a/src/basicauth.h b/src/basicauth.h
new file mode 100644
index 0000000..e9366bb
--- /dev/null
+++ b/src/basicauth.h
@@ -0,0 +1,31 @@
+/* tinyproxy - A fast light-weight HTTP proxy
+ * Copyright (C) 2005 Robert James Kaes <rjkaes@users.sourceforge.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/* See 'basicauth.c' for detailed information. */
+
+#ifndef TINYPROXY_BASICAUTH_H
+#define TINYPROXY_BASICAUTH_H
+
+#include "vector.h"
+
+extern void basicauth_add (vector_t authlist,
+ const char *user, const char *pass);
+
+extern int basicauth_check (vector_t authlist, const char *authstring);
+
+#endif
diff --git a/src/conf.c b/src/conf.c
index ca46930..4ee209d 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -36,6 +36,7 @@
#include "reverse-proxy.h"
#include "upstream.h"
#include "connect-ports.h"
+#include "basicauth.h"
/*
* The configuration directives are defined in the structure below. Each
@@ -116,6 +117,7 @@ static HANDLE_FUNC (handle_nop)
} /* do nothing function */
static HANDLE_FUNC (handle_allow);
+static HANDLE_FUNC (handle_basicauth);
static HANDLE_FUNC (handle_anonymous);
static HANDLE_FUNC (handle_bind);
static HANDLE_FUNC (handle_bindsame);
@@ -232,6 +234,7 @@ struct {
handle_deny),
STDCONF ("bind", "(" IP "|" IPV6 ")", handle_bind),
/* other */
+ STDCONF ("basicauth", ALNUM WS ALNUM, handle_basicauth),
STDCONF ("errorfile", INT WS STR, handle_errorfile),
STDCONF ("addheader", STR WS STR, handle_addheader),
@@ -299,6 +302,7 @@ static void free_config (struct config_s *conf)
safefree (conf->user);
safefree (conf->group);
vector_delete(conf->listen_addrs);
+ vector_delete(conf->basicauth_list);
#ifdef FILTER_ENABLE
safefree (conf->filter);
#endif /* FILTER_ENABLE */
@@ -1000,6 +1004,27 @@ static HANDLE_FUNC (handle_loglevel)
return -1;
}
+static HANDLE_FUNC (handle_basicauth)
+{
+ char *user, *pass;
+ user = get_string_arg(line, &match[2]);
+ if (!user)
+ return -1;
+ pass = get_string_arg(line, &match[3]);
+ if (!pass) {
+ safefree (user);
+ return -1;
+ }
+ if (!conf->basicauth_list) {
+ conf->basicauth_list = vector_create ();
+ }
+
+ basicauth_add (conf->basicauth_list, user, pass);
+ safefree (user);
+ safefree (pass);
+ return 0;
+}
+
#ifdef FILTER_ENABLE
static HANDLE_FUNC (handle_filter)
{
diff --git a/src/conf.h b/src/conf.h
index 0fb4226..beb2b01 100644
--- a/src/conf.h
+++ b/src/conf.h
@@ -37,6 +37,7 @@ typedef struct {
* Hold all the configuration time information.
*/
struct config_s {
+ vector_t basicauth_list;
char *logf_name;
char *config_file;
unsigned int syslog; /* boolean */
diff --git a/src/reqs.c b/src/reqs.c
index 86039bc..83fecf3 100644
--- a/src/reqs.c
+++ b/src/reqs.c
@@ -48,6 +48,7 @@
#include "upstream.h"
#include "connect-ports.h"
#include "conf.h"
+#include "basicauth.h"
/*
* Maximum length of a HTTP line
@@ -1562,6 +1563,30 @@ void handle_connection (int fd)
goto fail;
}
+ if (config.basicauth_list != NULL) {
+ ssize_t len;
+ char *authstring;
+ int failure = 1;
+ len = hashmap_entry_by_key (hashofheaders, "proxy-authorization",
+ (void **) &authstring);
+ if (len > 0 &&
+ /* currently only "basic" auth supported */
+ (strncmp(authstring, "Basic ", 6) == 0 ||
+ strncmp(authstring, "basic ", 6) == 0) &&
+ basicauth_check (config.basicauth_list, authstring + 6) == 1)
+ failure = 0;
+ if(failure) {
+ update_stats (STAT_DENIED);
+ indicate_http_error (connptr, 403, "Access denied",
+ "detail",
+ "The administrator of this proxy has not configured "
+ "it to service requests from you.",
+ NULL);
+ goto fail;
+ }
+ hashmap_remove (hashofheaders, "proxy-authorization");
+ }
+
/*
* Add any user-specified headers (AddHeader directive) to the
* outgoing HTTP request.