Mercurial > dovecot > original-hg > dovecot-1.2
view src/auth/cookie.c @ 1000:0fbafade2d85 HEAD
If auth/login process died unexpectedly, the exit status or killing signal
wasn't logged.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Tue, 21 Jan 2003 09:58:49 +0200 |
parents | 501f076f2e74 |
children |
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 struct cookie_list { struct cookie_list *next; time_t created; struct cookie_data *data; }; static struct hash_table *cookies; static struct cookie_list *oldest_cookie, **next_cookie; static struct 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 = ((const unsigned char *) p1)[i] - ((const unsigned char *) p2)[i]; if (ret != 0) return ret; } return 0; } void cookie_add(struct cookie_data *data) { struct cookie_list *list; do { random_fill(data->cookie, AUTH_COOKIE_SIZE); } while (hash_lookup(cookies, data->cookie)); /* add to linked list */ list = i_new(struct cookie_list, 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) { struct cookie_list **pos, *list; hash_remove(cookies, cookie); /* FIXME: slow */ 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); } struct cookie_data *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); } struct cookie_data * cookie_lookup_and_remove(unsigned int login_pid, unsigned char cookie[AUTH_COOKIE_SIZE]) { struct cookie_data *data; data = hash_lookup(cookies, cookie); if (data != NULL) { if (data->login_pid != login_pid) data = NULL; else cookie_destroy(cookie, FALSE); } return data; } void cookies_remove_login_pid(unsigned int login_pid) { struct cookie_list *list, *next; /* FIXME: slow */ for (list = oldest_cookie; list != NULL; list = next) { next = list->next; if (list->data->login_pid == login_pid) cookie_destroy(list->data->cookie, TRUE); } } static void cookie_timeout(void *context __attr_unused__, struct 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) { oldest_cookie = NULL; next_cookie = &oldest_cookie; cookies = hash_create(default_pool, 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); }