[Dovecot] Patch Adding BASE64-PLAIN Password Scheme

imacat imacat at mail.imacat.idv.tw
Sun May 13 06:50:26 EEST 2007


On Sat, 12 May 2007 21:58:30 +0300
Timo Sirainen <tss at 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 at 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
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 187 bytes
Desc: not available
Url : http://dovecot.org/pipermail/dovecot/attachments/20070513/01792854/attachment.pgp 


More information about the dovecot mailing list