PostgreSQL Source Code git master
Loading...
Searching...
No Matches
crypt.c File Reference
#include "postgres.h"
#include <unistd.h>
#include "catalog/pg_authid.h"
#include "common/md5.h"
#include "common/scram-common.h"
#include "libpq/crypt.h"
#include "libpq/scram.h"
#include "miscadmin.h"
#include "utils/builtins.h"
#include "utils/memutils.h"
#include "utils/syscache.h"
#include "utils/timestamp.h"
Include dependency graph for crypt.c:

Go to the source code of this file.

Functions

charget_role_password (const char *role, const char **logdetail)
 
PasswordType get_password_type (const char *shadow_pass)
 
charencrypt_password (PasswordType target_type, const char *role, const char *password)
 
int md5_crypt_verify (const char *role, const char *shadow_pass, const char *client_pass, const uint8 *md5_salt, int md5_salt_len, const char **logdetail)
 
int plain_crypt_verify (const char *role, const char *shadow_pass, const char *client_pass, const char **logdetail)
 

Variables

int password_expiration_warning_threshold = 604800
 
bool md5_password_warnings = true
 

Function Documentation

◆ encrypt_password()

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

Definition at line 180 of file crypt.c.

182{
184 char *encrypted_password = NULL;
185 const char *errstr = NULL;
186
188 {
189 /*
190 * Cannot convert an already-encrypted password from one format to
191 * another, so return it as it is.
192 */
194 }
195 else
196 {
197 switch (target_type)
198 {
201
202 if (!pg_md5_encrypt(password, (const uint8 *) role, strlen(role),
204 elog(ERROR, "password encryption failed: %s", errstr);
205 break;
206
209 break;
210
212 elog(ERROR, "cannot encrypt password with 'plaintext'");
213 break;
214 }
215 }
216
218
219 /*
220 * Valid password hashes may be very long, but we don't want to store
221 * anything that might need out-of-line storage, since de-TOASTing won't
222 * work during authentication because we haven't selected a database yet
223 * and cannot read pg_class. 512 bytes should be more than enough for all
224 * practical use, so fail for anything longer.
225 */
226 if (encrypted_password && /* keep compiler quiet */
228 {
229 /*
230 * We don't expect any of our own hashing routines to produce hashes
231 * that are too long.
232 */
234
237 errmsg("encrypted password is too long"),
238 errdetail("Encrypted passwords must be no longer than %d bytes.",
240 }
241
246 errmsg("setting an MD5-encrypted password"),
247 errdetail("MD5 password support is deprecated and will be removed in a future release of PostgreSQL."),
248 errhint("Refer to the PostgreSQL documentation for details about migrating to another password type.")));
249
250 return encrypted_password;
251}
char * pg_be_scram_build_secret(const char *password)
Definition auth-scram.c:481
uint8_t uint8
Definition c.h:556
#define Assert(condition)
Definition c.h:885
bool md5_password_warnings
Definition crypt.c:33
PasswordType get_password_type(const char *shadow_pass)
Definition crypt.c:153
PasswordType
Definition crypt.h:44
@ PASSWORD_TYPE_PLAINTEXT
Definition crypt.h:45
@ PASSWORD_TYPE_SCRAM_SHA_256
Definition crypt.h:47
@ PASSWORD_TYPE_MD5
Definition crypt.h:46
#define MAX_ENCRYPTED_PASSWORD_LEN
Definition crypt.h:26
int errcode(int sqlerrcode)
Definition elog.c:874
int errmsg(const char *fmt,...)
Definition elog.c:1093
int errhint(const char *fmt,...) pg_attribute_printf(1
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define WARNING
Definition elog.h:36
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
#define ereport(elevel,...)
Definition elog.h:150
char * pstrdup(const char *in)
Definition mcxt.c:1781
void * palloc(Size size)
Definition mcxt.c:1387
#define MD5_PASSWD_LEN
Definition md5.h:26
bool pg_md5_encrypt(const char *passwd, const uint8 *salt, size_t salt_len, char *buf, const char **errstr)
Definition md5_common.c:145
static int fb(int x)
static char * password
Definition streamutil.c:51

References Assert, elog, ereport, errcode(), errdetail(), errhint(), errmsg(), ERROR, fb(), get_password_type(), MAX_ENCRYPTED_PASSWORD_LEN, MD5_PASSWD_LEN, md5_password_warnings, palloc(), password, PASSWORD_TYPE_MD5, PASSWORD_TYPE_PLAINTEXT, PASSWORD_TYPE_SCRAM_SHA_256, pg_be_scram_build_secret(), pg_md5_encrypt(), pstrdup(), and WARNING.

Referenced by AlterRole(), and CreateRole().

◆ get_password_type()

PasswordType get_password_type ( const char shadow_pass)

Definition at line 153 of file crypt.c.

154{
155 char *encoded_salt;
156 int iterations;
157 int key_length = 0;
158 pg_cryptohash_type hash_type;
161
162 if (strncmp(shadow_pass, "md5", 3) == 0 &&
165 return PASSWORD_TYPE_MD5;
166 if (parse_scram_secret(shadow_pass, &iterations, &hash_type, &key_length,
170}
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:598
pg_cryptohash_type
Definition cryptohash.h:20
#define MD5_PASSWD_CHARSET
Definition md5.h:25
#define SCRAM_MAX_KEY_LEN
int iterations

References fb(), iterations, MD5_PASSWD_CHARSET, MD5_PASSWD_LEN, parse_scram_secret(), PASSWORD_TYPE_MD5, PASSWORD_TYPE_PLAINTEXT, PASSWORD_TYPE_SCRAM_SHA_256, and SCRAM_MAX_KEY_LEN.

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

◆ get_role_password()

char * get_role_password ( const char role,
const char **  logdetail 
)

Definition at line 43 of file crypt.c.

44{
47 Datum datum;
48 bool isnull;
49 char *shadow_pass;
50
51 /* Get role info from pg_authid */
54 {
55 *logdetail = psprintf(_("Role \"%s\" does not exist."),
56 role);
57 return NULL; /* no such user */
58 }
59
62 if (isnull)
63 {
65 *logdetail = psprintf(_("User \"%s\" has no password assigned."),
66 role);
67 return NULL; /* user has no password */
68 }
70
73 if (!isnull)
75
77
78 /*
79 * Password OK, but check to be sure we are not past rolvaliduntil or
80 * password_expiration_warning_threshold.
81 */
82 if (!isnull)
83 {
86
87 /*
88 * If we're past rolvaliduntil, the connection attempt should fail, so
89 * update logdetail and return NULL.
90 */
91 if (vuntil < now)
92 {
93 *logdetail = psprintf(_("User \"%s\" has an expired password."),
94 role);
95 return NULL;
96 }
97
98 /*
99 * If we're past the warning threshold, the connection attempt should
100 * succeed, but we still want to emit a warning. To do so, we queue
101 * the warning message using StoreConnectionWarning() so that it will
102 * be emitted at the end of InitPostgres(), and we return normally.
103 */
105 {
106 MemoryContext oldcontext;
107 int days;
108 int hours;
109 int minutes;
110 char *warning;
111 char *detail;
112
114
118
119 warning = pstrdup(_("role password will expire soon"));
120
121 if (days > 0)
122 detail = psprintf(ngettext("The password for role \"%s\" will expire in %d day.",
123 "The password for role \"%s\" will expire in %d days.",
124 days),
125 role, days);
126 else if (hours > 0)
127 detail = psprintf(ngettext("The password for role \"%s\" will expire in %d hour.",
128 "The password for role \"%s\" will expire in %d hours.",
129 hours),
130 role, hours);
131 else if (minutes > 0)
132 detail = psprintf(ngettext("The password for role \"%s\" will expire in %d minute.",
133 "The password for role \"%s\" will expire in %d minutes.",
134 minutes),
135 role, minutes);
136 else
137 detail = psprintf(_("The password for role \"%s\" will expire in less than 1 minute."),
138 role);
139
141
142 MemoryContextSwitchTo(oldcontext);
143 }
144 }
145
146 return shadow_pass;
147}
const char *const days[]
Definition datetime.c:84
TimestampTz GetCurrentTimestamp(void)
Definition timestamp.c:1645
Datum now(PG_FUNCTION_ARGS)
Definition timestamp.c:1609
#define TextDatumGetCString(d)
Definition builtins.h:99
#define ngettext(s, p, n)
Definition c.h:1198
uint64_t uint64
Definition c.h:559
int password_expiration_warning_threshold
Definition crypt.c:30
int64 TimestampTz
Definition timestamp.h:39
#define USECS_PER_HOUR
Definition timestamp.h:132
#define USECS_PER_DAY
Definition timestamp.h:131
#define USECS_PER_SEC
Definition timestamp.h:134
#define USECS_PER_MINUTE
Definition timestamp.h:133
#define _(x)
Definition elog.c:95
#define HeapTupleIsValid(tuple)
Definition htup.h:78
MemoryContext TopMemoryContext
Definition mcxt.c:166
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
static Datum PointerGetDatum(const void *X)
Definition postgres.h:352
uint64_t Datum
Definition postgres.h:70
void StoreConnectionWarning(char *msg, char *detail)
Definition postinit.c:1472
char * psprintf(const char *fmt,...)
Definition psprintf.c:43
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:264
HeapTuple SearchSysCache1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:220
Datum SysCacheGetAttr(SysCacheIdentifier cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition syscache.c:595
static uint64 TimestampDifferenceMicroseconds(TimestampTz start_time, TimestampTz stop_time)
Definition timestamp.h:90
static TimestampTz DatumGetTimestampTz(Datum X)
Definition timestamp.h:34
static void static void static void warning(const char *const string,...) pg_attribute_printf(1
Definition zic.c:529

References _, DatumGetTimestampTz(), days, fb(), GetCurrentTimestamp(), HeapTupleIsValid, MemoryContextSwitchTo(), ngettext, now(), password_expiration_warning_threshold, PointerGetDatum(), psprintf(), pstrdup(), ReleaseSysCache(), SearchSysCache1(), StoreConnectionWarning(), SysCacheGetAttr(), TextDatumGetCString, TimestampDifferenceMicroseconds(), TopMemoryContext, USECS_PER_DAY, USECS_PER_HOUR, USECS_PER_MINUTE, USECS_PER_SEC, and warning().

Referenced by CheckPasswordAuth(), and CheckPWChallengeAuth().

◆ md5_crypt_verify()

int md5_crypt_verify ( const char role,
const char shadow_pass,
const char client_pass,
const uint8 md5_salt,
int  md5_salt_len,
const char **  logdetail 
)

Definition at line 265 of file crypt.c.

269{
270 int retval;
271 char crypt_pwd[MD5_PASSWD_LEN + 1];
272 const char *errstr = NULL;
273
274 Assert(md5_salt_len > 0);
275
277 {
278 /* incompatible password hash format. */
279 *logdetail = psprintf(_("User \"%s\" has a password that cannot be used with MD5 authentication."),
280 role);
281 return STATUS_ERROR;
282 }
283
284 /*
285 * Compute the correct answer for the MD5 challenge.
286 */
287 /* stored password already encrypted, only do salt */
288 if (!pg_md5_encrypt(shadow_pass + strlen("md5"),
290 crypt_pwd, &errstr))
291 {
292 *logdetail = errstr;
293 return STATUS_ERROR;
294 }
295
296 if (strcmp(client_pass, crypt_pwd) == 0)
297 {
298 retval = STATUS_OK;
299
301 {
302 MemoryContext oldcontext;
303 char *warning;
304 char *detail;
305
307
308 warning = pstrdup(_("authenticated with an MD5-encrypted password"));
309 detail = pstrdup(_("MD5 password support is deprecated and will be removed in a future release of PostgreSQL."));
311
312 MemoryContextSwitchTo(oldcontext);
313 }
314 }
315 else
316 {
317 *logdetail = psprintf(_("Password does not match for user \"%s\"."),
318 role);
319 retval = STATUS_ERROR;
320 }
321
322 return retval;
323}
#define STATUS_OK
Definition c.h:1186
#define STATUS_ERROR
Definition c.h:1187

References _, Assert, fb(), get_password_type(), MD5_PASSWD_LEN, md5_password_warnings, MemoryContextSwitchTo(), PASSWORD_TYPE_MD5, pg_md5_encrypt(), psprintf(), pstrdup(), STATUS_ERROR, STATUS_OK, StoreConnectionWarning(), TopMemoryContext, and warning().

Referenced by CheckMD5Auth().

◆ plain_crypt_verify()

int plain_crypt_verify ( const char role,
const char shadow_pass,
const char client_pass,
const char **  logdetail 
)

Definition at line 336 of file crypt.c.

339{
341 const char *errstr = NULL;
342
343 /*
344 * Client sent password in plaintext. If we have an MD5 hash stored, hash
345 * the password the client sent, and compare the hashes. Otherwise
346 * compare the plaintext passwords directly.
347 */
349 {
354 {
355 return STATUS_OK;
356 }
357 else
358 {
359 *logdetail = psprintf(_("Password does not match for user \"%s\"."),
360 role);
361 return STATUS_ERROR;
362 }
363 break;
364
367 (const uint8 *) role,
368 strlen(role),
370 &errstr))
371 {
372 *logdetail = errstr;
373 return STATUS_ERROR;
374 }
376 return STATUS_OK;
377 else
378 {
379 *logdetail = psprintf(_("Password does not match for user \"%s\"."),
380 role);
381 return STATUS_ERROR;
382 }
383 break;
384
386
387 /*
388 * We never store passwords in plaintext, so this shouldn't
389 * happen.
390 */
391 break;
392 }
393
394 /*
395 * This shouldn't happen. Plain "password" authentication is possible
396 * with any kind of stored password hash.
397 */
398 *logdetail = psprintf(_("Password of user \"%s\" is in unrecognized format."),
399 role);
400 return STATUS_ERROR;
401}
bool scram_verify_plain_password(const char *username, const char *password, const char *secret)
Definition auth-scram.c:521

References _, fb(), 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().

Variable Documentation

◆ md5_password_warnings

bool md5_password_warnings = true

Definition at line 33 of file crypt.c.

Referenced by encrypt_password(), and md5_crypt_verify().

◆ password_expiration_warning_threshold

int password_expiration_warning_threshold = 604800

Definition at line 30 of file crypt.c.

Referenced by get_role_password().