[Dovecot] Virtual User Home Directory, and APOP Clear Text Passwords
Dear all,
Hi. This is imacat from Taiwan. I'm new to this list.
I was migrating from Qpopper to Dovecot. (Qpopper copies the
mailbox when POP3 logged in, which causes quota problem.) Generally Dovecot is nice. However, I have a few questions:
1. I have a few virtual users, and I'm not using IMAP. Do I still
have to give them a writable home directory? I mean, they exists only for me to receive mails from fetchmail. They really have nothing but their inbox. But if I do not give them a writable home directory, I got this error in my syslog all the time:
mbox: Can't create root mail directory /home/homeless/mail: Permission denied
2. I would like to use APOP in addition to SSL/TLS. Currently
Dovecot saves APOP passwords as clear text. I understand this. But is it possible to have some sort of encoding, for example, Base64? Just to prevent casual reads. I have several users. I do not want to know their passwords just to add them to the APOP database. I do not want other roots to read my passwords, intended or not.
Encoded passwords also have the advantage that I can use
passwords that contain the colon sign ":". It would be nice if something a little harder than Base64 can be used.
Thank you very much in advance.
-- imacat ^_*' imacat@mail.imacat.idv.tw PGP Key: http://www.imacat.idv.tw/me/pgpkey.txt
Tavern IMACAT's http://www.imacat.idv.tw/ Woman's Voice http://www.wov.idv.tw/ TLUG List Manager http://www.linux.org.tw/mailman/listinfo/tlug
On Fri, 2007-05-11 at 12:22 +0800, imacat wrote:
Dear all,
Hi. This is imacat from Taiwan. I'm new to this list. I was migrating from Qpopper to Dovecot. (Qpopper copies the
mailbox when POP3 logged in, which causes quota problem.) Generally Dovecot is nice. However, I have a few questions:
1. I have a few virtual users, and I'm not using IMAP. Do I still
have to give them a writable home directory? I mean, they exists only for me to receive mails from fetchmail. They really have nothing but their inbox. But if I do not give them a writable home directory, I got this error in my syslog all the time:
mbox: Can't create root mail directory /home/homeless/mail: Permission denied
See the bottom of http://wiki.dovecot.org/MailLocation/Mbox
2. I would like to use APOP in addition to SSL/TLS. Currently
Dovecot saves APOP passwords as clear text. I understand this. But is it possible to have some sort of encoding, for example, Base64? Just to prevent casual reads. I have several users. I do not want to know their passwords just to add them to the APOP database. I do not want other roots to read my passwords, intended or not.
Encoded passwords also have the advantage that I can use
passwords that contain the colon sign ":". It would be nice if something a little harder than Base64 can be used.
Currently there isn't anything like that. But I guess for v1.1 I could finally make it possible to specify base64/hex encoding in the scheme, so you could use eg. {plain.b64} or {plain.hex}.
If you really need this now you could also modify the sources yourself. It should be pretty easy to add a new plain.b64 scheme to src/auth/password-scheme.c (could also be implemented as a plugin)
On Fri, 11 May 2007 17:45:23 +0300 Timo Sirainen <tss@iki.fi> wrote:
On Fri, 2007-05-11 at 12:22 +0800, imacat wrote:
1. I have a few virtual users, and I'm not using IMAP. Do I still
have to give them a writable home directory? I mean, they exists only
See the bottom of http://wiki.dovecot.org/MailLocation/Mbox
Oh. That is very nice. I obviously missed it. It is working. Thank
you.
2. I would like to use APOP in addition to SSL/TLS. Currently
Dovecot saves APOP passwords as clear text. I understand this. But is it possible to have some sort of encoding, for example, Base64? Just to
Currently there isn't anything like that. But I guess for v1.1 I could finally make it possible to specify base64/hex encoding in the scheme, so you could use eg. {plain.b64} or {plain.hex}.
That is really very nice. I'm awaiting.
If you really need this now you could also modify the sources yourself. It should be pretty easy to add a new plain.b64 scheme to src/auth/password-scheme.c (could also be implemented as a plugin)
Well, I tried. It's a little harder than "pretty easy". ^^; There
are more source files other than src/auth/password-scheme.c that need to be updated accordingly, too, like src/auth/passdb.c. But I still believe it is easy, since base64_encode() is already there. I'll wait for the next summer anyway. ^_*'
-- 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
On Sat, 12 May 2007 01:25:45 +0800 imacat <imacat@mail.imacat.idv.tw> wrote:
2. I would like to use APOP in addition to SSL/TLS. Currently Dovecot saves APOP passwords as clear text. I understand this. But is it possible to have some sort of encoding, for example, Base64? Just to
If you really need this now you could also modify the sources yourself. It should be pretty easy to add a new plain.b64 scheme to src/auth/password-scheme.c (could also be implemented as a plugin)
Hi. Here is a simple patch that adds the BASE64-PLAIN password scheme. It may not be very clean. 1. I do not know if adding base64_decode() in passwd_file_save_results() in src/auth/passdb-passwd-file.c is appropriate. 2. It only work with the Passwd-file password database. Other password databases (like SQL) is not tested. However, it works fine. Hope that it helps. Please tell me if you need any more information. Thank you. -----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 00:04:15.000000000 +0800 @@ -63,6 +63,8 @@ case PASSDB_CREDENTIALS_PLAINTEXT: if (strcasecmp(wanted_scheme, "CLEARTEXT") == 0) return wanted_scheme; + if (strcasecmp(wanted_scheme, "BASE64-PLAIN") == 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, "BASE64-PLAIN") != 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 00:04:41.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,18 @@ 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); + if (*scheme_r != NULL && *crypted_pass_r != NULL && strcasecmp(*scheme_r, "BASE64-PLAIN") == 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/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 00:04:15.000000000 +0800 @@ -312,6 +312,26 @@ return plaintext; } +static bool base64_plain_verify(const char *plaintext, const char *password, + const char *user __attr_unused__) +{ + string_t *str; + + str = t_str_new(MAX_BASE64_ENCODED_SIZE(strlen(password)+1)); + base64_encode(password, strlen(password), str); + return strcmp(plaintext, str_c(str)) == 0; +} + +static const char *base64_plain_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 }, + { "BASE64-PLAIN", base64_plain_verify, base64_plain_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) iD8DBQFGRef6i9gubzC5S1wRArvCAJ992XKUOk0tbiSlmMTlEAZN9YFXbgCfSDXG fBuR00ppfcX1sBy20cCnmG0= =l5z1 -----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
On Sun, 2007-05-13 at 00:34 +0800, imacat wrote:
Hi. Here is a simple patch that adds the BASE64-PLAIN password scheme. It may not be very clean.
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.
@@ -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, "BASE64-PLAIN") != 0) {
This is ok, although it makes me think if there should be some kind of a password_scheme_is_plaintext() function.
+static bool base64_plain_verify(const char *plaintext, const char *password, + const char *user __attr_unused__) +{ + string_t *str; + + str = t_str_new(MAX_BASE64_ENCODED_SIZE(strlen(password)+1)); + base64_encode(password, strlen(password), str); + return strcmp(plaintext, str_c(str)) == 0; +}
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.
+ { "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. :)
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
On Sun, 2007-05-13 at 11:50 +0800, imacat wrote:
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.)
Oh right. The current code doesn't support modifying the passwords.
I implemented this now in a generic way to CVS and did some other cleanups as well. Pretty large changes, hopefully didn't break anything.
participants (2)
-
imacat
-
Timo Sirainen