26 const char *sasl_mechanism);
28 char **
output,
int *outputlen,
90 const char *client_final_message_without_proof,
91 uint8 *result,
const char **errstr);
99 const char *sasl_mechanism)
105 Assert(sasl_mechanism != NULL);
116 state->sasl_mechanism = strdup(sasl_mechanism);
117 if (!
state->sasl_mechanism)
141 state->password = prep_password;
189 free(
state->client_final_message_without_proof);
207 char **
output,
int *outputlen,
212 const char *errstr = NULL;
230 if (inputlen != strlen(input))
237 switch (
state->state)
245 *outputlen = strlen(*
output);
259 *outputlen = strlen(*
output);
310 char *begin = *input;
316 "malformed SCRAM message (attribute \"%c\" expected)",
325 "malformed SCRAM message (expected character \"=\" for attribute \"%c\")",
332 while (*end && *end !=
',')
355 int channel_info_len;
372 if (
state->client_nonce == NULL)
378 state->client_nonce, encoded_len);
384 state->client_nonce[encoded_len] =
'\0';
403 #ifdef HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH
424 channel_info_len =
buf.len;
434 state->client_first_message_bare = strdup(
buf.data + channel_info_len + 2);
435 if (!
state->client_first_message_bare)
438 result = strdup(
buf.data);
462 const char *errstr = NULL;
476 #ifdef HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH
477 char *cbind_data = NULL;
478 size_t cbind_data_len = 0;
479 size_t cbind_header_len;
481 size_t cbind_input_len;
482 int encoded_cbind_len;
486 pgtls_get_peer_certificate_hash(
state->conn,
488 if (cbind_data == NULL)
498 cbind_header_len = strlen(
"p=tls-server-end-point,,");
499 cbind_input_len = cbind_header_len + cbind_data_len;
500 cbind_input =
malloc(cbind_input_len);
506 memcpy(cbind_input,
"p=tls-server-end-point,,", cbind_header_len);
507 memcpy(cbind_input + cbind_header_len, cbind_data, cbind_data_len);
516 encoded_cbind_len =
pg_b64_encode(cbind_input, cbind_input_len,
519 if (encoded_cbind_len < 0)
525 "could not encode cbind data for channel binding\n");
528 buf.len += encoded_cbind_len;
540 "channel binding not supported by this build\n");
544 #ifdef HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH
559 state->client_final_message_without_proof = strdup(
buf.data);
560 if (
state->client_final_message_without_proof == NULL)
565 state->client_final_message_without_proof,
566 client_proof, &errstr))
587 buf.len += encoded_len;
590 result = strdup(
buf.data);
610 char *iterations_str;
614 int decoded_salt_len;
616 state->server_first_message = strdup(input);
617 if (
state->server_first_message == NULL)
633 if (strlen(nonce) < strlen(
state->client_nonce) ||
634 memcmp(nonce,
state->client_nonce, strlen(
state->client_nonce)) != 0)
640 state->nonce = strdup(nonce);
641 if (
state->nonce == NULL)
648 if (encoded_salt == NULL)
655 if (
state->salt == NULL)
661 strlen(encoded_salt),
664 if (
state->saltlen < 0)
671 if (iterations_str == NULL)
676 state->iterations = strtol(iterations_str, &endptr, 10);
677 if (*endptr !=
'\0' ||
state->iterations < 1)
696 char *encoded_server_signature;
697 char *decoded_server_signature;
698 int server_signature_len;
700 state->server_final_message = strdup(input);
701 if (!
state->server_final_message)
726 if (encoded_server_signature == NULL)
735 server_signature_len =
pg_b64_dec_len(strlen(encoded_server_signature));
736 decoded_server_signature =
malloc(server_signature_len);
737 if (!decoded_server_signature)
743 server_signature_len =
pg_b64_decode(encoded_server_signature,
744 strlen(encoded_server_signature),
745 decoded_server_signature,
746 server_signature_len);
747 if (server_signature_len !=
state->key_length)
749 free(decoded_server_signature);
753 memcpy(
state->ServerSignature, decoded_server_signature,
755 free(decoded_server_signature);
767 const char *client_final_message_without_proof,
768 uint8 *result,
const char **errstr)
792 state->key_length, ClientKey, errstr) < 0 ||
794 StoredKey, errstr) < 0)
804 strlen(
state->client_first_message_bare)) < 0 ||
808 strlen(
state->server_first_message)) < 0 ||
811 (
uint8 *) client_final_message_without_proof,
812 strlen(client_final_message_without_proof)) < 0 ||
820 for (
i = 0;
i <
state->key_length;
i++)
821 result[
i] = ClientKey[
i] ^ ClientSignature[
i];
850 state->key_length, ServerKey, errstr) < 0)
861 strlen(
state->client_first_message_bare)) < 0 ||
865 strlen(
state->server_first_message)) < 0 ||
868 (
uint8 *)
state->client_final_message_without_proof,
869 strlen(
state->client_final_message_without_proof)) < 0 ||
871 state->key_length) < 0)
881 if (memcmp(expected_ServerSignature,
state->ServerSignature,
882 state->key_length) != 0)
917 password = (
const char *) prep_password;
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)
int errmsg(const char *fmt,...)
static char * build_client_first_message(fe_scram_state *state)
char * pg_fe_scram_build_secret(const char *password, const char **errstr)
const pg_fe_sasl_mech pg_scram_mech
static bool verify_server_signature(fe_scram_state *state, bool *match, const char **errstr)
static void * scram_init(PGconn *conn, const char *password, const char *sasl_mechanism)
static void scram_free(void *opaq)
static void scram_exchange(void *opaq, char *input, int inputlen, char **output, int *outputlen, bool *done, bool *success)
static bool read_server_first_message(fe_scram_state *state, char *input)
static bool scram_channel_bound(void *opaq)
static char * read_attr_value(char **input, char attr, PQExpBuffer errorMessage)
static bool calculate_client_proof(fe_scram_state *state, const char *client_final_message_without_proof, uint8 *result, const char **errstr)
static char * build_client_final_message(fe_scram_state *state)
static bool read_server_final_message(fe_scram_state *state, char *input)
void libpq_append_error(PQExpBuffer errorMessage, const char *fmt,...)
void libpq_append_conn_error(PGconn *conn, const char *fmt,...)
pg_hmac_ctx * pg_hmac_create(pg_cryptohash_type type)
const char * pg_hmac_error(pg_hmac_ctx *ctx)
void pg_hmac_free(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)
Assert(fmt[strlen(fmt) - 1] !='\n')
static void output(uint64 loop_count)
bool pg_strong_random(void *buf, size_t len)
void initPQExpBuffer(PQExpBuffer str)
int enlargePQExpBuffer(PQExpBuffer str, size_t needed)
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
void appendPQExpBufferChar(PQExpBuffer str, char ch)
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
void termPQExpBuffer(PQExpBuffer str)
#define PQExpBufferDataBroken(buf)
pg_saslprep_rc pg_saslprep(const char *input, char **output)
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_ClientKey(const uint8 *salted_password, pg_cryptohash_type hash_type, int key_length, uint8 *result, const char **errstr)
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_H(const uint8 *input, pg_cryptohash_type hash_type, int key_length, uint8 *result, const char **errstr)
#define SCRAM_DEFAULT_ITERATIONS
#define SCRAM_SHA_256_PLUS_NAME
#define SCRAM_RAW_NONCE_LEN
#define SCRAM_DEFAULT_SALT_LEN
#define SCRAM_MAX_KEY_LEN
#define SCRAM_SHA_256_KEY_LEN
char * client_final_message_without_proof
fe_scram_state_enum state
char * client_first_message_bare
char * server_final_message
char * server_first_message
pg_cryptohash_type hash_type
PQExpBufferData errorMessage