Allow plaintext 'password' authentication when user has a SCRAM verifier.
Oversight in the main SCRAM patch.
This commit is contained in:
parent
ff30aec759
commit
c6305a9c57
|
@ -364,6 +364,52 @@ scram_build_verifier(const char *username, const char *password,
|
|||
return psprintf("scram-sha-256:%s:%d:%s:%s", encoded_salt, iterations, storedkey_hex, serverkey_hex);
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify a plaintext password against a SCRAM verifier. This is used when
|
||||
* performing plaintext password authentication for a user that has a SCRAM
|
||||
* verifier stored in pg_authid.
|
||||
*/
|
||||
bool
|
||||
scram_verify_plain_password(const char *username, const char *password,
|
||||
const char *verifier)
|
||||
{
|
||||
char *encoded_salt;
|
||||
char *salt;
|
||||
int saltlen;
|
||||
int iterations;
|
||||
uint8 stored_key[SCRAM_KEY_LEN];
|
||||
uint8 server_key[SCRAM_KEY_LEN];
|
||||
uint8 computed_key[SCRAM_KEY_LEN];
|
||||
|
||||
if (!parse_scram_verifier(verifier, &encoded_salt, &iterations,
|
||||
stored_key, server_key))
|
||||
{
|
||||
/*
|
||||
* The password looked like a SCRAM verifier, but could not be
|
||||
* parsed.
|
||||
*/
|
||||
elog(LOG, "invalid SCRAM verifier for user \"%s\"", username);
|
||||
return false;
|
||||
}
|
||||
|
||||
salt = palloc(pg_b64_dec_len(strlen(encoded_salt)));
|
||||
saltlen = pg_b64_decode(encoded_salt, strlen(encoded_salt), salt);
|
||||
if (saltlen == -1)
|
||||
{
|
||||
elog(LOG, "invalid SCRAM verifier for user \"%s\"", username);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Compute Server key based on the user-supplied plaintext password */
|
||||
scram_ClientOrServerKey(password, salt, saltlen, iterations,
|
||||
SCRAM_SERVER_KEY_NAME, computed_key);
|
||||
|
||||
/*
|
||||
* Compare the verifier's Server Key with the one computed from the
|
||||
* user-supplied password.
|
||||
*/
|
||||
return memcmp(computed_key, server_key, SCRAM_KEY_LEN) == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if given verifier can be used for SCRAM authentication.
|
||||
|
|
|
@ -283,7 +283,6 @@ plain_crypt_verify(const char *role, const char *shadow_pass,
|
|||
const char *client_pass,
|
||||
char **logdetail)
|
||||
{
|
||||
int retval;
|
||||
char crypt_client_pass[MD5_PASSWD_LEN + 1];
|
||||
|
||||
/*
|
||||
|
@ -293,6 +292,21 @@ plain_crypt_verify(const char *role, const char *shadow_pass,
|
|||
*/
|
||||
switch (get_password_type(shadow_pass))
|
||||
{
|
||||
case PASSWORD_TYPE_SCRAM:
|
||||
if (scram_verify_plain_password(role,
|
||||
client_pass,
|
||||
shadow_pass))
|
||||
{
|
||||
return STATUS_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
*logdetail = psprintf(_("Password does not match for user \"%s\"."),
|
||||
role);
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
break;
|
||||
|
||||
case PASSWORD_TYPE_MD5:
|
||||
if (!pg_md5_encrypt(client_pass,
|
||||
role,
|
||||
|
@ -307,30 +321,33 @@ plain_crypt_verify(const char *role, const char *shadow_pass,
|
|||
*/
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
client_pass = crypt_client_pass;
|
||||
if (strcmp(crypt_client_pass, shadow_pass) == 0)
|
||||
return STATUS_OK;
|
||||
else
|
||||
{
|
||||
*logdetail = psprintf(_("Password does not match for user \"%s\"."),
|
||||
role);
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
break;
|
||||
|
||||
case PASSWORD_TYPE_PLAINTEXT:
|
||||
if (strcmp(client_pass, shadow_pass) == 0)
|
||||
return STATUS_OK;
|
||||
else
|
||||
{
|
||||
*logdetail = psprintf(_("Password does not match for user \"%s\"."),
|
||||
role);
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
/*
|
||||
* This shouldn't happen. Plain "password" authentication should
|
||||
* be possible with any kind of stored password hash.
|
||||
*/
|
||||
*logdetail = psprintf(_("Password of user \"%s\" is in unrecognized format."),
|
||||
role);
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
|
||||
if (strcmp(client_pass, shadow_pass) == 0)
|
||||
retval = STATUS_OK;
|
||||
else
|
||||
{
|
||||
*logdetail = psprintf(_("Password does not match for user \"%s\"."),
|
||||
role);
|
||||
retval = STATUS_ERROR;
|
||||
}
|
||||
|
||||
return retval;
|
||||
/*
|
||||
* This shouldn't happen. Plain "password" authentication is possible
|
||||
* with any kind of stored password hash.
|
||||
*/
|
||||
*logdetail = psprintf(_("Password of user \"%s\" is in unrecognized format."),
|
||||
role);
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
|
|
|
@ -31,5 +31,7 @@ extern char *scram_build_verifier(const char *username,
|
|||
const char *password,
|
||||
int iterations);
|
||||
extern bool is_scram_verifier(const char *verifier);
|
||||
extern bool scram_verify_plain_password(const char *username,
|
||||
const char *password, const char *verifier);
|
||||
|
||||
#endif /* PG_SCRAM_H */
|
||||
|
|
Loading…
Reference in New Issue