mirror of
https://github.com/postgres/postgres.git
synced 2025-08-18 12:22:09 +03:00
Add PQencryptPasswordConn function to libpq, use it in psql and createuser.
The new function supports creating SCRAM verifiers, in addition to md5 hashes. The algorithm is chosen based on password_encryption, by default. This fixes the issue reported by Jeff Janes, that there was previously no way to create a SCRAM verifier with "\password". Michael Paquier and me Discussion: https://www.postgresql.org/message-id/CAMkU%3D1wfBgFPbfAMYZQE78p%3DVhZX7nN86aWkp0QcCp%3D%2BKxZ%3Dbg%40mail.gmail.com
This commit is contained in:
@@ -207,7 +207,7 @@ pg_be_scram_init(const char *username, const char *shadow_pass)
|
||||
*/
|
||||
char *verifier;
|
||||
|
||||
verifier = scram_build_verifier(username, shadow_pass, 0);
|
||||
verifier = pg_be_scram_build_verifier(shadow_pass);
|
||||
|
||||
(void) parse_scram_verifier(verifier, &state->iterations, &state->salt,
|
||||
state->StoredKey, state->ServerKey);
|
||||
@@ -387,22 +387,14 @@ pg_be_scram_exchange(void *opaq, char *input, int inputlen,
|
||||
/*
|
||||
* Construct a verifier string for SCRAM, stored in pg_authid.rolpassword.
|
||||
*
|
||||
* If iterations is 0, default number of iterations is used. The result is
|
||||
* palloc'd, so caller is responsible for freeing it.
|
||||
* The result is palloc'd, so caller is responsible for freeing it.
|
||||
*/
|
||||
char *
|
||||
scram_build_verifier(const char *username, const char *password,
|
||||
int iterations)
|
||||
pg_be_scram_build_verifier(const char *password)
|
||||
{
|
||||
char *prep_password = NULL;
|
||||
pg_saslprep_rc rc;
|
||||
char saltbuf[SCRAM_DEFAULT_SALT_LEN];
|
||||
uint8 salted_password[SCRAM_KEY_LEN];
|
||||
uint8 keybuf[SCRAM_KEY_LEN];
|
||||
char *encoded_salt;
|
||||
char *encoded_storedkey;
|
||||
char *encoded_serverkey;
|
||||
int encoded_len;
|
||||
char *result;
|
||||
|
||||
/*
|
||||
@@ -414,10 +406,7 @@ scram_build_verifier(const char *username, const char *password,
|
||||
if (rc == SASLPREP_SUCCESS)
|
||||
password = (const char *) prep_password;
|
||||
|
||||
if (iterations <= 0)
|
||||
iterations = SCRAM_DEFAULT_ITERATIONS;
|
||||
|
||||
/* Generate salt, and encode it in base64 */
|
||||
/* Generate random salt */
|
||||
if (!pg_backend_random(saltbuf, SCRAM_DEFAULT_SALT_LEN))
|
||||
{
|
||||
ereport(LOG,
|
||||
@@ -426,37 +415,11 @@ scram_build_verifier(const char *username, const char *password,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
encoded_salt = palloc(pg_b64_enc_len(SCRAM_DEFAULT_SALT_LEN) + 1);
|
||||
encoded_len = pg_b64_encode(saltbuf, SCRAM_DEFAULT_SALT_LEN, encoded_salt);
|
||||
encoded_salt[encoded_len] = '\0';
|
||||
|
||||
/* Calculate StoredKey, and encode it in base64 */
|
||||
scram_SaltedPassword(password, saltbuf, SCRAM_DEFAULT_SALT_LEN,
|
||||
iterations, salted_password);
|
||||
scram_ClientKey(salted_password, keybuf);
|
||||
scram_H(keybuf, SCRAM_KEY_LEN, keybuf); /* StoredKey */
|
||||
|
||||
encoded_storedkey = palloc(pg_b64_enc_len(SCRAM_KEY_LEN) + 1);
|
||||
encoded_len = pg_b64_encode((const char *) keybuf, SCRAM_KEY_LEN,
|
||||
encoded_storedkey);
|
||||
encoded_storedkey[encoded_len] = '\0';
|
||||
|
||||
/* And same for ServerKey */
|
||||
scram_ServerKey(salted_password, keybuf);
|
||||
|
||||
encoded_serverkey = palloc(pg_b64_enc_len(SCRAM_KEY_LEN) + 1);
|
||||
encoded_len = pg_b64_encode((const char *) keybuf, SCRAM_KEY_LEN,
|
||||
encoded_serverkey);
|
||||
encoded_serverkey[encoded_len] = '\0';
|
||||
|
||||
result = psprintf("SCRAM-SHA-256$%d:%s$%s:%s", iterations, encoded_salt,
|
||||
encoded_storedkey, encoded_serverkey);
|
||||
result = scram_build_verifier(saltbuf, SCRAM_DEFAULT_SALT_LEN,
|
||||
SCRAM_DEFAULT_ITERATIONS, password);
|
||||
|
||||
if (prep_password)
|
||||
pfree(prep_password);
|
||||
pfree(encoded_salt);
|
||||
pfree(encoded_storedkey);
|
||||
pfree(encoded_serverkey);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1194,7 +1157,7 @@ scram_MockSalt(const char *username)
|
||||
* Generate salt using a SHA256 hash of the username and the cluster's
|
||||
* mock authentication nonce. (This works as long as the salt length is
|
||||
* not larger the SHA256 digest length. If the salt is smaller, the caller
|
||||
* will just ignore the extra data))
|
||||
* will just ignore the extra data.)
|
||||
*/
|
||||
StaticAssertStmt(PG_SHA256_DIGEST_LENGTH >= SCRAM_DEFAULT_SALT_LEN,
|
||||
"salt length greater than SHA256 digest length");
|
||||
|
Reference in New Issue
Block a user