108 const char *shadow_pass);
110 char **
output,
int *outputlen,
111 const char **logdetail);
184 int *
iterations,
int *key_length,
char **salt,
214 if (
port->ssl_in_use)
259 state->channel_binding_in_use =
true;
263 state->channel_binding_in_use =
false;
266 (
errcode(ERRCODE_PROTOCOL_VIOLATION),
267 errmsg(
"client selected an invalid SASL authentication mechanism")));
291 (
errmsg(
"invalid SCRAM secret for user \"%s\"",
292 state->port->user_name)));
302 state->logdetail =
psprintf(
_(
"User \"%s\" does not have a valid SCRAM secret."),
303 state->port->user_name);
329 state->doomed =
true;
353 char **
output,
int *outputlen,
const char **logdetail)
381 (
errcode(ERRCODE_PROTOCOL_VIOLATION),
382 errmsg(
"malformed SCRAM message"),
384 if (inputlen != strlen(
input))
386 (
errcode(ERRCODE_PROTOCOL_VIOLATION),
387 errmsg(
"malformed SCRAM message"),
388 errdetail(
"Message length does not match input length.")));
390 switch (
state->state)
419 (
errcode(ERRCODE_PROTOCOL_VIOLATION),
420 errmsg(
"invalid SCRAM response"),
457 elog(
ERROR,
"invalid SCRAM exchange state");
462 *logdetail =
state->logdetail;
465 *outputlen = strlen(*
output);
489 const char *errstr = NULL;
498 password = (
const char *) prep_password;
503 (
errcode(ERRCODE_INTERNAL_ERROR),
504 errmsg(
"could not generate random salt")));
512 pfree(prep_password);
538 const char *errstr = NULL;
541 &encoded_salt, stored_key, server_key))
553 saltlen =
pg_b64_decode(encoded_salt, strlen(encoded_salt), salt,
570 salted_password, &errstr) < 0 ||
572 computed_key, &errstr) < 0)
574 elog(
ERROR,
"could not compute server key: %s", errstr);
578 pfree(prep_password);
584 return memcmp(computed_key, server_key, key_length) == 0;
602 char **salt,
uint8 *stored_key,
uint8 *server_key)
608 char *iterations_str;
612 char *decoded_salt_buf;
613 char *decoded_stored_buf;
614 char *decoded_server_buf;
622 scheme_str =
strsep(&v,
"$");
625 iterations_str =
strsep(&v,
":");
628 salt_str =
strsep(&v,
"$");
631 storedkey_str =
strsep(&v,
":");
637 if (strcmp(scheme_str,
"SCRAM-SHA-256") != 0)
644 if (*p || errno != 0)
652 decoded_salt_buf =
palloc(decoded_len);
654 decoded_salt_buf, decoded_len);
663 decoded_stored_buf =
palloc(decoded_len);
664 decoded_len =
pg_b64_decode(storedkey_str, strlen(storedkey_str),
665 decoded_stored_buf, decoded_len);
666 if (decoded_len != *key_length)
668 memcpy(stored_key, decoded_stored_buf, *key_length);
671 decoded_server_buf =
palloc(decoded_len);
672 decoded_len =
pg_b64_decode(serverkey_str, strlen(serverkey_str),
673 decoded_server_buf, decoded_len);
674 if (decoded_len != *key_length)
676 memcpy(server_key, decoded_server_buf, *key_length);
698 int *
iterations,
int *key_length,
char **salt,
718 if (raw_salt == NULL)
723 encoded_salt = (
char *)
palloc(encoded_len + 1);
729 encoded_salt[encoded_len] =
'\0';
731 *salt = encoded_salt;
745 char *begin = *
input;
750 (
errcode(ERRCODE_PROTOCOL_VIOLATION),
751 errmsg(
"malformed SCRAM message"),
752 errdetail(
"Expected attribute \"%c\" but found \"%s\".",
758 (
errcode(ERRCODE_PROTOCOL_VIOLATION),
759 errmsg(
"malformed SCRAM message"),
760 errdetail(
"Expected character \"=\" for attribute \"%c\".", attr)));
764 while (*end && *end !=
',')
792 if (*p < 0x21 || *p > 0x7E || *p == 0x2C )
811 if (
c >= 0x21 &&
c <= 0x7E)
829 static char buf[30 + 1];
832 for (
i = 0;
i <
sizeof(
buf) - 1;
i++)
839 if (
c >= 0x21 &&
c <= 0x7E)
857 char *begin = *
input;
863 (
errcode(ERRCODE_PROTOCOL_VIOLATION),
864 errmsg(
"malformed SCRAM message"),
865 errdetail(
"Attribute expected, but found end of string.")));
873 if (!((attr >=
'A' && attr <=
'Z') ||
874 (attr >=
'a' && attr <=
'z')))
876 (
errcode(ERRCODE_PROTOCOL_VIOLATION),
877 errmsg(
"malformed SCRAM message"),
878 errdetail(
"Attribute expected, but found invalid character \"%s\".",
886 (
errcode(ERRCODE_PROTOCOL_VIOLATION),
887 errmsg(
"malformed SCRAM message"),
888 errdetail(
"Expected character \"=\" for attribute \"%c\".", attr)));
892 while (*end && *end !=
',')
916 char *channel_binding_type;
983 state->cbind_flag = *p;
992 if (
state->channel_binding_in_use)
994 (
errcode(ERRCODE_PROTOCOL_VIOLATION),
995 errmsg(
"malformed SCRAM message"),
996 errdetail(
"The client selected SCRAM-SHA-256-PLUS, but the SCRAM message does not include channel binding data.")));
1001 (
errcode(ERRCODE_PROTOCOL_VIOLATION),
1002 errmsg(
"malformed SCRAM message"),
1003 errdetail(
"Comma expected, but found character \"%s\".",
1014 if (
state->channel_binding_in_use)
1016 (
errcode(ERRCODE_PROTOCOL_VIOLATION),
1017 errmsg(
"malformed SCRAM message"),
1018 errdetail(
"The client selected SCRAM-SHA-256-PLUS, but the SCRAM message does not include channel binding data.")));
1021 if (
state->port->ssl_in_use)
1023 (
errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
1024 errmsg(
"SCRAM channel binding negotiation error"),
1025 errdetail(
"The client supports SCRAM channel binding but thinks the server does not. "
1026 "However, this server does support channel binding.")));
1031 (
errcode(ERRCODE_PROTOCOL_VIOLATION),
1032 errmsg(
"malformed SCRAM message"),
1033 errdetail(
"Comma expected, but found character \"%s\".",
1043 if (!
state->channel_binding_in_use)
1045 (
errcode(ERRCODE_PROTOCOL_VIOLATION),
1046 errmsg(
"malformed SCRAM message"),
1047 errdetail(
"The client selected SCRAM-SHA-256 without channel binding, but the SCRAM message includes channel binding data.")));
1055 if (strcmp(channel_binding_type,
"tls-server-end-point") != 0)
1057 (
errcode(ERRCODE_PROTOCOL_VIOLATION),
1058 errmsg(
"unsupported SCRAM channel-binding type \"%s\"",
1063 (
errcode(ERRCODE_PROTOCOL_VIOLATION),
1064 errmsg(
"malformed SCRAM message"),
1065 errdetail(
"Unexpected channel-binding flag \"%s\".",
1074 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1075 errmsg(
"client uses authorization identity, but it is not supported")));
1078 (
errcode(ERRCODE_PROTOCOL_VIOLATION),
1079 errmsg(
"malformed SCRAM message"),
1080 errdetail(
"Unexpected attribute \"%s\" in client-first-message.",
1095 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1096 errmsg(
"client requires an unsupported SCRAM extension")));
1109 (
errcode(ERRCODE_PROTOCOL_VIOLATION),
1110 errmsg(
"non-printable characters in SCRAM nonce")));
1129 int client_nonce_len = strlen(
state->client_nonce);
1130 int server_nonce_len = strlen(
state->server_nonce);
1131 int final_nonce_len = strlen(
state->client_final_nonce);
1133 if (final_nonce_len != client_nonce_len + server_nonce_len)
1135 if (memcmp(
state->client_final_nonce,
state->client_nonce, client_nonce_len) != 0)
1137 if (memcmp(
state->client_final_nonce + client_nonce_len,
state->server_nonce, server_nonce_len) != 0)
1155 const char *errstr = NULL;
1165 strlen(
state->client_first_message_bare)) < 0 ||
1169 strlen(
state->server_first_message)) < 0 ||
1172 (
uint8 *)
state->client_final_message_without_proof,
1173 strlen(
state->client_final_message_without_proof)) < 0 ||
1176 elog(
ERROR,
"could not calculate client signature: %s",
1183 for (
i = 0;
i <
state->key_length;
i++)
1184 state->ClientKey[
i] =
state->ClientProof[
i] ^ ClientSignature[
i];
1188 client_StoredKey, &errstr) < 0)
1189 elog(
ERROR,
"could not hash stored key: %s", errstr);
1191 if (memcmp(client_StoredKey,
state->StoredKey,
state->key_length) != 0)
1239 (
errcode(ERRCODE_INTERNAL_ERROR),
1240 errmsg(
"could not generate random nonce")));
1246 state->server_nonce, encoded_len);
1247 if (encoded_len < 0)
1249 (
errcode(ERRCODE_INTERNAL_ERROR),
1250 errmsg(
"could not encode random nonce")));
1251 state->server_nonce[encoded_len] =
'\0';
1253 state->server_first_message =
1269 char *channel_binding;
1275 int client_proof_len;
1313 if (
state->channel_binding_in_use)
1316 const char *cbind_data = NULL;
1317 size_t cbind_data_len = 0;
1318 size_t cbind_header_len;
1320 size_t cbind_input_len;
1322 int b64_message_len;
1331 if (cbind_data == NULL || cbind_data_len == 0)
1332 elog(
ERROR,
"could not get server certificate hash");
1334 cbind_header_len = strlen(
"p=tls-server-end-point,,");
1335 cbind_input_len = cbind_header_len + cbind_data_len;
1336 cbind_input =
palloc(cbind_input_len);
1337 snprintf(cbind_input, cbind_input_len,
"p=tls-server-end-point,,");
1338 memcpy(cbind_input + cbind_header_len, cbind_data, cbind_data_len);
1342 b64_message =
palloc(b64_message_len + 1);
1343 b64_message_len =
pg_b64_encode(cbind_input, cbind_input_len,
1344 b64_message, b64_message_len);
1345 if (b64_message_len < 0)
1346 elog(
ERROR,
"could not encode channel binding data");
1347 b64_message[b64_message_len] =
'\0';
1353 if (strcmp(channel_binding, b64_message) != 0)
1355 (
errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
1356 errmsg(
"SCRAM channel binding check failed")));
1359 elog(
ERROR,
"channel binding not supported by this build");
1370 if (!(strcmp(channel_binding,
"biws") == 0 &&
state->cbind_flag ==
'n') &&
1371 !(strcmp(channel_binding,
"eSws") == 0 &&
state->cbind_flag ==
'y'))
1373 (
errcode(ERRCODE_PROTOCOL_VIOLATION),
1374 errmsg(
"unexpected SCRAM channel-binding attribute in client-final-message")));
1384 }
while (attr !=
'p');
1387 client_proof =
palloc(client_proof_len);
1389 client_proof_len) !=
state->key_length)
1391 (
errcode(ERRCODE_PROTOCOL_VIOLATION),
1392 errmsg(
"malformed SCRAM message"),
1393 errdetail(
"Malformed proof in client-final-message.")));
1394 memcpy(
state->ClientProof, client_proof,
state->key_length);
1395 pfree(client_proof);
1399 (
errcode(ERRCODE_PROTOCOL_VIOLATION),
1400 errmsg(
"malformed SCRAM message"),
1401 errdetail(
"Garbage found at the end of client-final-message.")));
1403 state->client_final_message_without_proof =
palloc(proof - begin + 1);
1404 memcpy(
state->client_final_message_without_proof,
input, proof - begin);
1405 state->client_final_message_without_proof[proof - begin] =
'\0';
1415 char *server_signature_base64;
1423 strlen(
state->client_first_message_bare)) < 0 ||
1427 strlen(
state->server_first_message)) < 0 ||
1430 (
uint8 *)
state->client_final_message_without_proof,
1431 strlen(
state->client_final_message_without_proof)) < 0 ||
1434 elog(
ERROR,
"could not calculate server signature: %s",
1442 server_signature_base64 =
palloc(siglen + 1);
1444 state->key_length, server_signature_base64,
1447 elog(
ERROR,
"could not encode server signature");
1448 server_signature_base64[siglen] =
'\0';
1461 return psprintf(
"v=%s", server_signature_base64);
1485 "salt length greater than SHA256 digest length");
1504 return (
char *) sha_digest;
static void * scram_init(Port *port, const char *selected_mech, const char *shadow_pass)
static char * build_server_first_message(scram_state *state)
const pg_be_sasl_mech pg_be_scram_mech
static void read_client_first_message(scram_state *state, const char *input)
bool parse_scram_secret(const char *secret, int *iterations, pg_cryptohash_type *hash_type, int *key_length, char **salt, uint8 *stored_key, uint8 *server_key)
static bool verify_client_proof(scram_state *state)
static bool verify_final_nonce(scram_state *state)
static char * sanitize_str(const char *s)
static char * scram_mock_salt(const char *username, pg_cryptohash_type hash_type, int key_length)
char * pg_be_scram_build_secret(const char *password)
static int scram_exchange(void *opaq, const char *input, int inputlen, char **output, int *outputlen, const char **logdetail)
static bool is_scram_printable(char *p)
static char * sanitize_char(char c)
bool scram_verify_plain_password(const char *username, const char *password, const char *secret)
static char * read_attr_value(char **input, char attr)
static void read_client_final_message(scram_state *state, const char *input)
static void mock_scram_secret(const char *username, pg_cryptohash_type *hash_type, int *iterations, int *key_length, char **salt, uint8 *stored_key, uint8 *server_key)
static char * read_any_attr(char **input, char *attr_p)
static char * build_server_final_message(scram_state *state)
static void scram_get_mechanisms(Port *port, StringInfo buf)
int scram_sha_256_iterations
int pg_b64_decode(const char *src, int len, char *dst, int dstlen)
int pg_b64_enc_len(int srclen)
int pg_b64_encode(const char *src, int len, char *dst, int dstlen)
int pg_b64_dec_len(int srclen)
char * be_tls_get_certificate_hash(Port *port, size_t *len)
#define Assert(condition)
#define StaticAssertDecl(condition, errmessage)
PasswordType get_password_type(const char *shadow_pass)
@ PASSWORD_TYPE_SCRAM_SHA_256
int pg_cryptohash_update(pg_cryptohash_ctx *ctx, const uint8 *data, size_t len)
pg_cryptohash_ctx * pg_cryptohash_create(pg_cryptohash_type type)
int pg_cryptohash_init(pg_cryptohash_ctx *ctx)
void pg_cryptohash_free(pg_cryptohash_ctx *ctx)
int pg_cryptohash_final(pg_cryptohash_ctx *ctx, uint8 *dest, size_t len)
int errdetail(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
pg_hmac_ctx * pg_hmac_create(pg_cryptohash_type type)
void pg_hmac_free(pg_hmac_ctx *ctx)
const char * pg_hmac_error(pg_hmac_ctx *ctx)
int pg_hmac_update(pg_hmac_ctx *ctx, const uint8 *data, size_t len)
int pg_hmac_init(pg_hmac_ctx *ctx, const uint8 *key, size_t len)
int pg_hmac_final(pg_hmac_ctx *ctx, uint8 *dest, size_t len)
if(TABLE==NULL||TABLE_index==NULL)
char * pstrdup(const char *in)
void pfree(void *pointer)
void * palloc0(Size size)
#define MOCK_AUTH_NONCE_LEN
char * strsep(char **stringp, const char *delim)
bool pg_strong_random(void *buf, size_t len)
char * psprintf(const char *fmt,...)
#define PG_MAX_SASL_MESSAGE_LENGTH
#define PG_SASL_EXCHANGE_FAILURE
#define PG_SASL_EXCHANGE_CONTINUE
#define PG_SASL_EXCHANGE_SUCCESS
pg_saslprep_rc pg_saslprep(const char *input, char **output)
char * scram_build_secret(pg_cryptohash_type hash_type, int key_length, const char *salt, int saltlen, int iterations, const char *password, const char **errstr)
int scram_ServerKey(const uint8 *salted_password, pg_cryptohash_type hash_type, int key_length, uint8 *result, const char **errstr)
int scram_SaltedPassword(const char *password, pg_cryptohash_type hash_type, int key_length, const char *salt, int saltlen, int iterations, uint8 *result, const char **errstr)
int scram_H(const uint8 *input, pg_cryptohash_type hash_type, int key_length, uint8 *result, const char **errstr)
#define SCRAM_SHA_256_PLUS_NAME
#define SCRAM_SHA_256_NAME
#define SCRAM_RAW_NONCE_LEN
#define SCRAM_DEFAULT_SALT_LEN
#define SCRAM_MAX_KEY_LEN
#define SCRAM_SHA_256_KEY_LEN
#define SCRAM_SHA_256_DEFAULT_ITERATIONS
#define PG_SHA256_DIGEST_LENGTH
void appendStringInfoString(StringInfo str, const char *s)
void appendStringInfoChar(StringInfo str, char ch)
uint8 scram_ServerKey[SCRAM_MAX_KEY_LEN]
uint8 scram_ClientKey[SCRAM_MAX_KEY_LEN]
char * client_final_nonce
char * client_first_message_bare
char * client_final_message_without_proof
char * server_first_message
bool channel_binding_in_use
pg_cryptohash_type hash_type
char * GetMockAuthenticationNonce(void)