On Sat, 12 May 2007 21:58:30 +0300 Timo Sirainen <tss@iki.fi> wrote:
On Sun, 2007-05-13 at 00:34 +0800, imacat wrote:
1. I do not know if adding base64_decode() in passwd_file_save_results() in src/auth/passdb-passwd-file.c is appropriate.
This isn't needed. The generic scheme handling code should have made it work everywhere.
In fact, no. (At least as far as I can tell.) The plain text passwords are used in many places later on, including generating other password formats directly. In some places it is saved into cache, and in some places it is restored from cache. I do not know if it shall be decoded before generating other MD5 password hashes, before generating APOP hash, before plain text comparison, or any other places. But "scheme" is not available in some of these places that I have no clue to decode it.
+static bool base64_plain_verify(const char *plaintext, const char *password, + const char *user __attr_unused__) + base64_encode(password, strlen(password), str); This is a bit wrong. plaintext is in the user-given password in plaintext, and password is the base64 encoded password. Here you're base64ing a password that's already base64d. That's probably why you added the code to passdb-passwd-file.c, the code in there is working right.
Oh. Thank you. This is where I need comments. But, no. Base on the result of code trace, base64_plain_verify() was never called with APOP. This makes sense that, APOP does not compare user-supplied cresidential information with the saved cresidential information directly with strcmp(). The same goes that, when verifying plain text passwords with PLAIN.B64 password scheme, it may fail since the password is already decoded in passwd_file_save_results().
+ { "BASE64-PLAIN", base64_plain_verify, base64_plain_generate }, I'm going to use PLAIN.B64 and PLAIN.BASE64 in Dovecot v1.1, so if you might want to use that name already for your passwords so one day you don't have to patch Dovecot anymore. :)
I shall follow it. Thank you for clarifying this. The revised patch is below, with fixes to src/auth/passdb-sql.c added, in the hope that it helps. (I found that only passwd-file and SQL password databases need this.) Please tell me if you need any information, or if I can be of any help. -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 diff -u -r dovecot-1.0.0.orig/src/auth/passdb.c dovecot-1.0.0/src/auth/passdb.c - --- dovecot-1.0.0.orig/src/auth/passdb.c 2007-02-15 19:48:37.000000000 +0800 +++ dovecot-1.0.0/src/auth/passdb.c 2007-05-13 11:19:46.000000000 +0800 @@ -63,6 +63,8 @@ case PASSDB_CREDENTIALS_PLAINTEXT: if (strcasecmp(wanted_scheme, "CLEARTEXT") == 0) return wanted_scheme; + if (strcasecmp(wanted_scheme, "PLAIN.B64") == 0) + return wanted_scheme; return "PLAIN"; case PASSDB_CREDENTIALS_CRYPT: return "CRYPT"; @@ -98,7 +100,8 @@ scheme); if (strcasecmp(scheme, wanted_scheme) != 0) { if (strcasecmp(scheme, "PLAIN") != 0 && - - strcasecmp(scheme, "CLEARTEXT") != 0) { + strcasecmp(scheme, "CLEARTEXT") != 0 && + strcasecmp(scheme, "PLAIN.B64") != 0) { auth_request_log_info(auth_request, "password", "Requested %s scheme, but we have only %s", wanted_scheme, scheme); diff -u -r dovecot-1.0.0.orig/src/auth/passdb-passwd-file.c dovecot-1.0.0/src/auth/passdb-passwd-file.c - --- dovecot-1.0.0.orig/src/auth/passdb-passwd-file.c 2007-03-25 01:10:24.000000000 +0800 +++ dovecot-1.0.0/src/auth/passdb-passwd-file.c 2007-05-13 11:22:13.000000000 +0800 @@ -10,6 +10,8 @@ #include "passdb.h" #include "password-scheme.h" #include "db-passwd-file.h" +#include "base64.h" +#include "buffer.h" #define PASSWD_FILE_CACHE_KEY "%u" #define PASSWD_FILE_DEFAULT_SCHEME "CRYPT" @@ -30,9 +32,19 @@ const char *key, *value; string_t *str; char **p; + buffer_t *buf; + size_t size, password_len; *crypted_pass_r = pu->password; *scheme_r = password_get_scheme(crypted_pass_r); + /* decode the Base64-encoded plain passwords. */ + if (*scheme_r != NULL && *crypted_pass_r != NULL && strcasecmp(*scheme_r, "PLAIN.B64") == 0) { + password_len = strlen(*crypted_pass_r); + buf = buffer_create_static_hard(pool_datastack_create(), + MAX_BASE64_DECODED_SIZE(password_len)); + base64_decode(*crypted_pass_r, password_len, NULL, buf); + *crypted_pass_r = buffer_get_data(buf, &size); + } if (*scheme_r == NULL) *scheme_r = request->passdb->passdb->default_pass_scheme; diff -u -r dovecot-1.0.0.orig/src/auth/passdb-sql.c dovecot-1.0.0/src/auth/passdb-sql.c - --- dovecot-1.0.0.orig/src/auth/passdb-sql.c 2007-03-07 07:39:25.000000000 +0800 +++ dovecot-1.0.0/src/auth/passdb-sql.c 2007-05-13 11:24:09.000000000 +0800 @@ -11,6 +11,8 @@ #include "auth-cache.h" #include "db-sql.h" #include "passdb.h" +#include "base64.h" +#include "buffer.h" #include <stdlib.h> #include <string.h> @@ -57,6 +59,8 @@ enum passdb_result passdb_result; const char *user, *password, *scheme; int ret; + buffer_t *buf; + size_t size, password_len; passdb_result = PASSDB_RESULT_INTERNAL_FAILURE; user = auth_request->user; @@ -95,6 +99,14 @@ } scheme = password_get_scheme(&password); + /* decode the Base64-encoded plain passwords. */ + if (*scheme_r != NULL && *crypted_pass_r != NULL && strcasecmp(*scheme_r, "PLAIN.B64") == 0) { + password_len = strlen(*crypted_pass_r); + buf = buffer_create_static_hard(pool_datastack_create(), + MAX_BASE64_DECODED_SIZE(password_len)); + base64_decode(*crypted_pass_r, password_len, NULL, buf); + *crypted_pass_r = buffer_get_data(buf, &size); + } /* auth_request_set_field() sets scheme */ i_assert(password == NULL || scheme != NULL); diff -u -r dovecot-1.0.0.orig/src/auth/password-scheme.c dovecot-1.0.0/src/auth/password-scheme.c - --- dovecot-1.0.0.orig/src/auth/password-scheme.c 2007-02-22 22:32:11.000000000 +0800 +++ dovecot-1.0.0/src/auth/password-scheme.c 2007-05-13 11:19:46.000000000 +0800 @@ -312,6 +312,26 @@ return plaintext; } +static bool plain_b64_verify(const char *plaintext, const char *password, + const char *user __attr_unused__) +{ + string_t *str; + + str = t_str_new(MAX_BASE64_ENCODED_SIZE(strlen(plaintext)+1)); + base64_encode(plaintext, strlen(plaintext), str); + return strcmp(str_c(str), password) == 0; +} + +static const char *plain_b64_generate(const char *plaintext, + const char *user __attr_unused__) +{ + string_t *str; + + str = t_str_new(MAX_BASE64_ENCODED_SIZE(strlen(plaintext)+1)); + base64_encode(plaintext, strlen(plaintext), str); + return str_c(str); +} + static bool cram_md5_verify(const char *plaintext, const char *password, const char *user __attr_unused__) { @@ -469,6 +489,7 @@ { "SMD5", smd5_verify, smd5_generate }, { "SSHA", ssha_verify, ssha_generate }, { "PLAIN", plain_verify, plain_generate }, + { "PLAIN.B64", plain_b64_verify, plain_b64_generate }, { "CLEARTEXT", plain_verify, plain_generate }, { "CRAM-MD5", cram_md5_verify, cram_md5_generate }, { "HMAC-MD5", cram_md5_verify, cram_md5_generate }, -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (GNU/Linux) iD8DBQFGRoaFi9gubzC5S1wRAscsAJ9w+LHv3rDlNidVynMKAJYUKOvNbwCfZWdZ Z9gxSaw5gnVBH/Ui1cpe6ew= =mXNP -----END PGP SIGNATURE----- -- Best regards, imacat ^_*' <imacat@mail.imacat.idv.tw> PGP Key: http://www.imacat.idv.tw/me/pgpkey.txt <<Woman's Voice>> News: http://www.wov.idv.tw/ Tavern IMACAT's: http://www.imacat.idv.tw/ TLUG List Manager: http://lists.linux.org.tw/cgi-bin/mailman/listinfo/tlug