Andrey Panin
2006-Jun-26 12:57 UTC
[Dovecot] [PATCH, RFC 0/13] OTP: add auth_cache_remove()
This patchset add support for One-Time-Password authentication mechanisms, both S/Key (RFC 1731) and OTP (RFC 2444) are implemented. Tested with mutt (uses cyrus sasl library for authentication). Patches were made against CVS HEAD. Please take a look. Add auth_cache_remove() function which will be used by OTP code to evict old entries from auth cache. diff -urdpNX /usr/share/dontdiff -x Makefile dovecot.vanilla/src/auth/auth-cache.c dovecot/src/auth/auth-cache.c --- dovecot.vanilla/src/auth/auth-cache.c 2006-06-23 13:42:22.122508080 +0400 +++ dovecot/src/auth/auth-cache.c 2006-06-23 13:44:30.945923944 +0400 @@ -226,3 +226,22 @@ void auth_cache_insert(struct auth_cache cache->size_left -= alloc_size; hash_insert(cache->hash, node->data, node); } + +void auth_cache_remove(struct auth_cache *cache, + const struct auth_request *request, + const char *key) +{ + string_t *str; + struct cache_node *node; + + str = t_str_new(256); + var_expand(str, key, + auth_request_get_var_expand_table(request, + auth_request_str_escape)); + + node = hash_lookup(cache->hash, str_c(str)); + if (node == NULL) + return; + + auth_cache_node_destroy(cache, node); +} diff -urdpNX /usr/share/dontdiff -x Makefile dovecot.vanilla/src/auth/auth-cache.h dovecot/src/auth/auth-cache.h --- dovecot.vanilla/src/auth/auth-cache.h 2006-06-23 13:42:22.122508080 +0400 +++ dovecot/src/auth/auth-cache.h 2006-06-23 13:44:30.945923944 +0400 @@ -27,4 +27,9 @@ void auth_cache_insert(struct auth_cache const struct auth_request *request, const char *key, const char *value); +/* Remove key from cache */ +void auth_cache_remove(struct auth_cache *cache, + const struct auth_request *request, + const char *key); + #endif
Add OTP hash generation functions. diff -urdpNX /usr/share/dontdiff -x Makefile dovecot.vanilla/src/lib-otp/otp-hash.c dovecot/src/lib-otp/otp-hash.c --- dovecot.vanilla/src/lib-otp/otp-hash.c 1970-01-01 03:00:00.000000000 +0300 +++ dovecot/src/lib-otp/otp-hash.c 2006-06-23 13:44:31.011913912 +0400 @@ -0,0 +1,163 @@ +/* + * OTP hash generaion. + * + * Copyright (c) 2006 Andrey Panin <pazke at donpac.ru> + * + * This software is released under the MIT license. + */ + +#include "lib.h" +#include "md4.h" +#include "md5.h" +#include "sha1.h" + +#include "otp.h" + +struct digest { + const char *name; + void (*init)(void *ctx); + void (*update)(void *ctx, const void *data, const size_t size); + void (*final)(void *ctx, void *res); + void (*otp_final)(void *ctx, void *res); +}; + +struct digest_context { + struct digest *digest; + union { + struct md4_context md4_ctx; + struct md5_context md5_ctx; + struct sha1_ctxt sha1_ctx; + } ctx; +}; + +static void md4_fold(struct md4_context *ctx, void *res) +{ + uint32_t tmp[4], *p = res; + + md4_final(ctx, (unsigned char *) tmp); + + *p++ = tmp[0] ^ tmp[2]; + *p = tmp[1] ^ tmp[3]; +} + +static void md5_fold(struct md5_context *ctx, void *res) +{ + uint32_t tmp[4], *p = res; + + md5_final(ctx, (unsigned char *) tmp); + + *p++ = tmp[0] ^ tmp[2]; + *p = tmp[1] ^ tmp[3]; +} + +/* + * Sometimes I simply can't look at code generated by gcc. + */ +static inline uint32_t swab(uint32_t val) +{ +#if defined(__GNUC__) && defined(__i386__) + asm("xchgb %b0, %h0\n" + "rorl $16, %0\n" + "xchgb %b0, %h0\n" + :"=q" (val) + : "0" (val)); +#else + val = ((val & 0xff) << 24) | ((val & 0xff00) << 8) | + ((val & 0xff0000) >> 8) | ((val >> 24) & 0xff); +#endif + return val; +} + +static void sha1_fold(struct sha1_ctxt *ctx, void *res) +{ + uint32_t tmp[5], *p = res; + + sha1_result(ctx, tmp); + + *p++ = swab(tmp[0] ^ tmp[2] ^ tmp[4]); + *p = swab(tmp[1] ^ tmp[3]); +} + + +#define F(name) ((void *) (name)) + +static struct digest digests[] = { + { "md4", F(md4_init), F(md4_update), F(md4_final), F(md4_fold) }, + { "md5", F(md5_init), F(md5_update), F(md5_final), F(md5_fold) }, + { "sha1", F(sha1_init), F(sha1_loop), F(sha1_result), F(sha1_fold) }, +}; + +#define N_DIGESTS (int)(sizeof(digests) / sizeof(digests[0])) + +#undef F + +const char * digest_name(int algo) +{ + return (algo < N_DIGESTS) ? digests[algo].name : NULL; +} + +int digest_find(const char *name) +{ + int i; + + for (i = 0; i < N_DIGESTS; i++) + if (strcmp(name, digests[i].name) == 0) + return i; + + return -1; +} + +int digest_init(struct digest_context *ctx, const int algo) +{ + i_assert(algo >= 0); + + ctx->digest = digests + algo; + + ctx->digest->init((void *) &ctx->ctx); + + return 0; +} + +void digest_update(struct digest_context *ctx, const void *data, + const size_t size) +{ + ctx->digest->update((void *) &ctx->ctx, data, size); +} + +void digest_final(struct digest_context *ctx, unsigned char *result) +{ + ctx->digest->final((void *) &ctx->ctx, result); +} + +void digest_otp_final(struct digest_context *ctx, unsigned char *result) +{ + ctx->digest->otp_final((void *) &ctx->ctx, result); +} + + +void otp_hash(int algo, const char *seed, const char *passphrase, + int step, unsigned char *result) +{ + struct digest_context ctx; + + digest_init(&ctx, algo); + digest_update(&ctx, seed, strlen(seed)); + digest_update(&ctx, passphrase, strlen(passphrase)); + digest_otp_final(&ctx, result); + + while (step--) { + digest_init(&ctx, algo); + digest_update(&ctx, result, OTP_HASH_SIZE); + digest_otp_final(&ctx, result); + } +} + +void otp_next_hash(int algo, const unsigned char *prev, + unsigned char *result) +{ + struct digest_context ctx; + + digest_init(&ctx, algo); + digest_update(&ctx, prev, OTP_HASH_SIZE); + digest_otp_final(&ctx, result); +} diff -urdpNX /usr/share/dontdiff -x Makefile dovecot.vanilla/src/lib-otp/otp-hash.h dovecot/src/lib-otp/otp-hash.h --- dovecot.vanilla/src/lib-otp/otp-hash.h 1970-01-01 03:00:00.000000000 +0300 +++ dovecot/src/lib-otp/otp-hash.h 2006-06-23 13:44:31.011913912 +0400 @@ -0,0 +1,25 @@ +#ifndef __OTP_HASH_H__ +#define __OTP_HASH_H__ + +struct digest_context; + +enum { + OTP_HASH_MD4, + OTP_HASH_MD5, + OTP_HASH_SHA1, +}; + +int digest_find(const char *name); +int digest_init(struct digest_context *ctx, const int algo); +void digest_update(struct digest_context *ctx, const void *data, + const size_t size); +void digest_final(struct digest_context *ctx, unsigned char *result); +void digest_otp_final(struct digest_context *ctx, unsigned char *result); +const char * digest_name(int algo); + +void otp_hash(int algo, const char *seed, const char *passphrase, + int step, unsigned char *result); + +void otp_next_hash(int algo, const unsigned char *prev, unsigned char *result); + +#endif /* __OTP_HASH_H__ */