PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
scram.h File Reference
#include "common/cryptohash.h"
#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, pg_cryptohash_type *hash_type, int *key_length, char **salt, uint8 *stored_key, uint8 *server_key)
 
bool scram_verify_plain_password (const char *username, const char *password, const char *secret)
 

Variables

PGDLLIMPORT int scram_sha_256_iterations
 
PGDLLIMPORT const pg_be_sasl_mech pg_be_scram_mech
 

Function Documentation

◆ parse_scram_secret()

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 
)

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

603{
604 char *v;
605 char *p;
606 char *scheme_str;
607 char *salt_str;
608 char *iterations_str;
609 char *storedkey_str;
610 char *serverkey_str;
611 int decoded_len;
612 char *decoded_salt_buf;
613 char *decoded_stored_buf;
614 char *decoded_server_buf;
615
616 /*
617 * The secret is of form:
618 *
619 * SCRAM-SHA-256$<iterations>:<salt>$<storedkey>:<serverkey>
620 */
621 v = pstrdup(secret);
622 scheme_str = strsep(&v, "$");
623 if (v == NULL)
624 goto invalid_secret;
625 iterations_str = strsep(&v, ":");
626 if (v == NULL)
627 goto invalid_secret;
628 salt_str = strsep(&v, "$");
629 if (v == NULL)
630 goto invalid_secret;
631 storedkey_str = strsep(&v, ":");
632 if (v == NULL)
633 goto invalid_secret;
634 serverkey_str = v;
635
636 /* Parse the fields */
637 if (strcmp(scheme_str, "SCRAM-SHA-256") != 0)
638 goto invalid_secret;
639 *hash_type = PG_SHA256;
640 *key_length = SCRAM_SHA_256_KEY_LEN;
641
642 errno = 0;
643 *iterations = strtol(iterations_str, &p, 10);
644 if (*p || errno != 0)
645 goto invalid_secret;
646
647 /*
648 * Verify that the salt is in Base64-encoded format, by decoding it,
649 * although we return the encoded version to the caller.
650 */
651 decoded_len = pg_b64_dec_len(strlen(salt_str));
652 decoded_salt_buf = palloc(decoded_len);
653 decoded_len = pg_b64_decode(salt_str, strlen(salt_str),
654 decoded_salt_buf, decoded_len);
655 if (decoded_len < 0)
656 goto invalid_secret;
657 *salt = pstrdup(salt_str);
658
659 /*
660 * Decode StoredKey and ServerKey.
661 */
662 decoded_len = pg_b64_dec_len(strlen(storedkey_str));
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)
667 goto invalid_secret;
668 memcpy(stored_key, decoded_stored_buf, *key_length);
669
670 decoded_len = pg_b64_dec_len(strlen(serverkey_str));
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)
675 goto invalid_secret;
676 memcpy(server_key, decoded_server_buf, *key_length);
677
678 return true;
679
680invalid_secret:
681 *salt = NULL;
682 return false;
683}
int pg_b64_decode(const char *src, int len, char *dst, int dstlen)
Definition: base64.c:116
int pg_b64_dec_len(int srclen)
Definition: base64.c:239
@ PG_SHA256
Definition: cryptohash.h:24
char * pstrdup(const char *in)
Definition: mcxt.c:1696
void * palloc(Size size)
Definition: mcxt.c:1317
char * strsep(char **stringp, const char *delim)
Definition: strsep.c:49
#define SCRAM_SHA_256_KEY_LEN
Definition: scram-common.h:24
int iterations
Definition: thread-thread.c:39

References iterations, palloc(), pg_b64_dec_len(), pg_b64_decode(), PG_SHA256, pstrdup(), SCRAM_SHA_256_KEY_LEN, and strsep().

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

◆ pg_be_scram_build_secret()

char * pg_be_scram_build_secret ( const char *  password)

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

484{
485 char *prep_password;
487 char saltbuf[SCRAM_DEFAULT_SALT_LEN];
488 char *result;
489 const char *errstr = NULL;
490
491 /*
492 * Normalize the password with SASLprep. If that doesn't work, because
493 * the password isn't valid UTF-8 or contains prohibited characters, just
494 * proceed with the original password. (See comments at top of file.)
495 */
496 rc = pg_saslprep(password, &prep_password);
497 if (rc == SASLPREP_SUCCESS)
498 password = (const char *) prep_password;
499
500 /* Generate random salt */
503 (errcode(ERRCODE_INTERNAL_ERROR),
504 errmsg("could not generate random salt")));
505
507 saltbuf, SCRAM_DEFAULT_SALT_LEN,
509 &errstr);
510
511 if (prep_password)
512 pfree(prep_password);
513
514 return result;
515}
int scram_sha_256_iterations
Definition: auth-scram.c:196
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
void pfree(void *pointer)
Definition: mcxt.c:1521
bool pg_strong_random(void *buf, size_t len)
pg_saslprep_rc pg_saslprep(const char *input, char **output)
Definition: saslprep.c:1047
pg_saslprep_rc
Definition: saslprep.h:21
@ SASLPREP_SUCCESS
Definition: saslprep.h:22
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)
Definition: scram-common.c:209
#define SCRAM_DEFAULT_SALT_LEN
Definition: scram-common.h:44
static char * password
Definition: streamutil.c:52

References ereport, errcode(), errmsg(), ERROR, password, pfree(), pg_saslprep(), PG_SHA256, pg_strong_random(), SASLPREP_SUCCESS, scram_build_secret(), SCRAM_DEFAULT_SALT_LEN, scram_sha_256_iterations, and SCRAM_SHA_256_KEY_LEN.

Referenced by encrypt_password().

◆ scram_verify_plain_password()

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

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

525{
526 char *encoded_salt;
527 char *salt;
528 int saltlen;
529 int iterations;
530 int key_length = 0;
531 pg_cryptohash_type hash_type;
532 uint8 salted_password[SCRAM_MAX_KEY_LEN];
533 uint8 stored_key[SCRAM_MAX_KEY_LEN];
534 uint8 server_key[SCRAM_MAX_KEY_LEN];
535 uint8 computed_key[SCRAM_MAX_KEY_LEN];
536 char *prep_password;
538 const char *errstr = NULL;
539
540 if (!parse_scram_secret(secret, &iterations, &hash_type, &key_length,
541 &encoded_salt, stored_key, server_key))
542 {
543 /*
544 * The password looked like a SCRAM secret, but could not be parsed.
545 */
546 ereport(LOG,
547 (errmsg("invalid SCRAM secret for user \"%s\"", username)));
548 return false;
549 }
550
551 saltlen = pg_b64_dec_len(strlen(encoded_salt));
552 salt = palloc(saltlen);
553 saltlen = pg_b64_decode(encoded_salt, strlen(encoded_salt), salt,
554 saltlen);
555 if (saltlen < 0)
556 {
557 ereport(LOG,
558 (errmsg("invalid SCRAM secret for user \"%s\"", username)));
559 return false;
560 }
561
562 /* Normalize the password */
563 rc = pg_saslprep(password, &prep_password);
564 if (rc == SASLPREP_SUCCESS)
565 password = prep_password;
566
567 /* Compute Server Key based on the user-supplied plaintext password */
568 if (scram_SaltedPassword(password, hash_type, key_length,
569 salt, saltlen, iterations,
570 salted_password, &errstr) < 0 ||
571 scram_ServerKey(salted_password, hash_type, key_length,
572 computed_key, &errstr) < 0)
573 {
574 elog(ERROR, "could not compute server key: %s", errstr);
575 }
576
577 if (prep_password)
578 pfree(prep_password);
579
580 /*
581 * Compare the secret's Server Key with the one computed from the
582 * user-supplied password.
583 */
584 return memcmp(computed_key, server_key, key_length) == 0;
585}
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)
Definition: auth-scram.c:600
uint8_t uint8
Definition: c.h:486
pg_cryptohash_type
Definition: cryptohash.h:20
#define LOG
Definition: elog.h:31
#define elog(elevel,...)
Definition: elog.h:225
static char * username
Definition: initdb.c:153
int scram_ServerKey(const uint8 *salted_password, pg_cryptohash_type hash_type, int key_length, uint8 *result, const char **errstr)
Definition: scram-common.c:172
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)
Definition: scram-common.c:38
#define SCRAM_MAX_KEY_LEN
Definition: scram-common.h:30

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

Referenced by plain_crypt_verify().

Variable Documentation

◆ pg_be_scram_mech

PGDLLIMPORT const pg_be_sasl_mech pg_be_scram_mech
extern

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

Referenced by CheckPWChallengeAuth().

◆ scram_sha_256_iterations

PGDLLIMPORT int scram_sha_256_iterations
extern

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

Referenced by pg_be_scram_build_secret().