summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile12
-rw-r--r--authdb.c23
-rw-r--r--authdb.h1
-rw-r--r--squark-auth-ip.c185
-rw-r--r--squark-auth-snmp.c2
-rw-r--r--squark-filter.c9
6 files changed, 216 insertions, 16 deletions
diff --git a/Makefile b/Makefile
index 09c58d4..7c69728 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-TARGETS=squark-auth-snmp squark-filter squarkdb.so
+TARGETS=squark-auth-snmp squark-auth-ip squark-filter squarkdb.so
NETSNMP_CFLAGS:=$(shell net-snmp-config --cflags)
NETSNMP_LIBS:=$(shell net-snmp-config --libs)
@@ -9,17 +9,21 @@ CMPH_LIBS:=$(shell pkg-config --libs cmph)
CC=gcc
CFLAGS=-g -I. $(NETSNMP_CFLAGS) $(LUA_CFLAGS) $(CMPH_CFLAGS) -std=gnu99 -D_GNU_SOURCE -Wall
+LIBS+=-lrt
all: $(TARGETS)
squark-auth-snmp: squark-auth-snmp.o blob.o addr.o
- $(CC) -o $@ $^ $(NETSNMP_LIBS)
+ $(CC) -o $@ $^ $(NETSNMP_LIBS) $(LIBS)
+
+squark-auth-ip: squark-auth-ip.o authdb.o blob.o addr.o
+ $(CC) -o $@ $^ $(LIBS)
squark-filter: squark-filter.o filterdb.o authdb.o blob.o addr.o
- $(CC) -o $@ $^ $(CMPH_LIBS) -lrt
+ $(CC) -o $@ $^ $(CMPH_LIBS) $(LIBS)
squarkdb.so: lua-squarkdb.o filterdb.o blob.o
- $(CC) -shared -o $@ $^ $(LUA_LIBS) $(CMPH_LIBS)
+ $(CC) -shared -o $@ $^ $(LUA_LIBS) $(CMPH_LIBS) $(LIBS)
clean:
rm $(OBJS1) $(TARGETS)
diff --git a/authdb.c b/authdb.c
index 452c94e..77620a3 100644
--- a/authdb.c
+++ b/authdb.c
@@ -9,8 +9,11 @@
#include "addr.h"
#include "blob.h"
+#define ALIGN(s,a) (((s) + a - 1) & ~(a - 1))
+
#define AUTHDB_IP_PER_ME 256
#define AUTHDB_LOGOFF_PERIOD (15*60) /* 15 mins */
+#define AUTHDB_SHM_SIZE ALIGN(sizeof(struct authdb_entry[AUTHDB_IP_PER_ME]), 4096)
static struct authdb_map_entry *authdb_me_open(sockaddr_any *addr, int create)
{
@@ -32,13 +35,12 @@ static struct authdb_map_entry *authdb_me_open(sockaddr_any *addr, int create)
if (fd < 0)
return NULL;
- if (create &&
- ftruncate(fd, sizeof(struct authdb_entry[AUTHDB_IP_PER_ME])) < 0) {
+ if (create && ftruncate(fd, AUTHDB_SHM_SIZE) < 0) {
close(fd);
return NULL;
}
- base = mmap(NULL, sizeof(struct authdb_entry[AUTHDB_IP_PER_ME]),
+ base = mmap(NULL, AUTHDB_SHM_SIZE,
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
close(fd);
@@ -47,7 +49,7 @@ static struct authdb_map_entry *authdb_me_open(sockaddr_any *addr, int create)
me = malloc(sizeof(*me));
if (me == NULL) {
- munmap(base, sizeof(struct authdb_entry[AUTHDB_IP_PER_ME]));
+ munmap(base, AUTHDB_SHM_SIZE);
return NULL;
}
@@ -60,7 +62,7 @@ static struct authdb_map_entry *authdb_me_open(sockaddr_any *addr, int create)
static void authdb_me_free(struct authdb_map_entry *me)
{
- munmap(me->entries, sizeof(struct authdb_entry[AUTHDB_IP_PER_ME]));
+ munmap(me->entries, AUTHDB_SHM_SIZE);
free(me);
}
@@ -130,7 +132,7 @@ static uint32_t authdb_entry_checksum(struct authdb_entry *entry)
void *authdb_get(struct authdb *adb, sockaddr_any *addr, struct authdb_entry *entry, int create)
{
struct authdb_map_entry *me;
- int hash, e, i;
+ unsigned int hash, e, i;
sockaddr_any baseaddr;
blob_t b;
@@ -156,7 +158,7 @@ void *authdb_get(struct authdb *adb, sockaddr_any *addr, struct authdb_entry *en
}
for (i = 0; i < 3; i++) {
- memcpy(&me->entries[e], entry, sizeof(struct authdb_entry));
+ memcpy(entry, &me->entries[e], sizeof(struct authdb_entry));
if (entry->u.checksum == 0 && entry->u.login_time == 0)
return &me->entries[e];
if (entry->u.checksum == authdb_entry_checksum(entry))
@@ -221,3 +223,10 @@ void authdb_commit_login(void *token, struct authdb_entry *e, time_t now)
authdb_set(token, e);
}
+
+void authdb_commit_override(void *token, struct authdb_entry *e, time_t now)
+{
+ struct authdb_entry *mme = token;
+
+ mme->u.override_time = now;
+}
diff --git a/authdb.h b/authdb.h
index 5a3f3c4..d8bec04 100644
--- a/authdb.h
+++ b/authdb.h
@@ -46,5 +46,6 @@ void authdb_clear_entry(struct authdb_entry *entry);
int authdb_set(void *token, struct authdb_entry *entry);
int authdb_check_login(void *token, struct authdb_entry *e, blob_t username, time_t now);
void authdb_commit_login(void *token, struct authdb_entry *e, time_t now);
+void authdb_commit_override(void *token, struct authdb_entry *entry, time_t now);
#endif
diff --git a/squark-auth-ip.c b/squark-auth-ip.c
new file mode 100644
index 0000000..dff4f8d
--- /dev/null
+++ b/squark-auth-ip.c
@@ -0,0 +1,185 @@
+/* squark-auth-ip.c - Squid User Authentication and Rating Kit
+ * An external acl helper for Squid which collects authentication
+ * information about an IP-address from local shared memory database.
+ *
+ * Copyright (C) 2010 Timo Teräs <timo.teras@iki.fi>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation. See http://www.gnu.org/ for details.
+ */
+
+#include <time.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "blob.h"
+#include "authdb.h"
+
+#define DO_LOGIN -1
+#define DO_OVERRIDE -2
+#define DO_PRINT -3
+
+static int running = 1;
+static struct authdb adb;
+static blob_t space = BLOB_STR_INIT(" ");
+static blob_t lf = BLOB_STR_INIT("\n");
+static time_t now;
+
+static void handle_line(blob_t line)
+{
+ char reply[128];
+ blob_t b, id, ipaddr;
+ struct authdb_entry entry;
+ sockaddr_any addr;
+ void *token;
+ int auth_ok = 0;
+
+ id = blob_pull_cspn(&line, space);
+ blob_pull_spn(&line, space);
+ ipaddr = blob_pull_cspn(&line, space);
+
+ if (addr_parse(ipaddr, &addr)) {
+ token = authdb_get(&adb, &addr, &entry, 1);
+
+ if (authdb_check_login(token, &entry, BLOB_NULL, now))
+ auth_ok = 1;
+ }
+
+ b = BLOB_BUF(reply);
+ blob_push(&b, id);
+ if (auth_ok) {
+ blob_push(&b, BLOB_STR(" OK user="));
+ blob_push(&b, BLOB_STRLEN(entry.p.login_name));
+ blob_push(&b, BLOB_PTR_LEN("\n", 1));
+ } else {
+ blob_push(&b, BLOB_STR(" ERR\n"));
+ }
+
+ b = blob_pushed(BLOB_BUF(reply), b);
+ write(STDOUT_FILENO, b.ptr, b.len);
+}
+
+static void read_input(void)
+{
+ static char buffer[256];
+ static blob_t left;
+
+ blob_t b, line;
+ int r;
+
+ if (blob_is_null(left))
+ left = BLOB_BUF(buffer);
+
+ r = read(STDIN_FILENO, left.ptr, left.len);
+ if (r < 0)
+ return;
+ if (r == 0) {
+ running = 0;
+ return;
+ }
+ left.ptr += r;
+ left.len -= r;
+
+ now = time(NULL);
+
+ b = blob_pushed(BLOB_BUF(buffer), left);
+ do {
+ line = blob_pull_cspn(&b, lf);
+ if (!blob_pull_matching(&b, lf))
+ return;
+
+ handle_line(line);
+
+ if (b.len) {
+ memcpy(buffer, b.ptr, b.len);
+ b.ptr = buffer;
+ }
+ left = BLOB_PTR_LEN(buffer + b.len, sizeof(buffer) - b.len);
+ } while (b.len);
+}
+
+int main(int argc, char **argv)
+{
+ int opt;
+ sockaddr_any ipaddr = { .any.sa_family = AF_UNSPEC };
+ blob_t ip = BLOB_NULL, username = BLOB_NULL;
+
+ while ((opt = getopt(argc, argv, "i:u:olp")) != -1) {
+ switch (opt) {
+ case 'i':
+ ip = BLOB_STRLEN(optarg);
+ if (!addr_parse(ip, &ipaddr)) {
+ fprintf(stderr, "'%s' does not look like IP-address\n",
+ optarg);
+ return 1;
+ }
+ break;
+ case 'u':
+ username = BLOB_STRLEN(optarg);
+ break;
+ case 'o':
+ running = DO_OVERRIDE;
+ break;
+ case 'l':
+ running = DO_LOGIN;
+ break;
+ case 'p':
+ running = DO_PRINT;
+ break;
+ }
+ }
+
+ now = time(NULL);
+ authdb_open(&adb);
+
+ if (running < 0) {
+ struct authdb_entry entry;
+ void *token;
+ char buf1[64], buf2[64];
+
+ if (ipaddr.any.sa_family == AF_UNSPEC) {
+ fprintf(stderr, "IP-address not specified\n");
+ return 2;
+ }
+
+ token = authdb_get(&adb, &ipaddr, &entry, 1);
+ if (token == NULL) {
+ fprintf(stderr, "Failed to get authdb record\n");
+ return 3;
+ }
+
+ switch (running) {
+ case DO_LOGIN:
+ if (blob_is_null(username)) {
+ fprintf(stderr, "Username not specified\n");
+ return 2;
+ }
+ authdb_clear_entry(&entry);
+ memcpy(entry.p.login_name, username.ptr, username.len);
+ authdb_commit_login(token, &entry, now);
+ break;
+ case DO_OVERRIDE:
+ if (authdb_check_login(token, &entry, username, now))
+ authdb_commit_override(token, &entry, now);
+ break;
+ case DO_PRINT:
+ fprintf(stdout,
+ "IP-address: %s\n"
+ "Username: %s\n"
+ "Login time: %s"
+ "Override time: %s",
+ ip.ptr,
+ username.ptr,
+ entry.u.login_time ? ctime_r(&entry.u.login_time, buf1) : "<none>\n",
+ entry.u.override_time ? ctime_r(&entry.u.override_time, buf2) : "<none>\n");
+ break;
+ }
+ } else {
+ while (running)
+ read_input();
+ }
+
+ authdb_close(&adb);
+}
diff --git a/squark-auth-snmp.c b/squark-auth-snmp.c
index f386ab3..817a466 100644
--- a/squark-auth-snmp.c
+++ b/squark-auth-snmp.c
@@ -1,4 +1,4 @@
-/* squark-auth.c - Squid User Authentication and Rating Kit
+/* squark-auth-snmp.c - Squid User Authentication and Rating Kit
* An external acl helper for Squid which collects authentication
* information about an IP-address from switches via SNMP.
*
diff --git a/squark-filter.c b/squark-filter.c
index 7a005e1..236dad4 100644
--- a/squark-filter.c
+++ b/squark-filter.c
@@ -23,6 +23,8 @@
#include "filterdb.h"
#include "authdb.h"
+#define FILTER_OVERRIDE_TIMEOUT (15*60)
+
static int running = 1;
static uint64_t banned_categories = 0;
static const blob_t dash = BLOB_STR_INIT("-");
@@ -396,10 +398,9 @@ static void read_input(struct sqdb *db)
if (!blob_is_null(url) &&
addr_parse(ipaddr, &addr)) {
/* valid request, handle it */
- if (url_parse(url, &nfo)) {
- url_print(&nfo);
+ if (url_parse(url, &nfo))
category = url_classify(&nfo, db);
- } else
+ else
category = 0;
token = authdb_get(&adb, &addr, &entry, 1);
@@ -421,7 +422,7 @@ static void read_input(struct sqdb *db)
send_redirect(redirect_login_page, id, url, BLOB_STR("auth"), username);
} else if (((1ULL << category) & entry.p.block_categories) &&
(entry.u.override_time < now ||
- entry.u.override_time + 15*60 > now ||
+ entry.u.override_time + FILTER_OVERRIDE_TIMEOUT > now ||
((1ULL << category) & entry.p.hard_block_categories))) {
send_redirect(redirect_banned_page, id, url, get_category_name(db, category), username);
} else