summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorrofl0r <retnyg@gmx.net>2017-11-16 12:04:37 +0000
committerrofl0r <rofl0r@users.noreply.github.com>2018-02-06 16:57:02 +0000
commit8db511b9bff5dfa61a9448659e28ce54d9aa8869 (patch)
treedfa874e224346c8453c3b24838481729de79c505 /src
parent1ebfd2a2d165bcd9bcebbeb907faf02cb3d54bae (diff)
add support for basic HTTP authentication
using the "BasicAuth" keyword in tinyproxy.conf. base64 code was written by myself and taken from my own library "libulz". for this purpose it is relicensed under the usual terms of the tinyproxy license.
Diffstat (limited to 'src')
-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
6 files changed, 205 insertions, 0 deletions
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.