@ -64,10 +64,10 @@
* Don ' t reveal user information to an unauthenticated client . We don ' t
* want an attacker to be able to probe whether a particular username is
* valid . In SCRAM , the server has to read the salt and iteration count
* from the user ' s password verifier , and send it to the client . To avoid
* from the user ' s stored secret , and send it to the client . To avoid
* revealing whether a user exists , when the client tries to authenticate
* with a username that doesn ' t exist , or doesn ' t have a valid SCRAM
* verifier in pg_authid , we create a fake salt and iteration count
* secret in pg_authid , we create a fake salt and iteration count
* on - the - fly , and proceed with the authentication with that . In the end ,
* we ' ll reject the attempt , as if an incorrect password was given . When
* we are performing a " mock " authentication , the ' doomed ' flag in
@ -161,7 +161,7 @@ static char *build_server_first_message(scram_state *state);
static char * build_server_final_message ( scram_state * state ) ;
static bool verify_client_proof ( scram_state * state ) ;
static bool verify_final_nonce ( scram_state * state ) ;
static void mock_scram_verifier ( const char * username , int * iterations ,
static void mock_scram_secret ( const char * username , int * iterations ,
char * * salt , uint8 * stored_key , uint8 * server_key ) ;
static bool is_scram_printable ( char * p ) ;
static char * sanitize_char ( char c ) ;
@ -202,13 +202,13 @@ pg_be_scram_get_mechanisms(Port *port, StringInfo buf)
*
* Initialize a new SCRAM authentication exchange status tracker . This
* needs to be called before doing any exchange . It will be filled later
* after the beginning of the exchange with verifier data .
* after the beginning of the exchange with authentication information .
*
* ' selected_mech ' identifies the SASL mechanism that the client selected .
* It should be one of the mechanisms that we support , as returned by
* pg_be_scram_get_mechanisms ( ) .
*
* ' shadow_pass ' is the role ' s password verifier , from pg_authid . rolpassword .
* ' shadow_pass ' is the role ' s stored secret , from pg_authid . rolpassword .
* The username was provided by the client in the startup message , and is
* available in port - > user_name . If ' shadow_pass ' is NULL , we still perform
* an authentication exchange , but it will fail , as if an incorrect password
@ -220,7 +220,7 @@ pg_be_scram_init(Port *port,
const char * shadow_pass )
{
scram_state * state ;
bool got_verifier ;
bool got_secret ;
state = ( scram_state * ) palloc0 ( sizeof ( scram_state ) ) ;
state - > port = port ;
@ -248,7 +248,7 @@ pg_be_scram_init(Port *port,
errmsg ( " client selected an invalid SASL authentication mechanism " ) ) ) ;
/*
* Parse the stored password verifier .
* Parse the stored secret .
*/
if ( shadow_pass )
{
@ -256,30 +256,30 @@ pg_be_scram_init(Port *port,
if ( password_type = = PASSWORD_TYPE_SCRAM_SHA_256 )
{
if ( parse_scram_verifier ( shadow_pass , & state - > iterations , & state - > salt ,
if ( parse_scram_secret ( shadow_pass , & state - > iterations , & state - > salt ,
state - > StoredKey , state - > ServerKey ) )
got_verifier = true ;
got_secret = true ;
else
{
/*
* The password looked like a SCRAM verifier , but could not be
* The password looked like a SCRAM secret , but could not be
* parsed .
*/
ereport ( LOG ,
( errmsg ( " invalid SCRAM verifier for user \" %s \" " ,
( errmsg ( " invalid SCRAM secret for user \" %s \" " ,
state - > port - > user_name ) ) ) ;
got_verifier = false ;
got_secret = false ;
}
}
else
{
/*
* The user doesn ' t have SCRAM verifier . ( You cannot do SCRAM
* The user doesn ' t have SCRAM secret . ( You cannot do SCRAM
* authentication with an MD5 hash . )
*/
state - > logdetail = psprintf ( _ ( " User \" %s \" does not have a valid SCRAM verifier . " ) ,
state - > logdetail = psprintf ( _ ( " User \" %s \" does not have a valid SCRAM secret . " ) ,
state - > port - > user_name ) ;
got_verifier = false ;
got_secret = false ;
}
}
else
@ -289,18 +289,18 @@ pg_be_scram_init(Port *port,
* considered normal , since the caller requested it , so don ' t set log
* detail .
*/
got_verifier = false ;
got_secret = false ;
}
/*
* If the user did not have a valid SCRAM verifier , we still go through
* If the user did not have a valid SCRAM secret , we still go through
* the motions with a mock one , and fail as if the client supplied an
* incorrect password . This is to avoid revealing information to an
* attacker .
*/
if ( ! got_verifier )
if ( ! got_secret )
{
mock_scram_verifier ( state - > port - > user_name , & state - > iterations ,
mock_scram_secret ( state - > port - > user_name , & state - > iterations ,
& state - > salt , state - > StoredKey , state - > ServerKey ) ;
state - > doomed = true ;
}
@ -443,12 +443,12 @@ pg_be_scram_exchange(void *opaq, const char *input, int inputlen,
}
/*
* Construct a verifier string for SCRAM , stored in pg_authid . rolpassword .
* Construct a SCRAM secret , for storing in pg_authid . rolpassword .
*
* The result is palloc ' d , so caller is responsible for freeing it .
*/
char *
pg_be_scram_build_verifier ( const char * password )
pg_be_scram_build_secret ( const char * password )
{
char * prep_password ;
pg_saslprep_rc rc ;
@ -470,7 +470,7 @@ pg_be_scram_build_verifier(const char *password)
( errcode ( ERRCODE_INTERNAL_ERROR ) ,
errmsg ( " could not generate random salt " ) ) ) ;
result = scram_build_verifier ( saltbuf , SCRAM_DEFAULT_SALT_LEN ,
result = scram_build_secret ( saltbuf , SCRAM_DEFAULT_SALT_LEN ,
SCRAM_DEFAULT_ITERATIONS , password ) ;
if ( prep_password )
@ -480,13 +480,13 @@ pg_be_scram_build_verifier(const char *password)
}
/*
* Verify a plaintext password against a SCRAM verifier . This is used when
* Verify a plaintext password against a SCRAM secret . This is used when
* performing plaintext password authentication for a user that has a SCRAM
* verifier stored in pg_authid .
* secret stored in pg_authid .
*/
bool
scram_verify_plain_password ( const char * username , const char * password ,
const char * verifier )
const char * secret )
{
char * encoded_salt ;
char * salt ;
@ -499,14 +499,14 @@ scram_verify_plain_password(const char *username, const char *password,
char * prep_password ;
pg_saslprep_rc rc ;
if ( ! parse_scram_verifier ( verifier , & iterations , & encoded_salt ,
if ( ! parse_scram_secret ( secret , & iterations , & encoded_salt ,
stored_key , server_key ) )
{
/*
* The password looked like a SCRAM verifier , but could not be parsed .
* The password looked like a SCRAM secret , but could not be parsed .
*/
ereport ( LOG ,
( errmsg ( " invalid SCRAM verifier for user \" %s \" " , username ) ) ) ;
( errmsg ( " invalid SCRAM secret for user \" %s \" " , username ) ) ) ;
return false ;
}
@ -517,7 +517,7 @@ scram_verify_plain_password(const char *username, const char *password,
if ( saltlen < 0 )
{
ereport ( LOG ,
( errmsg ( " invalid SCRAM verifier for user \" %s \" " , username ) ) ) ;
( errmsg ( " invalid SCRAM secret for user \" %s \" " , username ) ) ) ;
return false ;
}
@ -534,7 +534,7 @@ scram_verify_plain_password(const char *username, const char *password,
pfree ( prep_password ) ;
/*
* Compare the verifier ' s Server Key with the one computed from the
* Compare the secret ' s Server Key with the one computed from the
* user - supplied password .
*/
return memcmp ( computed_key , server_key , SCRAM_KEY_LEN ) = = 0 ;
@ -542,18 +542,18 @@ scram_verify_plain_password(const char *username, const char *password,
/*
* Parse and validate format of given SCRAM verifier .
* Parse and validate format of given SCRAM secret .
*
* On success , the iteration count , salt , stored key , and server key are
* extracted from the verifier , and returned to the caller . For ' stored_key '
* extracted from the secret , and returned to the caller . For ' stored_key '
* and ' server_key ' , the caller must pass pre - allocated buffers of size
* SCRAM_KEY_LEN . Salt is returned as a base64 - encoded , null - terminated
* string . The buffer for the salt is palloc ' d by this function .
*
* Returns true if the SCRAM verifier has been parsed , and false otherwise .
* Returns true if the SCRAM secret has been parsed , and false otherwise .
*/
bool
parse_scram_verifier ( const char * verifier , int * iterations , char * * salt ,
parse_scram_secret ( const char * secret , int * iterations , char * * salt ,
uint8 * stored_key , uint8 * server_key )
{
char * v ;
@ -569,30 +569,30 @@ parse_scram_verifier(const char *verifier, int *iterations, char **salt,
char * decoded_server_buf ;
/*
* The verifier is of form :
* The secret is of form :
*
* SCRAM - SHA - 256 $ < iterations > : < salt > $ < storedkey > : < serverkey >
*/
v = pstrdup ( verifier ) ;
v = pstrdup ( secret ) ;
if ( ( scheme_str = strtok ( v , " $ " ) ) = = NULL )
goto invalid_verifier ;
goto invalid_secret ;
if ( ( iterations_str = strtok ( NULL , " : " ) ) = = NULL )
goto invalid_verifier ;
goto invalid_secret ;
if ( ( salt_str = strtok ( NULL , " $ " ) ) = = NULL )
goto invalid_verifier ;
goto invalid_secret ;
if ( ( storedkey_str = strtok ( NULL , " : " ) ) = = NULL )
goto invalid_verifier ;
goto invalid_secret ;
if ( ( serverkey_str = strtok ( NULL , " " ) ) = = NULL )
goto invalid_verifier ;
goto invalid_secret ;
/* Parse the fields */
if ( strcmp ( scheme_str , " SCRAM-SHA-256 " ) ! = 0 )
goto invalid_verifier ;
goto invalid_secret ;
errno = 0 ;
* iterations = strtol ( iterations_str , & p , 10 ) ;
if ( * p | | errno ! = 0 )
goto invalid_verifier ;
goto invalid_secret ;
/*
* Verify that the salt is in Base64 - encoded format , by decoding it ,
@ -603,7 +603,7 @@ parse_scram_verifier(const char *verifier, int *iterations, char **salt,
decoded_len = pg_b64_decode ( salt_str , strlen ( salt_str ) ,
decoded_salt_buf , decoded_len ) ;
if ( decoded_len < 0 )
goto invalid_verifier ;
goto invalid_secret ;
* salt = pstrdup ( salt_str ) ;
/*
@ -614,7 +614,7 @@ parse_scram_verifier(const char *verifier, int *iterations, char **salt,
decoded_len = pg_b64_decode ( storedkey_str , strlen ( storedkey_str ) ,
decoded_stored_buf , decoded_len ) ;
if ( decoded_len ! = SCRAM_KEY_LEN )
goto invalid_verifier ;
goto invalid_secret ;
memcpy ( stored_key , decoded_stored_buf , SCRAM_KEY_LEN ) ;
decoded_len = pg_b64_dec_len ( strlen ( serverkey_str ) ) ;
@ -622,29 +622,29 @@ parse_scram_verifier(const char *verifier, int *iterations, char **salt,
decoded_len = pg_b64_decode ( serverkey_str , strlen ( serverkey_str ) ,
decoded_server_buf , decoded_len ) ;
if ( decoded_len ! = SCRAM_KEY_LEN )
goto invalid_verifier ;
goto invalid_secret ;
memcpy ( server_key , decoded_server_buf , SCRAM_KEY_LEN ) ;
return true ;
invalid_verifier :
invalid_secret :
* salt = NULL ;
return false ;
}
/*
* Generate plausible SCRAM verifier parameters for mock authentication .
* Generate plausible SCRAM secret parameters for mock authentication .
*
* In a normal authentication , these are extracted from the verifier
* In a normal authentication , these are extracted from the secret
* stored in the server . This function generates values that look
* realistic , for when there is no stored verifier .
* realistic , for when there is no stored secret .
*
* Like in parse_scram_verifier ( ) , for ' stored_key ' and ' server_key ' , the
* Like in parse_scram_secret ( ) , for ' stored_key ' and ' server_key ' , the
* caller must pass pre - allocated buffers of size SCRAM_KEY_LEN , and
* the buffer for the salt is palloc ' d by this function .
*/
static void
mock_scram_verifier ( const char * username , int * iterations , char * * salt ,
mock_scram_secret ( const char * username , int * iterations , char * * salt ,
uint8 * stored_key , uint8 * server_key )
{
char * raw_salt ;