PostgreSQL Source Code  git master
scram.h File Reference
#include "lib/stringinfo.h"
#include "libpq/libpq-be.h"
#include "libpq/sasl.h"
Include dependency graph for scram.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

char * pg_be_scram_build_secret (const char *password)
 
bool parse_scram_secret (const char *secret, int *iterations, char **salt, uint8 *stored_key, uint8 *server_key)
 
bool scram_verify_plain_password (const char *username, const char *password, const char *secret)
 

Variables

const pg_be_sasl_mech pg_be_scram_mech
 

Function Documentation

◆ parse_scram_secret()

bool parse_scram_secret ( const char *  secret,
int *  iterations,
char **  salt,
uint8 stored_key,
uint8 server_key 
)

Definition at line 570 of file auth-scram.c.

References palloc(), pg_b64_dec_len(), pg_b64_decode(), pstrdup(), and SCRAM_KEY_LEN.

Referenced by get_password_type(), scram_init(), and scram_verify_plain_password().

572 {
573  char *v;
574  char *p;
575  char *scheme_str;
576  char *salt_str;
577  char *iterations_str;
578  char *storedkey_str;
579  char *serverkey_str;
580  int decoded_len;
581  char *decoded_salt_buf;
582  char *decoded_stored_buf;
583  char *decoded_server_buf;
584 
585  /*
586  * The secret is of form:
587  *
588  * SCRAM-SHA-256$<iterations>:<salt>$<storedkey>:<serverkey>
589  */
590  v = pstrdup(secret);
591  if ((scheme_str = strtok(v, "$")) == NULL)
592  goto invalid_secret;
593  if ((iterations_str = strtok(NULL, ":")) == NULL)
594  goto invalid_secret;
595  if ((salt_str = strtok(NULL, "$")) == NULL)
596  goto invalid_secret;
597  if ((storedkey_str = strtok(NULL, ":")) == NULL)
598  goto invalid_secret;
599  if ((serverkey_str = strtok(NULL, "")) == NULL)
600  goto invalid_secret;
601 
602  /* Parse the fields */
603  if (strcmp(scheme_str, "SCRAM-SHA-256") != 0)
604  goto invalid_secret;
605 
606  errno = 0;
607  *iterations = strtol(iterations_str, &p, 10);
608  if (*p || errno != 0)
609  goto invalid_secret;
610 
611  /*
612  * Verify that the salt is in Base64-encoded format, by decoding it,
613  * although we return the encoded version to the caller.
614  */
615  decoded_len = pg_b64_dec_len(strlen(salt_str));
616  decoded_salt_buf = palloc(decoded_len);
617  decoded_len = pg_b64_decode(salt_str, strlen(salt_str),
618  decoded_salt_buf, decoded_len);
619  if (decoded_len < 0)
620  goto invalid_secret;
621  *salt = pstrdup(salt_str);
622 
623  /*
624  * Decode StoredKey and ServerKey.
625  */
626  decoded_len = pg_b64_dec_len(strlen(storedkey_str));
627  decoded_stored_buf = palloc(decoded_len);
628  decoded_len = pg_b64_decode(storedkey_str, strlen(storedkey_str),
629  decoded_stored_buf, decoded_len);
630  if (decoded_len != SCRAM_KEY_LEN)
631  goto invalid_secret;
632  memcpy(stored_key, decoded_stored_buf, SCRAM_KEY_LEN);
633 
634  decoded_len = pg_b64_dec_len(strlen(serverkey_str));
635  decoded_server_buf = palloc(decoded_len);
636  decoded_len = pg_b64_decode(serverkey_str, strlen(serverkey_str),
637  decoded_server_buf, decoded_len);
638  if (decoded_len != SCRAM_KEY_LEN)
639  goto invalid_secret;
640  memcpy(server_key, decoded_server_buf, SCRAM_KEY_LEN);
641 
642  return true;
643 
644 invalid_secret:
645  *salt = NULL;
646  return false;
647 }
char * pstrdup(const char *in)
Definition: mcxt.c:1299
int pg_b64_dec_len(int srclen)
Definition: base64.c:239
int pg_b64_decode(const char *src, int len, char *dst, int dstlen)
Definition: base64.c:116
void * palloc(Size size)
Definition: mcxt.c:1062
#define SCRAM_KEY_LEN
Definition: scram-common.h:24

◆ pg_be_scram_build_secret()

char* pg_be_scram_build_secret ( const char *  password)

Definition at line 461 of file auth-scram.c.

References ereport, errcode(), errmsg(), ERROR, pfree(), pg_saslprep(), pg_strong_random(), SASLPREP_SUCCESS, scram_build_secret(), SCRAM_DEFAULT_ITERATIONS, and SCRAM_DEFAULT_SALT_LEN.

Referenced by encrypt_password().

462 {
463  char *prep_password;
464  pg_saslprep_rc rc;
465  char saltbuf[SCRAM_DEFAULT_SALT_LEN];
466  char *result;
467 
468  /*
469  * Normalize the password with SASLprep. If that doesn't work, because
470  * the password isn't valid UTF-8 or contains prohibited characters, just
471  * proceed with the original password. (See comments at top of file.)
472  */
473  rc = pg_saslprep(password, &prep_password);
474  if (rc == SASLPREP_SUCCESS)
475  password = (const char *) prep_password;
476 
477  /* Generate random salt */
479  ereport(ERROR,
480  (errcode(ERRCODE_INTERNAL_ERROR),
481  errmsg("could not generate random salt")));
482 
483  result = scram_build_secret(saltbuf, SCRAM_DEFAULT_SALT_LEN,
485 
486  if (prep_password)
487  pfree(prep_password);
488 
489  return result;
490 }
int errcode(int sqlerrcode)
Definition: elog.c:698
char * scram_build_secret(const char *salt, int saltlen, int iterations, const char *password)
Definition: scram-common.c:169
pg_saslprep_rc pg_saslprep(const char *input, char **output)
Definition: saslprep.c:1044
pg_saslprep_rc
Definition: saslprep.h:20
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ERROR
Definition: elog.h:46
static char * password
Definition: streamutil.c:53
#define SCRAM_DEFAULT_SALT_LEN
Definition: scram-common.h:41
#define ereport(elevel,...)
Definition: elog.h:157
bool pg_strong_random(void *buf, size_t len)
#define SCRAM_DEFAULT_ITERATIONS
Definition: scram-common.h:47
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ scram_verify_plain_password()

bool scram_verify_plain_password ( const char *  username,
const char *  password,
const char *  secret 
)

Definition at line 498 of file auth-scram.c.

References elog, ereport, errmsg(), ERROR, LOG, palloc(), parse_scram_secret(), pfree(), pg_b64_dec_len(), pg_b64_decode(), pg_saslprep(), SASLPREP_SUCCESS, SCRAM_KEY_LEN, scram_SaltedPassword(), and scram_ServerKey().

Referenced by plain_crypt_verify().

500 {
501  char *encoded_salt;
502  char *salt;
503  int saltlen;
504  int iterations;
505  uint8 salted_password[SCRAM_KEY_LEN];
506  uint8 stored_key[SCRAM_KEY_LEN];
507  uint8 server_key[SCRAM_KEY_LEN];
508  uint8 computed_key[SCRAM_KEY_LEN];
509  char *prep_password;
510  pg_saslprep_rc rc;
511 
512  if (!parse_scram_secret(secret, &iterations, &encoded_salt,
513  stored_key, server_key))
514  {
515  /*
516  * The password looked like a SCRAM secret, but could not be parsed.
517  */
518  ereport(LOG,
519  (errmsg("invalid SCRAM secret for user \"%s\"", username)));
520  return false;
521  }
522 
523  saltlen = pg_b64_dec_len(strlen(encoded_salt));
524  salt = palloc(saltlen);
525  saltlen = pg_b64_decode(encoded_salt, strlen(encoded_salt), salt,
526  saltlen);
527  if (saltlen < 0)
528  {
529  ereport(LOG,
530  (errmsg("invalid SCRAM secret for user \"%s\"", username)));
531  return false;
532  }
533 
534  /* Normalize the password */
535  rc = pg_saslprep(password, &prep_password);
536  if (rc == SASLPREP_SUCCESS)
537  password = prep_password;
538 
539  /* Compute Server Key based on the user-supplied plaintext password */
540  if (scram_SaltedPassword(password, salt, saltlen, iterations,
541  salted_password) < 0 ||
542  scram_ServerKey(salted_password, computed_key) < 0)
543  {
544  elog(ERROR, "could not compute server key");
545  }
546 
547  if (prep_password)
548  pfree(prep_password);
549 
550  /*
551  * Compare the secret's Server Key with the one computed from the
552  * user-supplied password.
553  */
554  return memcmp(computed_key, server_key, SCRAM_KEY_LEN) == 0;
555 }
unsigned char uint8
Definition: c.h:439
pg_saslprep_rc pg_saslprep(const char *input, char **output)
Definition: saslprep.c:1044
#define LOG
Definition: elog.h:26
int scram_ServerKey(const uint8 *salted_password, uint8 *result)
Definition: scram-common.c:140
int pg_b64_dec_len(int srclen)
Definition: base64.c:239
pg_saslprep_rc
Definition: saslprep.h:20
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ERROR
Definition: elog.h:46
static char * password
Definition: streamutil.c:53
const char * username
Definition: pgbench.c:282
int pg_b64_decode(const char *src, int len, char *dst, int dstlen)
Definition: base64.c:116
#define ereport(elevel,...)
Definition: elog.h:157
int scram_SaltedPassword(const char *password, const char *salt, int saltlen, int iterations, uint8 *result)
Definition: scram-common.c:34
bool parse_scram_secret(const char *secret, int *iterations, char **salt, uint8 *stored_key, uint8 *server_key)
Definition: auth-scram.c:570
void * palloc(Size size)
Definition: mcxt.c:1062
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
#define SCRAM_KEY_LEN
Definition: scram-common.h:24

Variable Documentation

◆ pg_be_scram_mech

const pg_be_sasl_mech pg_be_scram_mech

Definition at line 117 of file auth-scram.c.

Referenced by CheckPWChallengeAuth().