Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dovecotpw needs to read my TLS certificate and its private key #398

Closed
AlphaJack opened this issue Nov 28, 2020 · 25 comments
Closed

Dovecotpw needs to read my TLS certificate and its private key #398

AlphaJack opened this issue Nov 28, 2020 · 25 comments

Comments

@AlphaJack
Copy link

AlphaJack commented Nov 28, 2020

I can't find it documented anywhere and I also don't understand the logic behind this: why does PostfixAdmin need to read my TLS certificate private key to allow login or create users?

Postfix, Dovecot and IMAP clients work well with the default ownership and permissions settings of Let's Encrypt files and folders (probably because their master processes are run as root), however to login on PostfixAdmin or create an account I need to run, as root:

# replace "postfixadmin" with your php-fpm user group, e.g. "www-data" for Ubuntu

# from root:root
chown root:postfixadmin /etc/letsencrypt/live/example.org/privkey.pem
chown root:postfixadmin /etc/letsencrypt/live
chown root:postfixadmin /etc/letsencrypt/archive

# from 600
chmod 640 /etc/letsencrypt/live/example.org/privkey.pem

# from 700
chmod 750 /etc/letsencrypt/live
chmod 750 /etc/letsencrypt/archive

If settings are different from above, when logging in, the page will simply refresh, throwing this vague error in NginX error log:

2020/11/28 01:08:46 [error] 534#534: *548 FastCGI sent in stderr: 
"PHP message: PostfixAdmin login failed (username: admin@example.org, ip_address: 127.0.0.1)" 
while reading response header from upstream, client: 127.0.0.1, server: postfixadmin, request: "POST /login.php HTTP/1.0", upstream: "fastcgi://unix:/run/postfixadmin/postfixadmin.sock:", host: "example.org"

By creating a new admin from setup.php the error gets more useful:

2020/11/28 01:11:36 [error] 534#534: *641 FastCGI sent in stderr: 
"PHP message: dovecotpw password encryption failed. STDERR output: doveconf: Fatal: Error in configuration file /etc/dovecot/dovecot.conf line 154: ssl_cert: Can't open file /etc/letsencrypt/live/example.org/fullchain.pem: Permission denied"
while reading response header from upstream, client: 127.0.0.1, server: postfixadmin, request: "POST /setup.php HTTP/1.0", upstream: "fastcgi://unix:/run/postfixadmin/postfixadmin.sock:", host: "example.org"

By changing ownership and permissions of only the directories /etc/letsencrypt/live and /etc/letsencrypt/archive, the error becomes:

2020/11/28 01:14:22 [error] 534#534: *641 FastCGI sent in stderr: 
"PHP message: dovecotpw password encryption failed. STDERR output: doveconf: Fatal: Error in configuration file /etc/dovecot/dovecot.conf line 154: ssl_key: Can't open file /etc/letsencrypt/live/example.org/privkey.pem: Permission denied"
while reading response header from upstream, client: 127.0.0.1, server: postfixadmin, request: "POST /setup.php HTTP/1.0", upstream: "fastcgi://unix:/run/postfixadmin/postfixadmin.sock:", host: "example.org"
@DavidGoodwin
Copy link
Member

it's an issue with dovecot / doveadm, not technically postfixadmin. Although postfixadmin calls doveadm, which is why you see the problem.

@DavidGoodwin
Copy link
Member

see also #379

@DavidGoodwin
Copy link
Member

see also - #382 - which probably has a fix

@AlphaJack
Copy link
Author

Ok, I see, thank you.
Do you have any clue on why doveadm pw needs to access dovecot configuration and read some of the files listed there to generate a simple password hash?

@DavidGoodwin
Copy link
Member

I don't know why; it's a dovecot change.

@AlphaJack
Copy link
Author

I've reached out Dovecot developers asking if read access in doveadm pw is really required, I will post updates when they will reply.

For the auth problem, I see that it goes away with my workaround, but I don't understand why: if PostfixAdmin has direct access to the mail database, why it can't authenticate neither admins nor even regular users? How does the authentication work?

It doesn't seem to use neither an auth socket created by Dovecot, nor the command doveadm auth (which would obviously require read access to dovecot.conf)

@piiskop
Copy link

piiskop commented Dec 2, 2020

I see that it goes away with my workaround

I don't see it:

chown root:postfixadmin /etc/letsencrypt/live/test.tennis24.ee/privkey.pem
chown: vigane grupp: `root:postfixadmin'

There's no such group as postfixadmin. And it complains about fullchain.pem:

[Wed Dec 02 16:08:15.393508 2020] [php7:notice] [pid 1636] [client 192.168.1.65:48922] STDERR output: doveconf: Fatal: Error in configuration file /etc/dovecot/conf.d/10-ssl.conf line 13: ssl_cert: Can't open file /etc/letsencrypt/live/test.tennis24.ee/fullchain.pem: Permission denied\n, referer: https://postfixadmin.tennis24.ee/setup.php

@AlphaJack
Copy link
Author

You should use the main group of the user running the php-fpm pool for PostfixAdmin. Another way (not reccomended) is to make the file world readable via chmod +r.

The group name depends on your system, it may be "www-data" in Ubuntu, the package in Arch Linux repos creates the specific user "postfixadmin" for this task.

You could test it even with your normal user: if you don't have read access to /etc/dovecot/dovecot.conf and you run doveadm pw -p XXXXXX, you get an error:

doveconf: Fatal: open(/etc/dovecot/dovecot.conf) failed: Permission denied (copy example configs from /usr/share/doc/dovecot/example-config/)

If you are able to read dovecot.conf with your normal user, you get a similar error for other files you aren't allowed to read (as you already saw):

doveconf: Fatal: Error in configuration file /etc/dovecot/dovecot.conf line 155: ssl_cert: Can't open file /etc/letsencrypt/live/example.org/fullchain.pem: Permission denied

For instance, if you specified a dhparam file, you need to read it as well to create a password hash through doveadm.
I am absolutely not an expert here, but the program seems to require more than it needs to launch the function pw

@DavidGoodwin
Copy link
Member

  1. Login is failing because you've configured Postfixadmin to use dovecot for it's hashing mechanism.
  2. Check the value of 'encrypt' within config.local.php (or config.inc.php). I assume yours is dovecot:
  3. I don't know what's in your database, but it may be possible to change to a different hash backend (e.g. from dovecot:sha256 to php_crypt:SHA256

@piiskop
Copy link

piiskop commented Dec 2, 2020

2. Check the value of 'encrypt' within config.local.php (or config.inc.php). I assume yours is dovecot:

$CONF['encrypt'] = 'dovecot:ARGON2I';

@piiskop
Copy link

piiskop commented Dec 2, 2020

3. change to a different hash backend (e.g. from dovecot:sha256 to php_crypt:SHA256

After the change and restart of apache2:

[Wed Dec 02 16:45:26.615145 2020] [authz_core:debug] [pid 28110] mod_authz_core.c(809): [client 192.168.1.65:49412] AH01626: authorization result of Require all granted: granted, referer: https://postfixadmin.tennis24.ee/setup.php
[Wed Dec 02 16:45:26.615186 2020] [authz_core:debug] [pid 28110] mod_authz_core.c(809): [client 192.168.1.65:49412] AH01626: authorization result of : granted, referer: https://postfixadmin.tennis24.ee/setup.php
[Wed Dec 02 16:45:26.627731 2020] [php7:warn] [pid 28110] [client 192.168.1.65:49412] PHP Warning: Cannot assign an empty string to a string offset in /usr/share/postfixadmin/variables.inc.php on line 31, referer: https://postfixadmin.tennis24.ee/setup.php
[Wed Dec 02 16:45:26.728127 2020] [deflate:debug] [pid 28110] mod_deflate.c(854): [client 192.168.1.65:49412] AH01384: Zlib: Compressed 1314 to 730 : URL /setup.php, referer: https://postfixadmin.tennis24.ee/setup.php

After another try, I got:

unknown/invalid $CONF["encrypt"] setting: php_crypt:SHA256

After I changed the value to system, I could create a new admin and change the password for another admin. This however didn't solve the problem that the only mail account created in the system kalmer@test.tennis24.ee only receives system log mails three times a day and no other mail will be received that I send to myself from other accounts. Sending out works well but not receiving.

@piiskop
Copy link

piiskop commented Dec 2, 2020

You should use the main group of the user running the php-fpm pool for PostfixAdmin.

Well, I did it:

root@test:/etc/letsencrypt/live/test.tennis24.ee# chown root:www-data /etc/letsencrypt/live/test.tennis24.ee/fullchain.pem
root@test:/etc/letsencrypt/live/test.tennis24.ee# l -la
kokku 12
drwxr-xr-x 2 root root 4096 dets 2 02:33 ./
drwxr-x--- 10 root www-data 4096 juuli 6 17:03 ../
lrwxrwxrwx 1 root root 40 dets 2 02:33 cert.pem -> ../../archive/test.tennis24.ee/cert4.pem
lrwxrwxrwx 1 root root 41 dets 2 02:33 chain.pem -> ../../archive/test.tennis24.ee/chain4.pem
lrwxrwxrwx 1 root root 45 dets 2 02:33 fullchain.pem -> ../../archive/test.tennis24.ee/fullchain4.pem
lrwxrwxrwx 1 root root 43 dets 2 02:33 privkey.pem -> ../../archive/test.tennis24.ee/privkey4.pem
-rw-r--r-- 1 root root 682 juuni 26 14:24 README

As you see, the system doesn't change the group for these files. All these files are world-readable anyway. But postfixadmin or dovecot still fails to get access to them.

Meanwhile, checking for new messages to kalmer@test.tennis24.ee, I get an error message in Thunderbird for having an incorrect authentication method which is normal password.

@AlphaJack
Copy link
Author

AlphaJack commented Dec 2, 2020

They appear world readable because files under "live" are links, however the real file permission could be (and probably are) different.

By running that command directed to /etc/letsencrypt/live/test.tennis24.ee/fullchain.pem you have changed the permissions of /etc/letsencrypt/archive/test.tennis24.ee/fullchain.pem.

You should then check directory permissions, because even if the right files are accessible to the correct group, they may still be located behind inaccessible folders:

  • /etc should be 755
  • /etc/letsencrypt should be 755
  • /etc/letsencrypt/live could be 700, change it to 750 and change the ownership to root:www-data. Same for "archive"
  • /etc/letsencrypt/live/example.org should be 755. Same for "archive"

Once you modified the permissions correctly, you should see the following inside /etc/letsencrypt/archive/example.org

-rw-r--r-- 1 root root 1.9K Nov 26 22:02 cert1.pem
-rw-r--r-- 1 root root 1.7K Nov 26 22:02 chain1.pem
-rw-r--r-- 1 root root 3.5K Nov 26 22:02 fullchain1.pem
-rw------- 1 root root 1.7K Nov 26 22:02 privkey1.pem

The only file that returns problem now is privkey1.pem, that you could either

  • chown root:www-data AND chmod 640
  • chmod 644 (not suggested)

Remember that folders need the execution permission, so you want 750 instead of 640 for a folder accessible by both owner and group.
Note that if privkey1.pem has a permission of 600 it means that the group www-data has still no access to it, even if it is owned by that group, you need at least 640.

@piiskop
Copy link

piiskop commented Dec 2, 2020

My file permissions seem to be suitable according to your suggestions:

  • root@test:/# l -la /etc/letsencrypt/archive/test.tennis24.ee/
  • kokku 72
  • drwxr-xr-x 2 root root 4096 dets 2 02:33 ./
  • drwxr-x--- 10 root www-data 4096 juuli 6 17:03 ../
  • -rw-r--r-- 1 root root 1915 juuni 26 14:24 cert1.pem
  • -rw-r--r-- 1 root root 1915 aug 25 13:31 cert2.pem
  • -rw-r--r-- 1 root root 1915 okt 24 23:16 cert3.pem
  • -rw-r--r-- 1 root root 1911 dets 2 02:33 cert4.pem
  • -rw-r--r-- 1 root root 1647 juuni 26 14:24 chain1.pem
  • -rw-r--r-- 1 root root 1647 aug 25 13:31 chain2.pem
  • -rw-r--r-- 1 root root 1647 okt 24 23:16 chain3.pem
  • -rw-r--r-- 1 root root 1647 dets 2 02:33 chain4.pem
  • -rw-r--r-- 1 root root 3562 juuni 26 14:24 fullchain1.pem
  • -rw-r--r-- 1 root root 3562 aug 25 13:31 fullchain2.pem
  • -rw-r--r-- 1 root root 3562 okt 24 23:16 fullchain3.pem
  • -rw-r----- 1 root www-data 3558 dets 2 02:33 fullchain4.pem
  • -rw-r--r-- 1 root root 1704 juuni 26 14:24 privkey1.pem
  • -rw-r--r-- 1 root root 1704 aug 25 13:31 privkey2.pem
  • -rw-r--r-- 1 root root 1704 okt 24 23:16 privkey3.pem
  • -rw-r----- 1 root www-data 1704 dets 2 02:33 privkey4.pem
  • root@test:/# l -la /etc/letsencrypt/live/test.tennis24.ee/
  • kokku 12
  • drwxr-xr-x 2 root root 4096 dets 2 02:33 ./
  • drwxr-x--- 10 root www-data 4096 juuli 6 17:03 ../
  • lrwxrwxrwx 1 root root 40 dets 2 02:33 cert.pem -> ../../archive/test.tennis24.ee/cert4.pem
  • lrwxrwxrwx 1 root root 41 dets 2 02:33 chain.pem -> ../../archive/test.tennis24.ee/chain4.pem
  • lrwxrwxrwx 1 root root 45 dets 2 02:33 fullchain.pem -> ../../archive/test.tennis24.ee/fullchain4.pem
  • lrwxrwxrwx 1 root root 43 dets 2 02:33 privkey.pem -> ../../archive/test.tennis24.ee/privkey4.pem
  • -rw-r--r-- 1 root root 682 juuni 26 14:24 README

Meanwhile, I was able to make kalmer@test.tennis24.ee to receive messages from outside by opening the port 25 for public. Currently, I have the following ports open for public: 22, 25, 80, 143, 443 and 587. Do I need some other ports to be open for public? Can that be connected to the issue that postfixadmin can't let me in because dovecot fails to read fullchain.pem?

For logging in to kalmer@test.tennis24.ee using postfixadmin:

[Wed Dec 02 17:44:28.472695 2020] [authz_core:debug] [pid 30964] mod_authz_core.c(809): [client 192.168.1.65:50900] AH01626: authorization result of Require all granted: granted, referer: https://postfixadmin.tennis24.ee/login.php
[Wed Dec 02 17:44:28.472756 2020] [authz_core:debug] [pid 30964] mod_authz_core.c(809): [client 192.168.1.65:50900] AH01626: authorization result of : granted, referer: https://postfixadmin.tennis24.ee/login.php
[Wed Dec 02 17:44:28.473093 2020] [php7:warn] [pid 30964] [client 192.168.1.65:50900] PHP Warning: Cannot assign an empty string to a string offset in /usr/share/postfixadmin/variables.inc.php on line 31, referer: https://postfixadmin.tennis24.ee/login.php
[Wed Dec 02 17:44:28.565304 2020] [php7:notice] [pid 30964] [client 192.168.1.65:50900] PostfixAdmin login failed (username: kalmer@test.tennis24.ee), referer: https://postfixadmin.tennis24.ee/login.php
[Wed Dec 02 17:44:28.567102 2020] [deflate:debug] [pid 30964] mod_deflate.c(854): [client 192.168.1.65:50900] AH01384: Zlib: Compressed 3946 to 1582 : URL /login.php, referer: https://postfixadmin.tennis24.ee/login.php

For setting up a new admin:

[Wed Dec 02 17:46:34.389121 2020] [authz_core:debug] [pid 30235] mod_authz_core.c(809): [client 192.168.1.65:50934] AH01626: authorization result of Require all granted: granted, referer: https://postfixadmin.tennis24.ee/setup.php
[Wed Dec 02 17:46:34.389149 2020] [authz_core:debug] [pid 30235] mod_authz_core.c(809): [client 192.168.1.65:50934] AH01626: authorization result of : granted, referer: https://postfixadmin.tennis24.ee/setup.php
[Wed Dec 02 17:46:34.389369 2020] [php7:warn] [pid 30235] [client 192.168.1.65:50934] PHP Warning: Cannot assign an empty string to a string offset in /usr/share/postfixadmin/variables.inc.php on line 31, referer: https://postfixadmin.tennis24.ee/setup.php
[Wed Dec 02 17:46:34.411416 2020] [php7:notice] [pid 30235] [client 192.168.1.65:50934] dovecotpw password encryption failed., referer: https://postfixadmin.tennis24.ee/setup.php
[Wed Dec 02 17:46:34.411442 2020] [php7:notice] [pid 30235] [client 192.168.1.65:50934] STDERR output: doveconf: Warning: NOTE: You can get a new clean config file with: doveconf -Pn > dovecot-new.conf\ndoveconf: Warning: Obsolete setting in /etc/dovecot/conf.d/10-ssl.conf:51: ssl_protocols has been replaced by ssl_min_protocol\ndoveconf: Error: ssl enabled, but ssl_dh not set\ndoveconf: Fatal: Invalid configuration\n, referer: https://postfixadmin.tennis24.ee/setup.php
[Wed Dec 02 17:46:34.412147 2020] [deflate:debug] [pid 30235] mod_deflate.c(854): [client 192.168.1.65:50934] AH01384: Zlib: Compressed 1320 to 732 : URL /setup.php, referer: https://postfixadmin.tennis24.ee/setup.php

This time, the error message is different. It complains about missing ssl_dh. I have no idea what that is. To get an idea what that is, I digged around in Internet and found no answer. So I went to the page with instructions I followed while I was creating the whole mail server system for the first time and found in the comments section how to get rid of that erroneous situation:

root@test:/# emacs /etc/dovecot/conf.d/10-ssl.conf

There, I put:

ssl_dh=</etc/dovecot/dh.pem

Then:

root@test:/# dd if=/var/lib/dovecot/ssl-parameters.dat bs=1 skip=88 | openssl dhparam -inform der | sudo tee /etc/dovecot/dh.pem
142+0 kirjet sisse
142+0 kirjet välja
142 baiti kopeeritud, 0,000339941 s, 418 kB/s
-----BEGIN DH PARAMETERS-----
MIGHAoGBAJixno3amM7FEaK5s4qqbY+A0p/xN2hc7nq03Q2gMi+fanjRBAOj7K00
zk0L7uqx8i175ImbjWxCSSxnLEzATW6U/gWyfS5504YjyL+rKH+KZ33PZDqglgJY
qlz1KFI08cxPErOjG1jyvJadmgaghQjKvFV9ThHz3REYx/XErISjAgEC
-----END DH PARAMETERS-----
root@test:/# sudo systemctl restart dovecot

After that, I could create a new admin and I could even log in to an admin account that I haven't deleted from the database.

Why is everything else straightforward to set up but setting up a mail server system has 11 books of instructions with comments?

@AlphaJack
Copy link
Author

AlphaJack commented Dec 2, 2020

Files seems good, if you run sudo -u www-data nano /etc/letsencrypt/live/test.tennis24.ee/privkey.pem and sudo -u www-data nano /etc/letsencrypt/live/test.tennis24.ee/fullchain.pem are you able to read the files?

Note that Postfix and Dovecot can work well even if PostfixAdmin isn't working (or installed at all)

Do I need some other ports to be open for public? Can that be connected to the issue that postfixadmin can't let me in because dovecot fails to read fullchain.pem?

I don't think so. The ports I use for mail are:

  • 25 (SMTP): required to receive emails from others. No way you can assign a different port to this task
  • 465 (submissionS): send mail using Postfix. You use 587 (submission) for that, it's fine.
  • 993 (IMAPS): access my inbox using Dovecot. You use 143 (IMAP) for that, I disabled it and switched to full encryption only.

It complains about missing ssl_dh. I have no idea what that is.

Check out the link I sent before regarding Diffie-Hellman parameters:

For instance, if you specified a dhparam file, you need to read it as well to create a password hash through doveadm.

I don't have anymore that option, but I use

ssl_min_protocol = TLSv1.2

Why is everything else straightforward to set up but setting up a mail server system has 11 books of instructions with comments?

I agree on that, I had to dig a lot of wikis, blog posts and documentations to get a fully modular setup. But when you achieve it, it gives you a sensation of pride and accomplishment that other services don't usually do.
To be honest, I still can't find a reason on why people create the user "vmail" with uid of 5000, a system user (uid<1000) with no special uid does the trick for me, there seem to be a lot of copy-paste and deprecated settings that even the most recent setups follow.
See at dh params, even the Arch Wiki tells to create them, even if Dovecot documentation suggests to disable non-ECC DH algorithms completely.

Congratulations, you did it 😉

@AlphaJack
Copy link
Author

Still no reply from Dovecot devs

SaraSmiseth added a commit to SaraSmiseth/postfixadmin that referenced this issue Jan 15, 2021
SaraSmiseth added a commit to mailserver2/postfixadmin that referenced this issue Jan 24, 2021
* update to alpine:3.13 and php8

* update postfixadmin to 3.3.4

* install new dependency: php8-pdo, php8-pdo_pgsql and php8-pdo_mysql

* temporary workaround for doveadm pw reading server.key.
See also postfixadmin/postfixadmin#398.

* run upgrade.php at start

* Update HASH lenght check. The HASH generated by setup.php is now 60 characters long.
@joh-ku
Copy link

joh-ku commented May 18, 2021

Applying different permissions to key files is imho never a good solution.

It is possible to workaround this issue. Create a file e.g. ssl-keys.conf and move the ssl_key and ssl_cert keys of dovecot (normally in 10-ssl.conf) into this file. Give the newly created file permission 600 and set as owner root.

Then include this file in your dovecot.conf with this line !include_try ssl-keys.conf.

Restart dovecot and you should be able to call doveadm pw with a non-privileged user like e.g. www-data.

See this discussion for further reference.

@AlphaJack
Copy link
Author

Applying different permissions to key files is imho never a good solution.

I knowm but I'd rather revoke those permissions whenever I don't need the postfixadmin (www-data) user to read my private TLS key (99.99% of the times, and it shouldn't be required in the first place even for that 0.01%).

@DavidGoodwin
Copy link
Member

see also : #491 - probably needs rewriting again - but hopefully there's a solution in the making

@joh-ku
Copy link

joh-ku commented May 19, 2021

I knowm but I'd rather revoke those permissions whenever I don't need the postfixadmin (www-data) user to read my private TLS key (99.99% of the times, and it shouldn't be required in the first place even for that 0.01%).

The postfixadmin user does not need to read your key. The error message is displayed depending on your dovecot configuration. That's why I commented above. You can leave those permissions untouched.

see also : #491 - probably needs rewriting again - but hopefully there's a solution in the making

Good to know, thanks!

@AlphaJack
Copy link
Author

Ok, I see, I can move secrets away from the main dovecot.conf using !include_try and strict permissions, and then make dovecot.conf world readable in order to get doveadm to work.
Thanks!

@mulderij
Copy link

mulderij commented Mar 6, 2022

An alternative is through php_crypt and then modify the Dovecot password query against MariaDB.

/etc/postfixadmin/config.local.php

$CONF['encrypt'] = 'php_crypt:SHA512';

/etc/dovecot/dovecot-sql.conf.ext

password_query = \
  SELECT \
  CASE \
    WHEN LEFT(password,4) = '$2y$' THEN CONCAT('{CRYPT}', password) \
    WHEN LEFT(password,3) = '$6$' THEN CONCAT('{SHA512-CRYPT}', password) \
    WHEN LEFT(password,3) = '$5$' THEN CONCAT('{SHA256-CRYPT}', password) \
    WHEN LEFT(password,3) = '$1$' THEN CONCAT('{MD5-CRYPT}', password) \
  END AS password \
  FROM mailbox \
  WHERE username='%u'

This doesn't add the the string for the encryption method in the database, but adds it in the result returned to Dovecot. For some unclear reason Dovecot needs this (the $&lt;code&gt;$ should have been enough). Of course if you are only using sha512 not all rewrite cases are necessary, but they don't hurt...

@mvasi90
Copy link

mvasi90 commented Jan 28, 2024

I really don't understand people. I'm reading the comments, and I see the people are juggling with system permissions and the security.

· Having read permissions for others in dovecot configuration files allows anyone to read database passwords and other sensitive configuration. My /etc/dovecot/ files permissions are 0640.
doveadm pw is not running at all with an unprivileged user other than dovecot because it needs access to /run/dovecot, /etc/dovecot/, /etc/letsencrypt/, etc.
Nobody understands why the pw command reads the ssl certs/keys and the configuration files.

· Adding the dovecot group to the postfixadmin or www-data user is giving away access to anyone who finds a vulnerability in the web service, to the entire dovecot configuration, including certificates and ssl keys.

This issue was created 4 years ago. The stable version 3.3.13 (as of 2024-01-28) still has no native solution for doveadm pw (argon2id) hashes.

I don't want a new and maybe unstable master branch on my system. Then, to solve this problem I created a small bash script that emulates the behavior of the doveadm pw with the following differences:

· It does not need any special access to any file, because it does not read any file.
· It works without root privileges.
· It uses native argon2 tool for creating and verifying the hash.

Here is the source code.
I do not want any kind of recognition or mention of my name. I am not one of those who want to see their name on fences when walking down the streets.

#!/bin/bash

# This script emulates the behavior of "doveadm pw". You can use it on PostfixAdmin
# for generating and checking argon2 hashes natively.
#
# The latest version of Dovecot requires access to /etc/dovecot/,
# /run/dovecot and /etc/letsencrypt/ when running "doveadm pw" 
#
# Run doveadm pw is impossible without changing permissions to all the above files/folders
# or adding the dovecot group to the postifxadmin user. This is a security risk.
#
# To solve that without breaking the security use this script.
#
# 1. Copy this script to /usr/local/bin and set execution permission 0755.
# 2. Edit the file /etc/webapps/postfixadmin/config.local.php and insert the next line:
#
# $CONF['dovecotpw'] = '/usr/local/bin/postfixadmin-pw';
#
# That's all.
#
# Author: nobody
# Copyright = Copyleft = Copyup = Copydown = Copymadafaka
# You can do what do you want. It's your code. No mentions, no names on walls.

if [[ "$(stat -c "%a" "$0")" != "755" ]]; then
  >&2 echo "Wrong file permissions. Must be 0755"
  exit
fi

if [[ -p /dev/stdin ]]; then
  IFS= read -r pass
  if [[ "${4}" == {ARGON2ID}* ]]; then
    v="$(echo -n ${4} | sed 's/.*v=\([0-9]\+\).*/\1/')"
    v=$(printf "%x" $v) # version in hex (19 = 0x13)
    m="$(echo -n ${4} | sed 's/.*m=\([0-9]\+\).*/\1/')"
    t="$(echo -n ${4} | sed 's/.*t=\([0-9]\+\).*/\1/')"
    p="$(echo -n ${4} | sed 's/.*p=\([0-9]\+\).*/\1/')"
    salt="$(echo -n ${4} | sed 's/.*\$\([^$]\+\)$.*/\1/')"
    pass_hash="$(echo -n ${4} | sed 's/.*\$.*\$\(.*\).*/\1/')"
    salt_padding=$((4- ${#salt} % 4))
    [[ $salt_padding -gt 0 ]] &&  [[ $salt_padding -lt 4 ]] && salt+="$(printf "=%.0s" $(seq 1 $salt_padding))"
    salt=$(echo -n "$salt" | base64 -d)
    new_hash=$(echo -n "$pass" | echo "{ARGON2ID}$(/usr/bin/argon2 "$salt" -id -k $m -t $t -p $p -e -v $v -l 32)")
    new_pass_hash="$(echo -n "$new_hash" | sed 's/.*\$.*\$\(.*\).*/\1/')"
    [[ "$pass_hash" = "$new_pass_hash" ]] && echo "$new_hash (verified)" || echo "Fatal: reverse password verification check failed: Password mismatch"
  else
    echo -n "$pass" | echo "{ARGON2ID}$(/usr/bin/argon2 $(openssl rand -hex 8) -id -k 65536 -t 3 -p 1 -e -v 13 -l 32)"
  fi

else
  >&2 echo "Missing password"
fi

Have a nice life!

@DavidGoodwin
Copy link
Member

thanks @mvasi90

@Icel3lade
Copy link

Icel3lade commented Apr 7, 2024

I really don't understand people. I'm reading the comments, and I see the people are juggling with system permissions and the security.

My Hero! 👍 Completely agree, thank you so much!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants