diff options
author | Timo Teräs <timo.teras@iki.fi> | 2010-11-07 00:47:39 +0200 |
---|---|---|
committer | Timo Teräs <timo.teras@iki.fi> | 2010-11-07 00:47:39 +0200 |
commit | 25593b5e6fea76ed7c08db586924032c0810c27e (patch) | |
tree | b632534eb96978ad620fee1e5a9a5d280e0b191e /authdb.c | |
parent | e0450bd60a30ca944c16f84ee195463fd4aab653 (diff) | |
download | squark-25593b5e6fea76ed7c08db586924032c0810c27e.tar.bz2 squark-25593b5e6fea76ed7c08db586924032c0810c27e.tar.xz |
squark: reorganize sources to src directory
Diffstat (limited to 'authdb.c')
-rw-r--r-- | authdb.c | 364 |
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); -} |