User Password Changes in Poste IO

So, I deployed Poste IO in Docker. Mostly to enable me to setup some other containers and be able to give them some burner emails. But, also a little bit because I liked the idea I had read about somewhere about using temporary email addresses as a means of fighting spam and determining who is leaking my personal information.

And, for a while, this setup was perfect. One man, managing many email addresses, but they all belong to me.

Then I invited my family to use it if they wanted. 

All of a sudden, I have a minor problem; non-admin users can't change their password. And admin users can only really do so through the Admin UI. Not a great solution. Even if it is my family and they trust me, email can be personal. There is no reason for me to have access to other people's email, and even less reason that I should need to make everyone an admin.

So, I dug around. And while I find indicators that maybe one other person had tried this, I hadn't found a successful solution. One person looked like they were trying to update the DB directly, but I got even further than the post did and hit further issues with permissions around the DB file. 

And thus, I was forced to make my own solution.

NOTE: This is a bit of a hack and I KNOW that there are better ways of doing this. At the same time, the approach I took is probably perfectly fine for pretty much anyone looking into this. Especially since the biggest hack was when I hi-jacked an existing password driver and you can only have 1 configured at a time.

Firstly, to describe the solution. I knew Poste IO was a bit of custom code and then a Docker image with a bunch of other projects pre-loaded. The Web UI was Roundcube. And I knew this was used by a number of other solutions. I assumed it MUST have this feature. And it does. Enabled via a plugin called "password". Using the default Docker image I can't actually change the plugin directly. And, the default plugin doesn't seem able to handle my needs. But, this seemed like the best starting point.

DISCLAIMER: I'm running the 2.2.22 tag of alaogic/poste.io. I can't guarantee this won't change. But, these changes SHOULD work on this particular version.

Step #1 - Extract the config file.

While I can't modify the config within the container and have the changes persisted, I CAN copy that file out of the container, modify it, and mount my copy over top of the one in the image. And that is exactly where I did. You'll want to run a command similar to this:

docker cp Poste_IO:/opt/www/webmail/config/config.inc.php ./ 

Replace "Poste_IO" with the name of your container in Docker and it should copy the config file into the current directory. Replace the "./" at the end if you want to copy it somewhere else. Then, about half way down the config file I found the following section and added the password plug-in to the list and overrode the driver (highlighted sections):

// ----------------------------------
// PLUGINS
// ----------------------------------
// List of active plugins (in plugins/ directory)
$config['plugins'] = array(
    'archive',
    'attachment_reminder',
    'emoticons',
    'enigma',
    'identity_select',
    'newmail_notifier',
    'managesieve',
    'vcard_attachments',
    'zipdownload',
    'dovecot_ident',
    'password'

);

// Update the password driver
$config['password_driver'] = 'chpasswd';

Don't miss the comma on the line above 'password'.

Step #2 - Extract the 'chpasswd' drivers php file.

You'll note above that I changed the password driver to 'chpasswd'. Mostly because this was the closest to what I wanted to accomplish. It already ran a bash script. Which, is exactly what we want to do in this version of poste.io. We want to call the "poste email:passwd" command. This is the only "approved" way of updating the password that I could find.

Also, I know you can change the chpasswd command via the configuration. But, there were 2 problems I could see; the format the account and password are supplied in are different, and the way the commands consume the parameters is different. Perhaps someone smarter than me can make it work without modifying the PHP. But, I'm a programmer and this was easy enough for me to do.

As with the config, we'll use the docker cp command again. This time, we'll be going after this file:

docker cp Poste_IO:/opt/www/webmail/plugins/password/drivers/chpasswd.php ./

As above, change the container name and output path if you want.

Then I replaced the original $cmd assignment with the following:

// $cmd = rcmail::get_instance()->config->get('password_chpasswd_cmd');
$cmd = "sudo /usr/sbin/poste email:passwd $username $newpass";

The first line above is the original, and the second line is mine.

I also change the $handle line from write to read:

$handle = popen($cmd, 'r');

And removed the line after this one which passed in the user and password as you can see we are doing that all in the $cmd variable now.

Step #3 - Granting the Necessary Permissions.

At this point, it STILL won't work. But, this is slightly well documented. The web server worker thread doesn't have permissions to run much outside of its own little bubble. The official documentation suggests adding a file to /etc/sudoers.d. And this is indeed the right solution. BUT, the poste.io container doesn't use the "apache" user as documented in the Roundcube documentation. Through some debugging, I was able to determine it happens under a user named "www-data".

So, I created a file called "99-roundcubemail" and put the following contents in it.

www-data ALL=(root) NOPASSWD:/usr/sbin/poste  
Defaults:www-data !requiretty

This basically says that the www-data user can call the poste command without requiring a password and that the user doesn't need the TTY role either. And, putting this in the /etc/sudoers.d folder tells the system that this user can use the SUDO command, which you can see we leverage in the modified chpasswd.php file.

So, now we just need to wire this all up. And that is done by adding the following lines to the volumes section of your docker-compose (or adding "-v" parameters for each in your docker run command):

      - <PATH TO FILES>/config.inc.php:/opt/www/webmail/config/config.inc.php
      - <PATH TO FILES>/99-roundcubemail:/etc/sudoers.d/99-roundcubemail:ro
      - <PATH TO FILES>/chpasswd.php:/opt/www/webmail/plugins/password/drivers/chpasswd.php 

Replace "<PATH TO FILES>" with wherever you stored all of the files we created/modified and this will mount those into the appropriate places within the container.

Step #4 - Test and Celebrate.

Then once everything is up and running, go into the web mail portal and test. Under the settings menu you should now find a "Password" section, and entering the new password should result in a notice that it succeeded. At which point you can log out and back in with the new credentials to verify.

And, if everything went well you can sit back and bask in the fact that it didn't take you hours to figure out why you couldn't make it update the DB, or why granting the "apache" user permissions didn't seem to magically solve your issues like I did.

Comments

  1. buddy, you have SAVED my life. I'm bookmarking this page

    ReplyDelete

Post a Comment

Popular Posts