Mercurial > dovecot > original-hg > dovecot-1.2
view src/auth/cookie.c @ 0:3b1985cbc908 HEAD
Initial revision
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Fri, 09 Aug 2002 12:15:38 +0300 |
parents | |
children | 82b7de533f98 |
line wrap: on
line source
/* Copyright (C) 2002 Timo Sirainen */ #include "common.h" #include "ioloop.h" #include "hash.h" #include "cookie.h" #include "randgen.h" #include <unistd.h> #include <fcntl.h> /* 30 seconds should be more than enough */ #define COOKIE_TIMEOUT 30 typedef struct _CookieList CookieList; struct _CookieList { CookieList *next; time_t created; CookieData *data; }; static HashTable *cookies; static CookieList *oldest_cookie, **next_cookie; static Timeout to; /* a char* hash function from ASU -- from glib */ static unsigned int cookie_hash(const void *p) { const unsigned char *s = p; unsigned int i, g, h = 0; for (i = 0; i < AUTH_COOKIE_SIZE; i++) { h = (h << 4) + s[i]; if ((g = h & 0xf0000000UL)) { h = h ^ (g >> 24); h = h ^ g; } } return h; } static int cookie_cmp(const void *p1, const void *p2) { int i, ret; for (i = 0; i < AUTH_COOKIE_SIZE; i++) { ret = ((unsigned char *) p1)[i] - ((unsigned char *) p2)[i]; if (ret != 0) return ret; } return 0; } void cookie_add(CookieData *data) { CookieList *list; do { random_fill(data->cookie, AUTH_COOKIE_SIZE); } while (hash_lookup(cookies, data->cookie)); /* add to linked list */ list = i_new(CookieList, 1); list->created = ioloop_time; list->data = data; *next_cookie = list; next_cookie = &list->next; /* add to hash */ hash_insert(cookies, data->cookie, data); } static void cookie_destroy(unsigned char cookie[AUTH_COOKIE_SIZE], int free_data) { CookieList **pos, *list; hash_remove(cookies, cookie); list = NULL; for (pos = &oldest_cookie; *pos != NULL; pos = &(*pos)->next) { if (cookie_cmp((*pos)->data->cookie, cookie) == 0) { list = *pos; *pos = list->next; break; } } i_assert(list != NULL); if (list->next == NULL) next_cookie = pos; if (free_data) list->data->free(list->data); i_free(list); } CookieData *cookie_lookup(unsigned char cookie[AUTH_COOKIE_SIZE]) { return hash_lookup(cookies, cookie); } void cookie_remove(unsigned char cookie[AUTH_COOKIE_SIZE]) { cookie_destroy(cookie, TRUE); } CookieData *cookie_lookup_and_remove(unsigned char cookie[AUTH_COOKIE_SIZE]) { CookieData *data; data = hash_lookup(cookies, cookie); if (data != NULL) cookie_destroy(cookie, FALSE); return data; } static void cookie_timeout(void *user_data __attr_unused__, Timeout timeout __attr_unused__) { time_t remove_time; remove_time = ioloop_time - COOKIE_TIMEOUT; while (oldest_cookie != NULL && oldest_cookie->created < remove_time) cookie_destroy(oldest_cookie->data->cookie, TRUE); } void cookies_init(void) { random_init(); oldest_cookie = NULL; next_cookie = &oldest_cookie; cookies = hash_create(default_pool, 100, cookie_hash, cookie_cmp); to = timeout_add(10000, cookie_timeout, NULL); } void cookies_deinit(void) { while (oldest_cookie != NULL) cookie_destroy(oldest_cookie->data->cookie, TRUE); hash_destroy(cookies); timeout_remove(to); random_deinit(); }