Dovecot with PostgreSQL users database: Password hashing - postgresql

I'm trying to set up a Mail Server using Postfix and Dovecot.
I have my users stored in a PostgreSQL database with bcrypt hashed passwords.
After some researching, I found ways to read users from a PostgreSQL database, but with passwords stored in plain text.
How do I set up Dovecot to read users from a PostgreSQL database with bcrypt hashed passwords?

Dovecot fully supports the BLF-CRYPT password scheme since the recent 2.3 release apparently.
It shouldn't make a difference for PostgreSQL what kind of scheme is used, the password is just a text field in the database and it's stored and retrieved in its hashed textual form. The scheme used to hash is known by the first few characters of the password, for instance $2a$ for bcrypt.
Hashing the password can be can be done with doveadm -s BLF-CRYPT and the output copied into the password field of the database in the row corresponding to the user.
For the authentication, dovecot, like postfix, expects a user-supplied SQL query with some documented placeholders in its configuration (see password_query), so it doesn't need to assume any particular structure of a table or view of users.

Related

Making Docker PostgreSql secure - untrusting local connection, username & password max length

Context
So currently I am creating a setup/launcher script that sets up a secure docker container with PostgreSql database on the client's machine.
To make it really secure, my plan is for the script to:
Autogenerate a random username and password
Execute docker run (with -d postgres of course) and with the randomly generated username and password
Autogenerate another set of random username and password
Create a new user with the newly generated username and password
Grant the newly created user with appropriate permissions
Return the credentials (username & password) of the newly created user and not store (in other word forget) the superuser credentials (username & password)
Questions
What are the limitations of Postgresql's username and password? From this source, it seems that the username max length is 64 bytes (so 64 characters) and from this source it seems the max password length is 100 bytes (so 100 characters). Is the information accurate (the sources are pretty old, and I might have misunderstood it)? Also, are only allowed characters alphanumerical? Does it support Base64, MD5, or SHA?
I noticed that I can access the Postgres bash without providing the superuser's password. Upon further research, it seems it's due to the fact that upon creation of the Postgres database, local access is trusted as its automatically configured in pg_hba.conf. What is the command to untrust all connections, including the local one, and any superuser action needs to have a superuser password supplied?
Any suggestion to increase the security, even more, that does not involve self-hosting the database instead of having the client hosting it on his/her machine? (I am aware that this is a broad/off-topic question, therefore feel free to ignore this question)
username and password length:
user names are limited to 63 bytes, like all other identifiers (unless you want to rebuild PostgreSQL).
src/include/pg_config_manual.h has:
/*
* Maximum length for identifiers (e.g. table names, column names,
* function names). Names actually are limited to one less byte than this,
* because the length must include a trailing zero byte.
*
* Changing this requires an initdb.
*/
#define NAMEDATALEN 64
The maximum length of the password depends on the password encryption method and the authentication used. For scram-sha-256, the limit is 1024.
See src/common/saslprep.c:
/*
* Limit on how large password's we will try to process. A password
* larger than this will be treated the same as out-of-memory.
*/
#define MAX_PASSWORD_LENGTH 1024
The limit of 100 that you are quoting is from the psql password prompt, but nobody forces you to use that.
default authentication method
Use the -A option during initdb to specify a different authentication method.
making a docker container safe
Yes, that is too broad. Essentially, if you have the files that make up the database, you can get at all the data, so I would think that impossible.

Default PostgreSQL password encryption method

I want to know what is the default encryption method used (if any) by PostgreSQL if I do not specify ENCRYPTED while Creating a user or Altering a Role.
I read the following on the PostgreSQL website:
Password Storage Encryption
By default, database user passwords are stored as MD5 hashes, so the administrator cannot determine the actual password assigned to the user. If MD5 encryption is used for client authentication, the unencrypted password is never even temporarily present on the server because the client MD5-encrypts it before being sent across the network.
But I am not sure if MD5 encryption method is used only when I use ENCRYPTED while creating/altering role/user.
I am using PostgreSQL 9.5
Thanks
From the docs
These key words control whether the password is stored encrypted in the system catalogs. (If neither is specified, the default behavior is determined by the configuration parameter password_encryption.) If the presented password string is already in MD5-encrypted format, then it is stored encrypted as-is, regardless of whether ENCRYPTED or UNENCRYPTED is specified (since the system cannot decrypt the specified encrypted password string). This allows reloading of encrypted passwords during dump/restore.
password_encryption defaults to true., though you can check it with SHOW password_encryption.
According to the encryption options,
Password Storage Encryption By default, database user passwords are stored as MD5 hashes, so the administrator cannot determine the actual password assigned to the user. If MD5 encryption is used for client authentication, the unencrypted password is never even temporarily present on the server because the client MD5-encrypts it before being sent across the network.

Comparing hashed passwords, Is it better to compare on the server or on the database using SQL?

I am building a system for authentication, and obviously to do so I will need to compare submitted passwords to hashed stored passwords in the database.
As far as I understand, I can either have the web service use SQL to get the hashed password value and salt, and evaluate on the server. Alternatively, I believe I could use SQL to do the comparison using the database, if I first use the server to extract the salt value, hash the salted password and send it to the database to evaluate. In other words:
Method One:
Receive username and password from the user.
Use SQL to extract the user's salt value and hashed password.
Use the salt and the provided password to compute a hashed password.
Evaluate whether to grant access by comparing the stored password with the newly hashed password.
Method Two:
Receive username and password from the user.
Use SQL to extract only the salt value from the database.
Use the salt and provided password to compute a hashed password.
Use an SQL query to compare the stored password with the newly hashed password.
SQL query returns whether the hashed passwords match.
Grant access to user based on results of SQL query.
Which would be the better practice?

How to store passwords exclusively through PostgreSQL

How would I store passwords exclusively in PostgreSQL? I am aware of the pgcrypto library that can be used with PostgreSQL as is outlined here, or below:
INSERT INTO users (name, password) VALUES ('jdoe', crypt('password', gen_salt('md5')));
However, it is still possible that passwords would be stored in plain text within PostgreSQL server logs. Another complicating factor is I do not have direct control over the log configuration.
Is there any way to completely hide the values in a server column, even from the logs?

Store SHA1 hash digest of a FreeRADIUS user password in PostgreSQL

I have a system with a centralized user database where usernames and passwords are stored for different application.
The database is created in PostgreSQL. FreeRDAIUS gets access to the users and passwords via OpenLDAP which uses PostgreSQL as a backend system. The passwords are supposed to be stored in their hash formats.
I have tested FreeRADIUS with SHA1 passwords stored in the database and users are successfully authenticated. I stored the digest with {SHA} prepnded to it and it work perfectly. This hash, however, needs to be in base64 with "=" as the a padding character. I generated the base64 hash digest using ldap utility slappasswd.
Since in reality, I am supposed to insert users in the database using a C function and the available cryptographic libs such as OpenSSL only offer function for hex hash, I thought the best way is to know how to tell FreeRDAIUS that the digest stored in the database is NOT base64 but HEX.
Does anyone know how I can do this? It seems that if I simply put {SHA} before the hashed value, it only works for base64 with FreeRADIUS. I would also like to know if FreeRADIUS supports other hash algorithms such as SHA256.
OS: Ubuntu 12.04 LTS
PostgreSQL: 9.1
FreeRADIUS: 2.1.10
No currently released versions support any of the SHA-2 hash algorithms.
The rlm_pap module in FreeRADIUS 2.1.10 should automatically 'normify' the 'known good' password, that is convert the hexits to binary, and assign it to the correct control: attribute. This works the same way for hexits as it does base64.
Update:
https://github.com/FreeRADIUS/freeradius-server/commit/0bd0f7453adb2c331a9c1127eda9c9a9fe203b2d