From 5bc7fd8f1e41365677eb6787cb7d2a6dea62ee0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Wed, 1 Sep 2010 15:11:57 +0300 Subject: auth-ip: introduce helper tool for authdb management fix also some authdb bugs, and make it actually usable. --- Makefile | 12 ++-- authdb.c | 23 +++++-- authdb.h | 1 + squark-auth-ip.c | 185 +++++++++++++++++++++++++++++++++++++++++++++++++++++ squark-auth-snmp.c | 2 +- squark-filter.c | 9 +-- 6 files changed, 216 insertions(+), 16 deletions(-) create mode 100644 squark-auth-ip.c 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 + * 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 +#include +#include + +#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) : "\n", + entry.u.override_time ? ctime_r(&entry.u.override_time, buf2) : "\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 -- cgit v1.2.3