[GH-ISSUE #178] Refactor password handling #139

Open
opened 2026-02-26 09:36:14 +03:00 by kerem · 8 comments
Owner

Originally created by @PhrozenByte on GitHub (Apr 11, 2016).
Original GitHub issue: https://github.com/opensolutions/ViMbAdmin/issues/178

ViMbAdmin 3.0.15 now recommends the dovecot:BLF-CRYPT password scheme by default. Needless to say that this is a significant improvement in comparison to the previous default md5.salted (no matter whether salting worked or not), but it still has some disadvantages:

  • Using the dovecot: password scheme family is a security issue in general, because it forces you to allow PHP to use the exec() function. This function is disabled on many webservers on purpose.
  • Well secured systems using SELinux or AppArmor will likely prevent PHP from executing the doveadm command when using the dovecot: password scheme family (see #95). ViMbAdmin therefore requires you to change the configuration of highly security sensitive system components. Breaking the configuration may even prevent you from booting your system.
  • The dovecot: password scheme family also requires you to install ViMbAdmin on the same machine as Dovecot. This prevents service separation or at least makes it more difficult. Additionally, just think of using Docker.
  • The Dovecot packages shipped with widely used Linux distributions (like Debian) don't support BLF-CRYPT. You will need to compile your own version of libc with enabled Blowfish support to make this work. It's definitely the most secure password scheme, but shouldn't be recommended as default as long as it isn't widely supported.

Now the funny part: You don't need the dovecot: password scheme family to allow users to use the most secure password schemes (BLF-CRYPT, SHA512-CRYPT, SHA256-CRYPT) - just use the crypt: password scheme family instead. They are completely identical!

So, why does the dovecot: password scheme family work (provided that PHP is able to run doveadm) (nearly) out-of-the-box, whereas the crypt: password scheme family does not? It's simple: doveadm adds a {…} prefix (e.g. {SHA512-CRYPT}) indicating the used password scheme, so users don't have to tell Dovecot what password scheme is used. ViMbAdmin's crypt: password scheme doesn't add this prefix, so you will have to tell Dovecot the used password scheme by setting the default_pass_scheme option.

ViMbAdmin should add the {…} prefix to the database, so Dovecot can determine the used password scheme without additional configuration and without using the dovecot: password scheme family. I can think of two possible solutions:

  1. Refactor password generation in whole, so ViMbAdmin always stores the password with the appropriate prefix. This also allows users to change the default password scheme without loosing all passwords (at the moment you can't change the password scheme without making all passwords invalid). You will either have to drop support of the dovecot: password scheme family or add a additional column to store the used password scheme (e.g. crypt:sha512), otherwise it would be impossible for ViMbAdmin to distinguish between e.g. dovecot:SHA512-CRYPT and crypt:sha512 (as said, they are identical).
  2. Add a new password_dovecot column which extends the existing password column by the appropriate {…} prefix. The new column actually is never read by ViMbAdmin, it's just used by Dovecot. Not the nicest, but definitely the easiest solution. It can be implemented with a very small number of additional lines of code.

To prove that this works just fine, here's the SQL query I'm using as Dovecot's password_query. default_pass_scheme is unset. ViMbAdmin is configured with defaults.mailbox.password_scheme = "crypt:sha512". I'm using a CASE statement to distinguish between the most important password schemes (namely the crypt: and dovecot: password scheme families), a solution built into ViMbAdmin obviously won't require such a hack and supports all (possible) password schemes of all password scheme families. I switched from SHA256-CRYPT to SHA512-CRYPT on-the-fly (i.e. without resetting a single password) not long ago.

SELECT username AS user,
    CASE
        WHEN password LIKE '{%}%'
            THEN password
        WHEN password LIKE '$1$%'
            THEN CONCAT('{MD5}', password)
        WHEN password LIKE '$2a$%'
            THEN CONCAT('{BLF-CRYPT}', password)
        WHEN password LIKE '$5$%'
            THEN CONCAT('{SHA256-CRYPT}', password)
        WHEN password LIKE '$6$%'
            THEN CONCAT('{SHA512-CRYPT}', password)
        ELSE
            password
    END AS password,
    homedir AS userdb_home,
    maildir AS userdb_mail,
    CONCAT('*:bytes=', quota) AS userdb_quota_rule,
    uid AS userdb_uid,
    gid AS userdb_gid
FROM mailbox
WHERE username = '%Lu'
    AND ( access_restriction = 'ALL' OR LOCATE('%Us', access_restriction) > 0 )
Originally created by @PhrozenByte on GitHub (Apr 11, 2016). Original GitHub issue: https://github.com/opensolutions/ViMbAdmin/issues/178 [ViMbAdmin 3.0.15](https://github.com/opensolutions/ViMbAdmin/commit/166c13b7b0b939f08d9e4a4385e134ff56b0cc74#diff-4a46ed05e9c88660ea73c20a05701e5cR153) now recommends the `dovecot:BLF-CRYPT` password scheme by default. Needless to say that this is a significant improvement in comparison to the previous default `md5.salted` (no matter whether salting worked or not), but it still has some disadvantages: - Using the `dovecot:` password scheme family is a security issue in general, because it forces you to allow PHP to [use the `exec()` function](https://github.com/opensolutions/ViMbAdmin/blob/3.0.15/library/ViMbAdmin/Dovecot.php#L54). This function is disabled on many webservers on purpose. - Well secured systems using [SELinux](https://en.wikipedia.org/wiki/Security-Enhanced_Linux) or [AppArmor](https://en.wikipedia.org/wiki/AppArmor) will likely prevent PHP from executing the `doveadm` command when using the `dovecot:` password scheme family (see #95). ViMbAdmin therefore requires you to change the configuration of highly security sensitive system components. Breaking the configuration may even prevent you from booting your system. - The `dovecot:` password scheme family also requires you to install ViMbAdmin on the same machine as Dovecot. This prevents service separation or at least makes it more difficult. Additionally, just think of using Docker. - The Dovecot packages shipped with widely used Linux distributions (like Debian) don't support `BLF-CRYPT`. You will need to compile your own version of `libc` with enabled Blowfish support to make this work. It's definitely the most secure password scheme, but shouldn't be recommended as default as long as it isn't widely supported. Now the funny part: **You don't need the `dovecot:` password scheme family** to allow users to use the most secure password schemes (`BLF-CRYPT`, `SHA512-CRYPT`, `SHA256-CRYPT`) - just use the `crypt:` password scheme family instead. They are completely identical! So, why does the `dovecot:` password scheme family work (provided that PHP is able to run `doveadm`) (nearly) out-of-the-box, whereas the `crypt:` password scheme family does not? It's simple: `doveadm` adds a `{…}` prefix (e.g. `{SHA512-CRYPT}`) indicating the used password scheme, so users don't have to tell Dovecot what password scheme is used. ViMbAdmin's `crypt:` password scheme doesn't add this prefix, so you will have to tell Dovecot the used password scheme by setting the `default_pass_scheme` option. ViMbAdmin should add the `{…}` prefix to the database, so Dovecot can determine the used password scheme without additional configuration and without using the `dovecot:` password scheme family. I can think of two possible solutions: 1. Refactor password generation in whole, so ViMbAdmin always stores the password with the appropriate prefix. This also allows users to change the default password scheme without loosing all passwords (at the moment you can't change the password scheme without making all passwords invalid). You will either have to drop support of the `dovecot:` password scheme family or add a additional column to store the used password scheme (e.g. `crypt:sha512`), otherwise it would be impossible for ViMbAdmin to distinguish between e.g. `dovecot:SHA512-CRYPT` and `crypt:sha512` (as said, they are identical). 2. Add a new `password_dovecot` column which extends the existing `password` column by the appropriate `{…}` prefix. The new column actually is never read by ViMbAdmin, it's just used by Dovecot. Not the nicest, but definitely the easiest solution. It can be implemented with a very small number of additional lines of code. To prove that this works just fine, here's the SQL query I'm using as Dovecot's `password_query`. `default_pass_scheme` is unset. ViMbAdmin is configured with `defaults.mailbox.password_scheme = "crypt:sha512"`. I'm using a `CASE` statement to distinguish between the most important password schemes (namely the `crypt:` and `dovecot:` password scheme families), a solution built into ViMbAdmin obviously won't require such a hack and supports all (possible) password schemes of all password scheme families. I switched from `SHA256-CRYPT` to `SHA512-CRYPT` on-the-fly (i.e. without resetting a single password) not long ago. ``` sql SELECT username AS user, CASE WHEN password LIKE '{%}%' THEN password WHEN password LIKE '$1$%' THEN CONCAT('{MD5}', password) WHEN password LIKE '$2a$%' THEN CONCAT('{BLF-CRYPT}', password) WHEN password LIKE '$5$%' THEN CONCAT('{SHA256-CRYPT}', password) WHEN password LIKE '$6$%' THEN CONCAT('{SHA512-CRYPT}', password) ELSE password END AS password, homedir AS userdb_home, maildir AS userdb_mail, CONCAT('*:bytes=', quota) AS userdb_quota_rule, uid AS userdb_uid, gid AS userdb_gid FROM mailbox WHERE username = '%Lu' AND ( access_restriction = 'ALL' OR LOCATE('%Us', access_restriction) > 0 ) ```
Author
Owner

@barryo commented on GitHub (Apr 12, 2016):

Hi @PhrozenByte - yip, I agree with:

ViMbAdmin should add the {…} prefix to the database

In fact in trying to conjure up various fixes to the issue that prompted this, allowing multiple password schemes is really the only solution.

What above a second column that defines the schema used? Advantages:

  • use CONCAT() to get the Dovecot version
  • still allows for the existing setup unchanged
  • doesn't add the password twice
  • allows flexibility for other systems
<!-- gh-comment-id:208728567 --> @barryo commented on GitHub (Apr 12, 2016): Hi @PhrozenByte - yip, I agree with: > ViMbAdmin should add the {…} prefix to the database In fact in trying to conjure up various fixes to the issue that prompted this, allowing multiple password schemes is really the only solution. What above a second column that defines the schema used? Advantages: - use CONCAT() to get the Dovecot version - still allows for the existing setup unchanged - doesn't add the password twice - allows flexibility for other systems
Author
Owner

@PhrozenByte commented on GitHub (Apr 12, 2016):

Yeah, sounds reasonable to me 👍 😃

<!-- gh-comment-id:208843192 --> @PhrozenByte commented on GitHub (Apr 12, 2016): Yeah, sounds reasonable to me :+1: :smiley:
Author
Owner

@pquan commented on GitHub (Apr 13, 2016):

If the {...} is not in the database, dovecot will fail to authenticate users with an error like this:

Password data is not valid for scheme : Input isn't valid base64 encoded data

Adding the {..} will make it work.

Currently vimbadmin is striping the {..} generated by "doveadm pw -s '' -u 'user@domain' -p 'password'

This is a "bug" when not using the default MD5 cipher

<!-- gh-comment-id:209356175 --> @pquan commented on GitHub (Apr 13, 2016): If the {...} is not in the database, dovecot will fail to authenticate users with an error like this: Password data is not valid for scheme <SCHEME>: Input isn't valid base64 encoded data Adding the {..} will make it work. Currently vimbadmin is striping the {..} generated by "doveadm pw -s '<CIPHER>' -u 'user@domain' -p 'password' This is a "bug" when not using the default MD5 cipher
Author
Owner

@barryo commented on GitHub (Apr 13, 2016):

Hi @pquan - it's only a bug if allowing multiple password schemes to be supported simultaneously was/is meant to be a feature 😉

It wasn't but this issue is about supporting that.

Note also that ViMbAdmin isn't just for Dovecot so how this is supported needs to be more flexible. Presenting the {scheme} to Dovecot would be just a matter of crafting your SQL query with CONCAT().

<!-- gh-comment-id:209359115 --> @barryo commented on GitHub (Apr 13, 2016): Hi @pquan - it's only a bug if allowing multiple password schemes to be supported simultaneously was/is meant to be a feature 😉 It wasn't but this issue is about supporting that. Note also that ViMbAdmin isn't _just for Dovecot_ so how this is supported needs to be more flexible. Presenting the `{scheme}` to Dovecot would be just a matter of crafting your SQL query with `CONCAT()`.
Author
Owner

@nysander commented on GitHub (Feb 5, 2017):

for me this should be a config option "Do you use Dovecot" which changes line 59 in Dovecot.php library file from:

        return trim( substr( $a, strlen( $scheme ) + 2 ) );

to

        return trim( $a );

because this easily make doveadm pw generated passwords compatible with Dovecot setup without any tricks and complicated SQL queries.

<!-- gh-comment-id:277499022 --> @nysander commented on GitHub (Feb 5, 2017): for me this should be a config option "Do you use Dovecot" which changes [line 59](https://github.com/opensolutions/ViMbAdmin/blob/master/library/ViMbAdmin/Dovecot.php#L59) in **Dovecot.php** library file from: return trim( substr( $a, strlen( $scheme ) + 2 ) ); to return trim( $a ); because this easily make **doveadm pw** generated passwords compatible with Dovecot setup without any tricks and complicated SQL queries.
Author
Owner

@mfechner commented on GitHub (May 29, 2020):

I use this modification since 16.12.2018:
github.com/mfechner/ViMbAdmin@9495046e50

And I have not seen any errors. But I only use dovecot and no other imap server. Postfix is using dovecot also for authentication.

I used this modification also to switch all users to newer more secure password hashes where dovecot automatically updates the hash if the user logs in:
https://wiki.dovecot.org/HowTo/ConvertPasswordSchemes

<!-- gh-comment-id:635850370 --> @mfechner commented on GitHub (May 29, 2020): I use this modification since 16.12.2018: https://github.com/mfechner/ViMbAdmin/commit/9495046e5038a27112dcce1d6d15a6f977e8a44e And I have not seen any errors. But I only use dovecot and no other imap server. Postfix is using dovecot also for authentication. I used this modification also to switch all users to newer more secure password hashes where dovecot automatically updates the hash if the user logs in: https://wiki.dovecot.org/HowTo/ConvertPasswordSchemes
Author
Owner

@barryo commented on GitHub (Apr 1, 2022):

Time out closing on this - please reopen if help still required.

<!-- gh-comment-id:1086289523 --> @barryo commented on GitHub (Apr 1, 2022): Time out closing on this - please reopen if help still required.
Author
Owner

@PhrozenByte commented on GitHub (Apr 1, 2022):

@barryo Since you've closed a whole lot of dangling issues, I reckon that you just overlooked that this is not a help request, but a feature request. You even already acknowledged that it should be implemented (at some point, possibly never if nobody else picks it up, but nevertheless). So, if desired, you (only contributors can) might wanna reopen it 👍

<!-- gh-comment-id:1086372383 --> @PhrozenByte commented on GitHub (Apr 1, 2022): @barryo Since you've closed a whole lot of dangling issues, I reckon that you just overlooked that this is not a help request, but a feature request. You even already acknowledged that it should be implemented (at some point, possibly never if nobody else picks it up, but nevertheless). So, if desired, you (only contributors can) might wanna reopen it :+1:
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/ViMbAdmin-opensolutions#139
No description provided.