PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
crypt.h File Reference
Include dependency graph for crypt.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Typedefs

typedef enum PasswordType PasswordType
 

Enumerations

enum  PasswordType { PASSWORD_TYPE_PLAINTEXT = 0, PASSWORD_TYPE_MD5, PASSWORD_TYPE_SCRAM_SHA_256 }
 

Functions

PasswordType get_password_type (const char *shadow_pass)
 
char * encrypt_password (PasswordType target_type, const char *role, const char *password)
 
char * get_role_password (const char *role, char **logdetail)
 
int md5_crypt_verify (const char *role, const char *shadow_pass, const char *client_pass, const char *md5_salt, int md5_salt_len, char **logdetail)
 
int plain_crypt_verify (const char *role, const char *shadow_pass, const char *client_pass, char **logdetail)
 

Typedef Documentation

Enumeration Type Documentation

Enumerator
PASSWORD_TYPE_PLAINTEXT 
PASSWORD_TYPE_MD5 
PASSWORD_TYPE_SCRAM_SHA_256 

Definition at line 27 of file crypt.h.

Function Documentation

char* encrypt_password ( PasswordType  target_type,
const char *  role,
const char *  password 
)

Definition at line 108 of file crypt.c.

References elog, ERROR, get_password_type(), MD5_PASSWD_LEN, palloc(), PASSWORD_TYPE_MD5, PASSWORD_TYPE_PLAINTEXT, PASSWORD_TYPE_SCRAM_SHA_256, pg_be_scram_build_verifier(), pg_md5_encrypt(), and pstrdup().

Referenced by AlterRole(), and CreateRole().

110 {
111  PasswordType guessed_type = get_password_type(password);
112  char *encrypted_password;
113 
114  if (guessed_type != PASSWORD_TYPE_PLAINTEXT)
115  {
116  /*
117  * Cannot convert an already-encrypted password from one format to
118  * another, so return it as it is.
119  */
120  return pstrdup(password);
121  }
122 
123  switch (target_type)
124  {
125  case PASSWORD_TYPE_MD5:
126  encrypted_password = palloc(MD5_PASSWD_LEN + 1);
127 
128  if (!pg_md5_encrypt(password, role, strlen(role),
129  encrypted_password))
130  elog(ERROR, "password encryption failed");
131  return encrypted_password;
132 
135 
137  elog(ERROR, "cannot encrypt password with 'plaintext'");
138  }
139 
140  /*
141  * This shouldn't happen, because the above switch statements should
142  * handle every combination of source and target password types.
143  */
144  elog(ERROR, "cannot encrypt password to requested type");
145  return NULL; /* keep compiler quiet */
146 }
static char password[100]
Definition: streamutil.c:45
char * pstrdup(const char *in)
Definition: mcxt.c:1076
PasswordType get_password_type(const char *shadow_pass)
Definition: crypt.c:91
bool pg_md5_encrypt(const char *passwd, const char *salt, size_t salt_len, char *buf)
Definition: md5.c:323
#define ERROR
Definition: elog.h:43
PasswordType
Definition: crypt.h:27
#define MD5_PASSWD_LEN
Definition: md5.h:19
void * palloc(Size size)
Definition: mcxt.c:848
#define elog
Definition: elog.h:219
char * pg_be_scram_build_verifier(const char *password)
Definition: auth-scram.c:381
PasswordType get_password_type ( const char *  shadow_pass)

Definition at line 91 of file crypt.c.

References MD5_PASSWD_LEN, PASSWORD_TYPE_MD5, PASSWORD_TYPE_PLAINTEXT, and PASSWORD_TYPE_SCRAM_SHA_256.

Referenced by AlterRole(), CheckPWChallengeAuth(), CreateRole(), encrypt_password(), md5_crypt_verify(), pg_be_scram_init(), plain_crypt_verify(), and RenameRole().

92 {
93  if (strncmp(shadow_pass, "md5", 3) == 0 && strlen(shadow_pass) == MD5_PASSWD_LEN)
94  return PASSWORD_TYPE_MD5;
95  if (strncmp(shadow_pass, "SCRAM-SHA-256$", strlen("SCRAM-SHA-256$")) == 0)
98 }
#define MD5_PASSWD_LEN
Definition: md5.h:19
char* get_role_password ( const char *  role,
char **  logdetail 
)

Definition at line 39 of file crypt.c.

References _, Anum_pg_authid_rolpassword, Anum_pg_authid_rolvaliduntil, AUTHNAME, DatumGetTimestampTz, GetCurrentTimestamp(), HeapTupleIsValid, PointerGetDatum, psprintf(), ReleaseSysCache(), SearchSysCache1(), SysCacheGetAttr(), and TextDatumGetCString.

Referenced by CheckPasswordAuth(), and CheckPWChallengeAuth().

40 {
41  TimestampTz vuntil = 0;
42  HeapTuple roleTup;
43  Datum datum;
44  bool isnull;
45  char *shadow_pass;
46 
47  /* Get role info from pg_authid */
48  roleTup = SearchSysCache1(AUTHNAME, PointerGetDatum(role));
49  if (!HeapTupleIsValid(roleTup))
50  {
51  *logdetail = psprintf(_("Role \"%s\" does not exist."),
52  role);
53  return NULL; /* no such user */
54  }
55 
56  datum = SysCacheGetAttr(AUTHNAME, roleTup,
58  if (isnull)
59  {
60  ReleaseSysCache(roleTup);
61  *logdetail = psprintf(_("User \"%s\" has no password assigned."),
62  role);
63  return NULL; /* user has no password */
64  }
65  shadow_pass = TextDatumGetCString(datum);
66 
67  datum = SysCacheGetAttr(AUTHNAME, roleTup,
69  if (!isnull)
70  vuntil = DatumGetTimestampTz(datum);
71 
72  ReleaseSysCache(roleTup);
73 
74  /*
75  * Password OK, but check to be sure we are not past rolvaliduntil
76  */
77  if (!isnull && vuntil < GetCurrentTimestamp())
78  {
79  *logdetail = psprintf(_("User \"%s\" has an expired password."),
80  role);
81  return NULL;
82  }
83 
84  return shadow_pass;
85 }
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1570
int64 TimestampTz
Definition: timestamp.h:39
#define PointerGetDatum(X)
Definition: postgres.h:562
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
#define Anum_pg_authid_rolpassword
Definition: pg_authid.h:88
#define Anum_pg_authid_rolvaliduntil
Definition: pg_authid.h:89
#define DatumGetTimestampTz(X)
Definition: timestamp.h:28
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
#define TextDatumGetCString(d)
Definition: builtins.h:92
uintptr_t Datum
Definition: postgres.h:372
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1368
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define _(x)
Definition: elog.c:84
int md5_crypt_verify ( const char *  role,
const char *  shadow_pass,
const char *  client_pass,
const char *  md5_salt,
int  md5_salt_len,
char **  logdetail 
)

Definition at line 160 of file crypt.c.

References _, Assert, get_password_type(), MD5_PASSWD_LEN, PASSWORD_TYPE_MD5, pg_md5_encrypt(), psprintf(), STATUS_ERROR, and STATUS_OK.

Referenced by CheckMD5Auth().

164 {
165  int retval;
166  char crypt_pwd[MD5_PASSWD_LEN + 1];
167 
168  Assert(md5_salt_len > 0);
169 
170  if (get_password_type(shadow_pass) != PASSWORD_TYPE_MD5)
171  {
172  /* incompatible password hash format. */
173  *logdetail = psprintf(_("User \"%s\" has a password that cannot be used with MD5 authentication."),
174  role);
175  return STATUS_ERROR;
176  }
177 
178  /*
179  * Compute the correct answer for the MD5 challenge.
180  *
181  * We do not bother setting logdetail for any pg_md5_encrypt failure
182  * below: the only possible error is out-of-memory, which is unlikely, and
183  * if it did happen adding a psprintf call would only make things worse.
184  */
185  /* stored password already encrypted, only do salt */
186  if (!pg_md5_encrypt(shadow_pass + strlen("md5"),
187  md5_salt, md5_salt_len,
188  crypt_pwd))
189  {
190  return STATUS_ERROR;
191  }
192 
193  if (strcmp(client_pass, crypt_pwd) == 0)
194  retval = STATUS_OK;
195  else
196  {
197  *logdetail = psprintf(_("Password does not match for user \"%s\"."),
198  role);
199  retval = STATUS_ERROR;
200  }
201 
202  return retval;
203 }
PasswordType get_password_type(const char *shadow_pass)
Definition: crypt.c:91
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
#define STATUS_ERROR
Definition: c.h:982
bool pg_md5_encrypt(const char *passwd, const char *salt, size_t salt_len, char *buf)
Definition: md5.c:323
#define STATUS_OK
Definition: c.h:981
#define MD5_PASSWD_LEN
Definition: md5.h:19
#define Assert(condition)
Definition: c.h:681
#define _(x)
Definition: elog.c:84
int plain_crypt_verify ( const char *  role,
const char *  shadow_pass,
const char *  client_pass,
char **  logdetail 
)

Definition at line 216 of file crypt.c.

References _, get_password_type(), MD5_PASSWD_LEN, PASSWORD_TYPE_MD5, PASSWORD_TYPE_PLAINTEXT, PASSWORD_TYPE_SCRAM_SHA_256, pg_md5_encrypt(), psprintf(), scram_verify_plain_password(), STATUS_ERROR, and STATUS_OK.

Referenced by AlterRole(), check_password(), CheckPasswordAuth(), and CreateRole().

219 {
220  char crypt_client_pass[MD5_PASSWD_LEN + 1];
221 
222  /*
223  * Client sent password in plaintext. If we have an MD5 hash stored, hash
224  * the password the client sent, and compare the hashes. Otherwise
225  * compare the plaintext passwords directly.
226  */
227  switch (get_password_type(shadow_pass))
228  {
231  client_pass,
232  shadow_pass))
233  {
234  return STATUS_OK;
235  }
236  else
237  {
238  *logdetail = psprintf(_("Password does not match for user \"%s\"."),
239  role);
240  return STATUS_ERROR;
241  }
242  break;
243 
244  case PASSWORD_TYPE_MD5:
245  if (!pg_md5_encrypt(client_pass,
246  role,
247  strlen(role),
248  crypt_client_pass))
249  {
250  /*
251  * We do not bother setting logdetail for pg_md5_encrypt
252  * failure: the only possible error is out-of-memory, which is
253  * unlikely, and if it did happen adding a psprintf call would
254  * only make things worse.
255  */
256  return STATUS_ERROR;
257  }
258  if (strcmp(crypt_client_pass, shadow_pass) == 0)
259  return STATUS_OK;
260  else
261  {
262  *logdetail = psprintf(_("Password does not match for user \"%s\"."),
263  role);
264  return STATUS_ERROR;
265  }
266  break;
267 
269 
270  /*
271  * We never store passwords in plaintext, so this shouldn't
272  * happen.
273  */
274  break;
275  }
276 
277  /*
278  * This shouldn't happen. Plain "password" authentication is possible
279  * with any kind of stored password hash.
280  */
281  *logdetail = psprintf(_("Password of user \"%s\" is in unrecognized format."),
282  role);
283  return STATUS_ERROR;
284 }
bool scram_verify_plain_password(const char *username, const char *password, const char *verifier)
Definition: auth-scram.c:418
PasswordType get_password_type(const char *shadow_pass)
Definition: crypt.c:91
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
#define STATUS_ERROR
Definition: c.h:982
bool pg_md5_encrypt(const char *passwd, const char *salt, size_t salt_len, char *buf)
Definition: md5.c:323
#define STATUS_OK
Definition: c.h:981
#define MD5_PASSWD_LEN
Definition: md5.h:19
#define _(x)
Definition: elog.c:84