[dovecot-cvs] dovecot/src/auth Makefile.am, 1.51, 1.52 mech-otp.c, NONE, 1.1 mech-skey.c, NONE, 1.1 mech.c, 1.56, 1.57 otp-skey-common.c, NONE, 1.1 otp-skey-common.h, NONE, 1.1 passdb.c, 1.43, 1.44 passdb.h, 1.35, 1.36 password-scheme-otp.c, NONE, 1.1 password-scheme.c, 1.24, 1.25 password-scheme.h, 1.8, 1.9
tss at dovecot.org
tss at dovecot.org
Sun Nov 12 19:36:46 UTC 2006
- Previous message: [dovecot-cvs] dovecot/src/lib-otp .cvsignore, NONE, 1.1 Makefile.am, NONE, 1.1 otp-dictionary.c, NONE, 1.1 otp-dictionary.h, NONE, 1.1 otp-hash.c, NONE, 1.1 otp-hash.h, NONE, 1.1 otp-parity.c, NONE, 1.1 otp-parity.h, NONE, 1.1 otp-parse.c, NONE, 1.1 otp-parse.h, NONE, 1.1 otp.h, NONE, 1.1
- Next message: [dovecot-cvs] dovecot/src/master master-settings.c, 1.125.2.17, 1.125.2.18
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /var/lib/cvs/dovecot/src/auth
In directory talvi:/tmp/cvs-serv24954/src/auth
Modified Files:
Makefile.am mech.c passdb.c passdb.h password-scheme.c
password-scheme.h
Added Files:
mech-otp.c mech-skey.c otp-skey-common.c otp-skey-common.h
password-scheme-otp.c
Log Message:
Added OTP and S/KEY authentication mechanisms. Patch by Andrey Panin.
Index: Makefile.am
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/Makefile.am,v
retrieving revision 1.51
retrieving revision 1.52
diff -u -d -r1.51 -r1.52
--- Makefile.am 8 Oct 2006 21:25:17 -0000 1.51
+++ Makefile.am 12 Nov 2006 19:36:41 -0000 1.52
@@ -9,6 +9,7 @@
-I$(top_srcdir)/src/lib-sql \
-I$(top_srcdir)/src/lib-settings \
-I$(top_srcdir)/src/lib-ntlm \
+ -I$(top_srcdir)/src/lib-otp \
-DAUTH_MODULE_DIR=\""$(moduledir)/auth"\" \
-DPKG_LIBEXECDIR=\""$(pkglibexecdir)"\" \
$(AUTH_CFLAGS)
@@ -21,12 +22,14 @@
password-scheme-md5crypt.c \
password-scheme-cram-md5.c \
password-scheme-ntlm.c \
+ password-scheme-otp.c \
password-scheme-rpa.c
dovecot_auth_LDADD = \
libpassword.a \
../lib-settings/libsettings.a \
../lib-ntlm/libntlm.a \
+ ../lib-otp/libotp.a \
../lib-sql/libsql.a \
../lib/liblib.a \
$(AUTH_LIBS) \
@@ -56,9 +59,12 @@
mech-cram-md5.c \
mech-digest-md5.c \
mech-ntlm.c \
+ mech-otp.c \
+ mech-skey.c \
mech-gssapi.c \
mech-rpa.c \
mech-apop.c \
+ otp-skey-common.c \
passdb.c \
passdb-blocking.c \
passdb-bsdauth.c \
@@ -102,6 +108,7 @@
common.h \
mech.h \
mycrypt.h \
+ otp-skey-common.h \
passdb.h \
passdb-blocking.h \
passdb-cache.h \
--- NEW FILE: mech-otp.c ---
/*
* One-Time-Password (RFC 2444) authentication mechanism.
*
* Copyright (c) 2006 Andrey Panin <pazke at donpac.ru>
*
* This software is released under the MIT license.
*/
#include "common.h"
#include "safe-memset.h"
#include "hash.h"
#include "mech.h"
#include "passdb.h"
#include "hex-binary.h"
#include "otp.h"
#include "otp-skey-common.h"
static void
otp_send_challenge(struct auth_request *auth_request,
const char *credentials)
{
struct otp_auth_request *request =
(struct otp_auth_request *)auth_request;
const char *answer;
if (otp_parse_dbentry(credentials, &request->state) != 0) {
auth_request_log_error(&request->auth_request, "otp",
"invalid OTP data in passdb");
auth_request_fail(auth_request);
return;
}
if (--request->state.seq < 1) {
auth_request_log_error(&request->auth_request, "otp",
"sequence number < 1");
auth_request_fail(auth_request);
return;
}
request->lock = otp_try_lock(auth_request);
if (!request->lock) {
auth_request_log_error(&request->auth_request, "otp",
"user is locked, race attack?");
auth_request_fail(auth_request);
return;
}
answer = p_strdup_printf(request->pool, "otp-%s %u %s ext",
digest_name(request->state.algo),
request->state.seq, request->state.seed);
auth_request->callback(auth_request,
AUTH_CLIENT_RESULT_CONTINUE,
answer, strlen(answer));
}
static void
skey_credentials_callback(enum passdb_result result,
const char *credentials,
struct auth_request *auth_request)
{
switch (result) {
case PASSDB_RESULT_OK:
otp_send_challenge(auth_request, credentials);
break;
case PASSDB_RESULT_INTERNAL_FAILURE:
auth_request_internal_failure(auth_request);
break;
default:
auth_request_fail(auth_request);
break;
}
}
static void
otp_credentials_callback(enum passdb_result result,
const char *credentials,
struct auth_request *auth_request)
{
switch (result) {
case PASSDB_RESULT_OK:
otp_send_challenge(auth_request, credentials);
break;
case PASSDB_RESULT_INTERNAL_FAILURE:
auth_request_internal_failure(auth_request);
break;
default:
/* OTP credentials not found, try S/KEY */
auth_request_lookup_credentials(auth_request,
PASSDB_CREDENTIALS_OTP,
skey_credentials_callback);
break;
}
}
static void
mech_otp_auth_phase1(struct auth_request *auth_request,
const unsigned char *data, size_t data_size)
{
struct otp_auth_request *request =
(struct otp_auth_request *)auth_request;
const char *authzid, *authenid, *error;
size_t i, count;
/* authorization ID \0 authentication ID
FIXME: we'll ignore authorization ID for now. */
authzid = (const char *) data;
authenid = NULL;
count = 0;
for (i = 0; i < data_size; i++) {
if (data[i] == '\0') {
if (++count == 1)
authenid = (const char *) data + i + 1;
}
}
if ((count < 1) || (count > 2)) {
auth_request_log_error(&request->auth_request, "otp",
"invalid input");
auth_request_fail(auth_request);
return;
}
if (!auth_request_set_username(auth_request, authenid, &error)) {
auth_request_log_info(auth_request, "otp", "%s", error);
auth_request_fail(auth_request);
return;
}
auth_request_lookup_credentials(auth_request, PASSDB_CREDENTIALS_OTP,
otp_credentials_callback);
}
static void mech_otp_verify(struct auth_request *auth_request,
const char *data, bool hex)
{
struct otp_auth_request *request =
(struct otp_auth_request *)auth_request;
struct otp_state *state = &request->state;
unsigned char hash[OTP_HASH_SIZE], cur_hash[OTP_HASH_SIZE];
int ret;
ret = otp_parse_response(data, hash, hex);
if (ret < 0) {
auth_request_log_error(&request->auth_request, "otp",
"invalid response");
auth_request_fail(auth_request);
otp_unlock(auth_request);
return;
}
otp_next_hash(state->algo, hash, cur_hash);
ret = memcmp(cur_hash, state->hash, OTP_HASH_SIZE);
if (ret != 0) {
auth_request_fail(auth_request);
otp_unlock(auth_request);
return;
}
memcpy(state->hash, hash, sizeof(state->hash));
auth_request_set_credentials(auth_request,
PASSDB_CREDENTIALS_OTP,
otp_print_dbentry(state),
otp_set_credentials_callback);
}
static void mech_otp_verify_init(struct auth_request *auth_request,
const char *data, bool hex)
{
struct otp_auth_request *request =
(struct otp_auth_request *)auth_request;
struct otp_state new_state;
unsigned char hash[OTP_HASH_SIZE], cur_hash[OTP_HASH_SIZE];
const char *error;
int ret;
ret = otp_parse_init_response(data, &new_state, cur_hash, hex, &error);
if (ret < 0) {
auth_request_log_error(&request->auth_request, "otp",
"invalid init response, %s", error);
auth_request_fail(auth_request);
otp_unlock(auth_request);
return;
}
otp_next_hash(request->state.algo, cur_hash, hash);
ret = memcmp(hash, request->state.hash, OTP_HASH_SIZE);
if (ret != 0) {
auth_request_fail(auth_request);
otp_unlock(auth_request);
return;
}
auth_request_set_credentials(auth_request,
PASSDB_CREDENTIALS_OTP,
otp_print_dbentry(&new_state),
otp_set_credentials_callback);
}
static void
mech_otp_auth_phase2(struct auth_request *auth_request,
const unsigned char *data, size_t data_size)
{
const char *str = t_strndup(data, data_size);
if (strncmp(str, "hex:", 4) == 0) {
mech_otp_verify(auth_request, str + 4, TRUE);
} else if (strncmp(str, "word:", 5) == 0) {
mech_otp_verify(auth_request, str + 5, FALSE);
} else if (strncmp(str, "init-hex:", 9) == 0) {
mech_otp_verify_init(auth_request, str + 9, TRUE);
} else if (strncmp(str, "init-word:", 10) == 0) {
mech_otp_verify_init(auth_request, str + 10, FALSE);
} else {
auth_request_log_error(auth_request, "otp",
"unsupported response type");
auth_request_fail(auth_request);
otp_unlock(auth_request);
}
}
static void
mech_otp_auth_continue(struct auth_request *auth_request,
const unsigned char *data, size_t data_size)
{
if (auth_request->user == NULL) {
mech_otp_auth_phase1(auth_request, data, data_size);
} else {
mech_otp_auth_phase2(auth_request, data, data_size);
}
}
static struct auth_request *mech_otp_auth_new(void)
{
struct otp_auth_request *request;
pool_t pool;
otp_lock_init();
pool = pool_alloconly_create("otp_auth_request", 256);
request = p_new(pool, struct otp_auth_request, 1);
request->pool = pool;
request->lock = FALSE;
request->auth_request.refcount = 1;
request->auth_request.pool = pool;
return &request->auth_request;
}
const struct mech_module mech_otp = {
"OTP",
MEMBER(flags) MECH_SEC_DICTIONARY | MECH_SEC_ACTIVE,
MEMBER(passdb_need_plain) FALSE,
MEMBER(passdb_need_credentials) TRUE,
MEMBER(passdb_need_set_credentials) TRUE,
mech_otp_auth_new,
mech_generic_auth_initial,
mech_otp_auth_continue,
mech_otp_skey_auth_free
};
--- NEW FILE: mech-skey.c ---
/*
* S/Key (RFC 1731) authentication mechanism.
*
* Copyright (c) 2006 Andrey Panin <pazke at donpac.ru>
*
* This software is released under the MIT license.
*/
#include "common.h"
#include "safe-memset.h"
#include "hash.h"
#include "mech.h"
#include "passdb.h"
#include "hex-binary.h"
#include "otp.h"
#include "otp-skey-common.h"
static void
skey_send_challenge(struct auth_request *auth_request,
const char *credentials)
{
struct otp_auth_request *request =
(struct otp_auth_request *)auth_request;
const char *answer;
if (otp_parse_dbentry(credentials, &request->state) != 0) {
auth_request_log_error(&request->auth_request, "skey",
"invalid OTP data in passdb");
auth_request_fail(auth_request);
return;
}
if (request->state.algo != OTP_HASH_MD4) {
auth_request_log_error(&request->auth_request, "skey",
"md4 hash is needed");
auth_request_fail(auth_request);
return;
}
if (--request->state.seq < 1) {
auth_request_log_error(&request->auth_request, "skey",
"sequence number < 1");
auth_request_fail(auth_request);
return;
}
request->lock = otp_try_lock(auth_request);
if (!request->lock) {
auth_request_log_error(&request->auth_request, "skey",
"user is locked, race attack?");
auth_request_fail(auth_request);
return;
}
answer = p_strdup_printf(request->pool, "%u %s",
request->state.seq, request->state.seed);
auth_request->callback(auth_request,
AUTH_CLIENT_RESULT_CONTINUE,
answer, strlen(answer));
}
static void
otp_credentials_callback(enum passdb_result result,
const char *credentials,
struct auth_request *auth_request)
{
switch (result) {
case PASSDB_RESULT_OK:
skey_send_challenge(auth_request, credentials);
break;
case PASSDB_RESULT_INTERNAL_FAILURE:
auth_request_internal_failure(auth_request);
break;
default:
auth_request_fail(auth_request);
break;
}
}
static void
skey_credentials_callback(enum passdb_result result,
const char *credentials,
struct auth_request *auth_request)
{
switch (result) {
case PASSDB_RESULT_OK:
skey_send_challenge(auth_request, credentials);
break;
case PASSDB_RESULT_INTERNAL_FAILURE:
auth_request_internal_failure(auth_request);
break;
default:
/* S/KEY credentials not found, try OTP */
auth_request_lookup_credentials(auth_request,
PASSDB_CREDENTIALS_OTP,
otp_credentials_callback);
break;
}
}
static void
mech_skey_auth_phase1(struct auth_request *auth_request,
const unsigned char *data, size_t data_size)
{
const char *username, *error;
username = t_strndup(data, data_size);
if (!auth_request_set_username(auth_request, username, &error)) {
auth_request_log_info(auth_request, "skey", "%s", error);
auth_request_fail(auth_request);
return;
}
auth_request_lookup_credentials(auth_request, PASSDB_CREDENTIALS_SKEY,
skey_credentials_callback);
}
static void
mech_skey_auth_phase2(struct auth_request *auth_request,
const unsigned char *data, size_t data_size)
{
struct otp_auth_request *request =
(struct otp_auth_request *)auth_request;
struct otp_state *state = &request->state;
unsigned char hash[OTP_HASH_SIZE], cur_hash[OTP_HASH_SIZE];
int ret;
if (data_size == 8) {
memcpy(hash, data, 8);
} else {
const char *words = t_strndup(data, data_size);
ret = otp_parse_response(words, hash, 0);
if (ret < 0) {
auth_request_log_error(&request->auth_request, "skey",
"invalid response");
auth_request_fail(auth_request);
otp_unlock(auth_request);
return;
}
}
otp_next_hash(state->algo, hash, cur_hash);
ret = memcmp(cur_hash, state->hash, OTP_HASH_SIZE);
if (ret != 0) {
auth_request_fail(auth_request);
otp_unlock(auth_request);
return;
}
memcpy(state->hash, hash, sizeof(state->hash));
auth_request_set_credentials(auth_request,
PASSDB_CREDENTIALS_OTP,
otp_print_dbentry(state),
otp_set_credentials_callback);
}
static void
mech_skey_auth_continue(struct auth_request *auth_request,
const unsigned char *data, size_t data_size)
{
if (auth_request->user == NULL) {
mech_skey_auth_phase1(auth_request, data, data_size);
} else {
mech_skey_auth_phase2(auth_request, data, data_size);
}
}
static struct auth_request *mech_skey_auth_new(void)
{
struct otp_auth_request *request;
pool_t pool;
otp_lock_init();
pool = pool_alloconly_create("skey_auth_request", 256);
request = p_new(pool, struct otp_auth_request, 1);
request->pool = pool;
request->lock = FALSE;
request->auth_request.refcount = 1;
request->auth_request.pool = pool;
return &request->auth_request;
}
const struct mech_module mech_skey = {
"SKEY",
MEMBER(flags) MECH_SEC_DICTIONARY | MECH_SEC_ACTIVE,
MEMBER(passdb_need_plain) FALSE,
MEMBER(passdb_need_credentials) TRUE,
MEMBER(passdb_need_set_credentials) TRUE,
mech_skey_auth_new,
mech_generic_auth_initial,
mech_skey_auth_continue,
mech_otp_skey_auth_free
};
Index: mech.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/mech.c,v
retrieving revision 1.56
retrieving revision 1.57
diff -u -d -r1.56 -r1.57
--- mech.c 17 Jun 2006 19:15:20 -0000 1.56
+++ mech.c 12 Nov 2006 19:36:41 -0000 1.57
@@ -68,6 +68,8 @@
extern struct mech_module mech_cram_md5;
extern struct mech_module mech_digest_md5;
extern struct mech_module mech_ntlm;
+extern struct mech_module mech_otp;
+extern struct mech_module mech_skey;
extern struct mech_module mech_rpa;
extern struct mech_module mech_anonymous;
#ifdef HAVE_GSSAPI
@@ -82,6 +84,8 @@
mech_register_module(&mech_cram_md5);
mech_register_module(&mech_digest_md5);
mech_register_module(&mech_ntlm);
+ mech_register_module(&mech_otp);
+ mech_register_module(&mech_skey);
mech_register_module(&mech_rpa);
mech_register_module(&mech_anonymous);
#ifdef HAVE_GSSAPI
@@ -97,6 +101,8 @@
mech_unregister_module(&mech_cram_md5);
mech_unregister_module(&mech_digest_md5);
mech_unregister_module(&mech_ntlm);
+ mech_unregister_module(&mech_otp);
+ mech_unregister_module(&mech_skey);
mech_unregister_module(&mech_rpa);
mech_unregister_module(&mech_anonymous);
#ifdef HAVE_GSSAPI
--- NEW FILE: otp-skey-common.c ---
/*
* Common code for OTP and SKEY authentication mechanisms.
*
* Copyright (c) 2006 Andrey Panin <pazke at donpac.ru>
*
* This software is released under the MIT license.
*/
#include "common.h"
#include "hash.h"
#include "mech.h"
#include "otp.h"
#include "otp-skey-common.h"
static struct hash_table *otp_lock_table;
void otp_lock_init(void)
{
if (otp_lock_table != NULL)
return;
otp_lock_table = hash_create(system_pool, system_pool,
128, strcase_hash,
(hash_cmp_callback_t *)strcasecmp);
}
int otp_try_lock(struct auth_request *auth_request)
{
if (hash_lookup(otp_lock_table, auth_request->user))
return FALSE;
hash_insert(otp_lock_table, auth_request->user, auth_request);
return TRUE;
}
void otp_unlock(struct auth_request *auth_request)
{
struct otp_auth_request *request =
(struct otp_auth_request *)auth_request;
if (!request->lock)
return;
hash_remove(otp_lock_table, auth_request->user);
request->lock = FALSE;
}
void otp_set_credentials_callback(enum passdb_result result,
struct auth_request *auth_request)
{
switch (result) {
case PASSDB_RESULT_OK:
auth_request_success(auth_request, NULL, 0);
break;
default:
auth_request_internal_failure(auth_request);
otp_unlock(auth_request);
break;
}
otp_unlock(auth_request);
}
void mech_otp_skey_auth_free(struct auth_request *auth_request)
{
otp_unlock(auth_request);
pool_unref(auth_request->pool);
}
--- NEW FILE: otp-skey-common.h ---
#ifndef __OTP_SKEY_COMMON_H__
#define __OTP_SKEY_COMMON_H__
struct otp_auth_request {
struct auth_request auth_request;
pool_t pool;
int lock;
struct otp_state state;
};
void otp_lock_init(void);
int otp_try_lock(struct auth_request *auth_request);
void otp_unlock(struct auth_request *auth_request);
void otp_set_credentials_callback(enum passdb_result result,
struct auth_request *auth_request);
void mech_otp_skey_auth_free(struct auth_request *auth_request);
#endif /* __OTP_SKEY_COMMON_H__ */
Index: passdb.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/passdb.c,v
retrieving revision 1.43
retrieving revision 1.44
diff -u -d -r1.43 -r1.44
--- passdb.c 8 Oct 2006 21:25:17 -0000 1.43
+++ passdb.c 12 Nov 2006 19:36:41 -0000 1.44
@@ -71,6 +71,10 @@
return "LANMAN";
case PASSDB_CREDENTIALS_NTLM:
return "NTLM";
+ case PASSDB_CREDENTIALS_OTP:
+ return "OTP";
+ case PASSDB_CREDENTIALS_SKEY:
+ return "SKEY";
case PASSDB_CREDENTIALS_RPA:
return "RPA";
}
Index: passdb.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/passdb.h,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -d -r1.35 -r1.36
--- passdb.h 8 Nov 2006 20:22:08 -0000 1.35
+++ passdb.h 12 Nov 2006 19:36:41 -0000 1.36
@@ -15,6 +15,8 @@
PASSDB_CREDENTIALS_DIGEST_MD5,
PASSDB_CREDENTIALS_LANMAN,
PASSDB_CREDENTIALS_NTLM,
+ PASSDB_CREDENTIALS_OTP,
+ PASSDB_CREDENTIALS_SKEY,
PASSDB_CREDENTIALS_RPA
};
--- NEW FILE: password-scheme-otp.c ---
/*
* OTP password scheme.
*
* Copyright (c) 2006 Andrey Panin <pazke at donpac.ru>
*
* This software is released under the MIT license.
*/
#include "lib.h"
#include "hex-binary.h"
#include "password-scheme.h"
#include "randgen.h"
#include "otp.h"
const char *password_generate_otp(const char *pw, const char *data,
unsigned int algo)
{
struct otp_state state;
if (data != NULL) {
if (otp_parse_dbentry(data, &state) != 0) {
i_warning("Invalid OTP data in passdb");
return "";
}
} else {
/* Generate new OTP credentials from plaintext */
unsigned char random_data[OTP_MAX_SEED_LEN / 2];
random_fill(random_data, sizeof(random_data));
strocpy(state.seed, binary_to_hex(random_data,
OTP_MAX_SEED_LEN / 2), sizeof(state.seed));
state.seq = 1024;
state.algo = algo;
}
otp_hash(state.algo, state.seed, pw, state.seq, state.hash);
return otp_print_dbentry(&state);
}
Index: password-scheme.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/password-scheme.c,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -d -r1.24 -r1.25
--- password-scheme.c 8 Oct 2006 23:18:18 -0000 1.24
+++ password-scheme.c 12 Nov 2006 19:36:41 -0000 1.25
@@ -10,6 +10,7 @@
#include "mycrypt.h"
#include "randgen.h"
#include "sha1.h"
+#include "otp.h"
#include "str.h"
#include "password-scheme.h"
@@ -448,6 +449,25 @@
return password_generate_ntlm(plaintext);
}
+static bool otp_verify(const char *plaintext, const char *password,
+ const char *user __attr_unused__)
+{
+ return strcasecmp(password,
+ password_generate_otp(plaintext, password, -1)) == 0;
+}
+
+static const char *otp_generate(const char *plaintext,
+ const char *user __attr_unused__)
+{
+ return password_generate_otp(plaintext, NULL, OTP_HASH_SHA1);
+}
+
+static const char *skey_generate(const char *plaintext,
+ const char *user __attr_unused__)
+{
+ return password_generate_otp(plaintext, NULL, OTP_HASH_MD4);
+}
+
static bool rpa_verify(const char *plaintext, const char *password,
const char *user __attr_unused__)
{
@@ -476,6 +496,8 @@
{ "LDAP-MD5", plain_md5_verify, ldap_md5_generate },
{ "LANMAN", lm_verify, lm_generate },
{ "NTLM", ntlm_verify, ntlm_generate },
+ { "OTP", otp_verify, otp_generate },
+ { "SKEY", otp_verify, skey_generate },
{ "RPA", rpa_verify, rpa_generate },
{ NULL, NULL, NULL }
};
Index: password-scheme.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/password-scheme.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- password-scheme.h 13 Jan 2006 20:25:57 -0000 1.8
+++ password-scheme.h 12 Nov 2006 19:36:41 -0000 1.9
@@ -32,6 +32,8 @@
const char *password_generate_cram_md5(const char *pw);
const char *password_generate_lm(const char *pw);
const char *password_generate_ntlm(const char *pw);
+const char *password_generate_otp(const char *pw, const char *state,
+ unsigned int algo);
const char *password_generate_rpa(const char *pw);
#endif
- Previous message: [dovecot-cvs] dovecot/src/lib-otp .cvsignore, NONE, 1.1 Makefile.am, NONE, 1.1 otp-dictionary.c, NONE, 1.1 otp-dictionary.h, NONE, 1.1 otp-hash.c, NONE, 1.1 otp-hash.h, NONE, 1.1 otp-parity.c, NONE, 1.1 otp-parity.h, NONE, 1.1 otp-parse.c, NONE, 1.1 otp-parse.h, NONE, 1.1 otp.h, NONE, 1.1
- Next message: [dovecot-cvs] dovecot/src/master master-settings.c, 1.125.2.17, 1.125.2.18
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the dovecot-cvs
mailing list