summaryrefslogtreecommitdiffstats
path: root/authdb.c
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2010-11-07 00:47:39 +0200
committerTimo Teräs <timo.teras@iki.fi>2010-11-07 00:47:39 +0200
commit25593b5e6fea76ed7c08db586924032c0810c27e (patch)
treeb632534eb96978ad620fee1e5a9a5d280e0b191e /authdb.c
parente0450bd60a30ca944c16f84ee195463fd4aab653 (diff)
downloadsquark-25593b5e6fea76ed7c08db586924032c0810c27e.tar.bz2
squark-25593b5e6fea76ed7c08db586924032c0810c27e.tar.xz
squark: reorganize sources to src directory
Diffstat (limited to 'authdb.c')
-rw-r--r--authdb.c364
1 files changed, 0 insertions, 364 deletions
diff --git a/authdb.c b/authdb.c
deleted file mode 100644
index e6e71c4..0000000
--- a/authdb.c
+++ /dev/null
@@ -1,364 +0,0 @@
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <malloc.h>
-#include <sched.h>
-#include <fcntl.h>
-#include <ctype.h>
-#include <time.h>
-#include <grp.h>
-
-#include "authdb.h"
-#include "filterdb.h"
-#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)
-{
- int oflag, fd;
- char name[64], buf[256];
- blob_t b = BLOB_BUF(name);
- void *base;
- struct authdb_map_entry *me;
- struct group grp, *res;
-
- blob_push(&b, BLOB_STR("squark-auth-"));
- blob_push_hexdump(&b, addr_get_hostaddr_blob(addr));
- blob_push_byte(&b, 0);
-
- oflag = O_RDWR;
- if (create)
- oflag |= O_CREAT;
-
- fd = shm_open(name, oflag, 0660);
- if (fd < 0)
- return NULL;
-
- if (ftruncate(fd, AUTHDB_SHM_SIZE) < 0) {
- close(fd);
- return NULL;
- }
-
- getgrnam_r("squark", &grp, buf, sizeof(buf), &res);
- if (res != NULL) {
- fchown(fd, -1, res->gr_gid);
- fchmod(fd, 0660);
- }
-
- base = mmap(NULL, AUTHDB_SHM_SIZE,
- PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
- close(fd);
-
- if (base == MAP_FAILED)
- return NULL;
-
- me = malloc(sizeof(*me));
- if (me == NULL) {
- munmap(base, AUTHDB_SHM_SIZE);
- return NULL;
- }
-
- me->next = NULL;
- me->baseaddr = *addr;
- me->entries = base;
-
- return me;
-}
-
-static void authdb_me_free(struct authdb_map_entry *me)
-{
- munmap(me->entries, AUTHDB_SHM_SIZE);
- free(me);
-}
-
-int authdb_open(struct authdb *adb, struct authdb_config *cfg, struct sqdb *db)
-{
- memset(adb, 0, sizeof(*adb));
- memset(cfg, 0, sizeof(*cfg));
- cfg->db = db;
- return adbc_refresh(cfg, time(NULL));
-}
-
-void authdb_close(struct authdb *adb)
-{
- struct authdb_map_entry *c, *n;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(adb->hash_bucket); i++) {
- for (c = adb->hash_bucket[i]; c != NULL; c = n) {
- n = c->next;
- authdb_me_free(c);
- }
- }
-}
-
-static unsigned int MurmurHash2(const void * key, int len, unsigned int seed)
-{
- // 'm' and 'r' are mixing constants generated offline.
- // They're not really 'magic', they just happen to work well.
- const unsigned int m = 0x5bd1e995;
- const int r = 24;
- unsigned int h = seed ^ len;
- const unsigned char * data = (const unsigned char *)key;
-
- while(len >= 4)
- {
- unsigned int k = *(unsigned int *)data;
-
- k *= m;
- k ^= k >> r;
- k *= m;
-
- h *= m;
- h ^= k;
-
- data += 4;
- len -= 4;
- }
-
- switch(len)
- {
- case 3: h ^= data[2] << 16;
- case 2: h ^= data[1] << 8;
- case 1: h ^= data[0];
- h *= m;
- }
-
- h ^= h >> 13;
- h *= m;
- h ^= h >> 15;
-
- return h;
-}
-
-static uint32_t authdb_entry_checksum(struct authdb_entry *entry)
-{
- return MurmurHash2(&entry->p, sizeof(entry->p), 0);
-}
-
-void *authdb_get(struct authdb *adb, sockaddr_any *addr, struct authdb_entry *entry, int create)
-{
- struct authdb_map_entry *me;
- unsigned int hash, e, i;
- sockaddr_any baseaddr;
- blob_t b;
-
- baseaddr = *addr;
- b = addr_get_hostaddr_blob(&baseaddr);
- if (b.len < 4)
- return NULL;
-
- e = (unsigned char) b.ptr[0];
- b.ptr[0] = 0x00;
-
- hash = b.ptr[1] + b.ptr[2] + b.ptr[3];
- hash %= ARRAY_SIZE(adb->hash_bucket);
-
- for (me = adb->hash_bucket[hash]; me != NULL; me = me->next) {
- if (addr_cmp(&baseaddr, &me->baseaddr) == 0)
- break;
- }
- if (me == NULL) {
- me = authdb_me_open(&baseaddr, create);
- if (me == NULL)
- return NULL;
- me->next = adb->hash_bucket[hash];
- adb->hash_bucket[hash] = me;
- }
-
- for (i = 0; i < 3; i++) {
- memcpy(entry, &me->entries[e], sizeof(struct authdb_entry));
- if (entry->checksum == 0 && entry->p.login_time == 0)
- return &me->entries[e];
- if (entry->checksum == authdb_entry_checksum(entry))
- return &me->entries[e];
- sched_yield();
- }
-
- authdb_clear_entry(entry);
-
- return &me->entries[e];
-}
-
-int authdb_set(void *token, struct authdb_entry *entry)
-{
- struct authdb_entry *mme = token;
- uint32_t checksum = entry->checksum;
-
- entry->checksum = authdb_entry_checksum(entry);
- if (mme->checksum != checksum)
- return 0;
-
- mme->checksum = ~0;
- memcpy(mme, entry, sizeof(*entry));
-
- return 1;
-}
-
-int authdb_check_login(void *token, struct authdb_entry *e, blob_t username, time_t now)
-{
- struct authdb_entry *mme = token;
-
- /* check username */
- if (!blob_is_null(username) &&
- blob_cmp(username, BLOB_STRLEN(e->p.login_name)) != 0)
- return 0;
-
- /* and dates */
- if (now > e->last_activity_time + AUTHDB_LOGOFF_PERIOD)
- return 0;
-
- /* and that no one clobbered the entry */
- if (mme->checksum != e->checksum)
- return 0;
-
- /* refresh last activity */
- mme->last_activity_time = now;
-
- return 1;
-}
-
-void authdb_clear_entry(struct authdb_entry *entry)
-{
- uint32_t checksum = entry->checksum;
-
- memset(entry, 0, sizeof(*entry));
- entry->checksum = checksum;
-}
-
-void authdb_commit_login(void *token, struct authdb_entry *e, time_t now, struct authdb_config *cfg)
-{
- e->p.block_categories = cfg->block_categories;
- e->p.hard_block_categories = cfg->hard_block_categories;
- e->p.login_time = now;
- e->last_activity_time = now;
- e->override_time = 0;
-
- authdb_set(token, e);
-}
-
-void authdb_commit_logout(void *token)
-{
- memset(token, 0, sizeof(struct authdb_entry));
-}
-
-void authdb_commit_override(void *token, struct authdb_entry *e, time_t now)
-{
- struct authdb_entry *mme = token;
-
- mme->override_time = now;
-}
-
-static blob_t read_word(FILE *in, int *lineno, blob_t b)
-{
- int ch, i, comment = 0;
- blob_t r;
-
- ch = fgetc(in);
- while (1) {
- if (ch == EOF)
- return BLOB_NULL;
- if (ch == '#')
- comment = 1;
- if (!comment && !isspace(ch))
- break;
- if (ch == '\n') {
- (*lineno)++;
- comment = 0;
- }
- ch = fgetc(in);
- }
-
- r.ptr = b.ptr;
- r.len = 0;
- for (i = 0; i < b.len-1 && !isspace(ch); i++, r.len++) {
- r.ptr[i] = ch;
- ch = fgetc(in);
- if (ch == EOF)
- break;
- if (ch == '\n')
- (*lineno)++;
- }
-
- return r;
-}
-
-static int find_category_id(struct sqdb *db, blob_t cat)
-{
- uint32_t size, *ptr;
- int i;
-
- ptr = sqdb_section_get(db, SQDB_SECTION_CATEGORIES, &size);
- if (ptr == NULL)
- return -1;
-
- size /= sizeof(uint32_t);
- for (i = 0; i < size; i++)
- if (blob_cmp(cat, sqdb_get_string_literal(db, ptr[i])) == 0)
- return i;
-
- return -1;
-}
-
-static inline uint64_t to_category(struct sqdb *db, blob_t c)
-{
- int category;
-
- category = find_category_id(db, c);
- if (category >= 0)
- return 1ULL << category;
-
- fprintf(stderr, "WARNING: unknown category '%.*s'\n",
- c.len, c.ptr);
- return 0;
-}
-
-int adbc_refresh(struct authdb_config *cfg, time_t now)
-{
- FILE *in;
- int lineno = 1;
- char word1[64], word2[64];
- blob_t b, p;
- struct stat st;
-
- if (cfg->last_check != 0 && cfg->last_check + 2*60 > now)
- return 0;
-
- if (stat("/etc/squark/filter.conf", &st) != 0)
- return -1;
-
- if (cfg->last_change == st.st_ctime)
- return 0;
-
- /* check timestamp */
-
- in = fopen("/etc/squark/filter.conf", "r");
- if (in == NULL)
- return -1;
-
- cfg->block_categories = 0;
- cfg->hard_block_categories = 0;
- while (1) {
- b = read_word(in, &lineno, BLOB_BUF(word1));
- if (blob_is_null(b))
- break;
-
- p = read_word(in, &lineno, BLOB_BUF(word2));
- if (blob_cmp(b, BLOB_STR("redirect_path")) == 0) {
- cfg->redirect_url_base = blob_dup(p);
- } else if (blob_cmp(b, BLOB_STR("forbid")) == 0) {
- cfg->hard_block_categories |= to_category(cfg->db, p);
- } else if (blob_cmp(b, BLOB_STR("warn")) == 0) {
- cfg->block_categories |= to_category(cfg->db, p);
- }
- }
- cfg->block_categories |= cfg->hard_block_categories;
-
- fclose(in);
-}