0001-Improve-error-reporting-for-cryptohashes.patch
text/x-diff
Filename: 0001-Improve-error-reporting-for-cryptohashes.patch
Type: text/x-diff
Part: 0
Message:
Re: md5 issues Postgres14 on OL7
Patch
Format: format-patch
Series: patch 0001
Subject: Improve error reporting for cryptohashes
| File | + | − |
|---|---|---|
| contrib/uuid-ossp/uuid-ossp.c | 12 | 6 |
| src/backend/libpq/auth.c | 10 | 4 |
| src/backend/libpq/crypt.c | 12 | 8 |
| src/backend/replication/backup_manifest.c | 6 | 3 |
| src/backend/utils/adt/cryptohashfuncs.c | 16 | 9 |
| src/common/cryptohash.c | 56 | 1 |
| src/common/cryptohash_openssl.c | 68 | 0 |
| src/common/md5_common.c | 15 | 5 |
| src/include/common/cryptohash.h | 1 | 0 |
| src/include/common/md5.h | 5 | 3 |
| src/interfaces/libpq/fe-auth.c | 18 | 4 |
From 064ef97fd2a171485ff408550380515493ce0072 Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@paquier.xyz>
Date: Thu, 6 Jan 2022 17:13:55 +0900
Subject: [PATCH] Improve error reporting for cryptohashes
---
src/include/common/cryptohash.h | 1 +
src/include/common/md5.h | 8 ++-
src/backend/libpq/auth.c | 14 +++--
src/backend/libpq/crypt.c | 20 ++++---
src/backend/replication/backup_manifest.c | 9 ++-
src/backend/utils/adt/cryptohashfuncs.c | 25 ++++++---
src/common/cryptohash.c | 57 ++++++++++++++++++-
src/common/cryptohash_openssl.c | 68 +++++++++++++++++++++++
src/common/md5_common.c | 20 +++++--
src/interfaces/libpq/fe-auth.c | 22 ++++++--
contrib/uuid-ossp/uuid-ossp.c | 18 ++++--
11 files changed, 219 insertions(+), 43 deletions(-)
diff --git a/src/include/common/cryptohash.h b/src/include/common/cryptohash.h
index 541dc844c8..61d74e1195 100644
--- a/src/include/common/cryptohash.h
+++ b/src/include/common/cryptohash.h
@@ -34,5 +34,6 @@ extern int pg_cryptohash_init(pg_cryptohash_ctx *ctx);
extern int pg_cryptohash_update(pg_cryptohash_ctx *ctx, const uint8 *data, size_t len);
extern int pg_cryptohash_final(pg_cryptohash_ctx *ctx, uint8 *dest, size_t len);
extern void pg_cryptohash_free(pg_cryptohash_ctx *ctx);
+extern char *pg_cryptohash_error(pg_cryptohash_ctx *ctx);
#endif /* PG_CRYPTOHASH_H */
diff --git a/src/include/common/md5.h b/src/include/common/md5.h
index 62a31e6ed4..1db2855d95 100644
--- a/src/include/common/md5.h
+++ b/src/include/common/md5.h
@@ -26,9 +26,11 @@
#define MD5_PASSWD_LEN 35
/* Utilities common to all the MD5 implementations, as of md5_common.c */
-extern bool pg_md5_hash(const void *buff, size_t len, char *hexsum);
-extern bool pg_md5_binary(const void *buff, size_t len, void *outbuf);
+extern bool pg_md5_hash(const void *buff, size_t len, char *hexsum,
+ char **errstr);
+extern bool pg_md5_binary(const void *buff, size_t len, void *outbuf,
+ char **errstr);
extern bool pg_md5_encrypt(const char *passwd, const char *salt,
- size_t salt_len, char *buf);
+ size_t salt_len, char *buf, char **errstr);
#endif /* PG_MD5_H */
diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c
index 7bcf52523b..9f118ec546 100644
--- a/src/backend/libpq/auth.c
+++ b/src/backend/libpq/auth.c
@@ -3085,6 +3085,8 @@ PerformRadiusTransaction(const char *server, const char *secret, const char *por
md5trailer = packet->vector;
for (i = 0; i < encryptedpasswordlen; i += RADIUS_VECTOR_LENGTH)
{
+ char *errstr = NULL;
+
memcpy(cryptvector + strlen(secret), md5trailer, RADIUS_VECTOR_LENGTH);
/*
@@ -3093,10 +3095,12 @@ PerformRadiusTransaction(const char *server, const char *secret, const char *por
*/
md5trailer = encryptedpassword + i;
- if (!pg_md5_binary(cryptvector, strlen(secret) + RADIUS_VECTOR_LENGTH, encryptedpassword + i))
+ if (!pg_md5_binary(cryptvector, strlen(secret) + RADIUS_VECTOR_LENGTH,
+ encryptedpassword + i, &errstr))
{
ereport(LOG,
- (errmsg("could not perform MD5 encryption of password")));
+ (errmsg("could not perform MD5 encryption of password: %s",
+ errstr)));
pfree(cryptvector);
pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
return STATUS_ERROR;
@@ -3181,6 +3185,7 @@ PerformRadiusTransaction(const char *server, const char *secret, const char *por
struct timeval timeout;
struct timeval now;
int64 timeoutval;
+ char *errstr;
gettimeofday(&now, NULL);
timeoutval = (endtime.tv_sec * 1000000 + endtime.tv_usec) - (now.tv_sec * 1000000 + now.tv_usec);
@@ -3299,10 +3304,11 @@ PerformRadiusTransaction(const char *server, const char *secret, const char *por
if (!pg_md5_binary(cryptvector,
packetlength + strlen(secret),
- encryptedpassword))
+ encryptedpassword, &errstr))
{
ereport(LOG,
- (errmsg("could not perform MD5 encryption of received packet")));
+ (errmsg("could not perform MD5 encryption of received packet: %s",
+ errstr)));
pfree(cryptvector);
continue;
}
diff --git a/src/backend/libpq/crypt.c b/src/backend/libpq/crypt.c
index 3fcad991a7..396510e7a5 100644
--- a/src/backend/libpq/crypt.c
+++ b/src/backend/libpq/crypt.c
@@ -116,6 +116,7 @@ encrypt_password(PasswordType target_type, const char *role,
{
PasswordType guessed_type = get_password_type(password);
char *encrypted_password;
+ char *errstr = NULL;
if (guessed_type != PASSWORD_TYPE_PLAINTEXT)
{
@@ -132,8 +133,8 @@ encrypt_password(PasswordType target_type, const char *role,
encrypted_password = palloc(MD5_PASSWD_LEN + 1);
if (!pg_md5_encrypt(password, role, strlen(role),
- encrypted_password))
- elog(ERROR, "password encryption failed");
+ encrypted_password, &errstr))
+ elog(ERROR, "password encryption failed: %s", errstr);
return encrypted_password;
case PASSWORD_TYPE_SCRAM_SHA_256:
@@ -170,6 +171,7 @@ md5_crypt_verify(const char *role, const char *shadow_pass,
{
int retval;
char crypt_pwd[MD5_PASSWD_LEN + 1];
+ char *errstr = NULL;
Assert(md5_salt_len > 0);
@@ -185,13 +187,13 @@ md5_crypt_verify(const char *role, const char *shadow_pass,
* Compute the correct answer for the MD5 challenge.
*
* We do not bother setting logdetail for any pg_md5_encrypt failure
- * below: the only possible error is out-of-memory, which is unlikely, and
- * if it did happen adding a psprintf call would only make things worse.
+ * below: an out-of-memory, which is unlikely, is possible and if it
+ * did happen adding a psprintf call would only make things worse.
*/
/* stored password already encrypted, only do salt */
if (!pg_md5_encrypt(shadow_pass + strlen("md5"),
md5_salt, md5_salt_len,
- crypt_pwd))
+ crypt_pwd, &errstr))
{
return STATUS_ERROR;
}
@@ -224,6 +226,7 @@ plain_crypt_verify(const char *role, const char *shadow_pass,
char **logdetail)
{
char crypt_client_pass[MD5_PASSWD_LEN + 1];
+ char *errstr = NULL;
/*
* Client sent password in plaintext. If we have an MD5 hash stored, hash
@@ -251,12 +254,13 @@ plain_crypt_verify(const char *role, const char *shadow_pass,
if (!pg_md5_encrypt(client_pass,
role,
strlen(role),
- crypt_client_pass))
+ crypt_client_pass,
+ &errstr))
{
/*
* We do not bother setting logdetail for pg_md5_encrypt
- * failure: the only possible error is out-of-memory, which is
- * unlikely, and if it did happen adding a psprintf call would
+ * failure: out-of-memory, which is unlikely, is a possible
+ * outcome and if it did happen adding a psprintf call would
* only make things worse.
*/
return STATUS_ERROR;
diff --git a/src/backend/replication/backup_manifest.c b/src/backend/replication/backup_manifest.c
index 4fe11a3b5c..f29d66b719 100644
--- a/src/backend/replication/backup_manifest.c
+++ b/src/backend/replication/backup_manifest.c
@@ -68,7 +68,8 @@ InitializeBackupManifest(backup_manifest_info *manifest,
manifest->buffile = BufFileCreateTemp(false);
manifest->manifest_ctx = pg_cryptohash_create(PG_SHA256);
if (pg_cryptohash_init(manifest->manifest_ctx) < 0)
- elog(ERROR, "failed to initialize checksum of backup manifest");
+ elog(ERROR, "failed to initialize checksum of backup manifest: %s",
+ pg_cryptohash_error(manifest->manifest_ctx));
}
manifest->manifest_size = UINT64CONST(0);
@@ -334,7 +335,8 @@ SendBackupManifest(backup_manifest_info *manifest, bbsink *sink)
manifest->still_checksumming = false;
if (pg_cryptohash_final(manifest->manifest_ctx, checksumbuf,
sizeof(checksumbuf)) < 0)
- elog(ERROR, "failed to finalize checksum of backup manifest");
+ elog(ERROR, "failed to finalize checksum of backup manifest: %s",
+ pg_cryptohash_error(manifest->manifest_ctx));
AppendStringToManifest(manifest, "\"Manifest-Checksum\": \"");
hex_encode((char *) checksumbuf, sizeof checksumbuf, checksumstringbuf);
@@ -391,7 +393,8 @@ AppendStringToManifest(backup_manifest_info *manifest, char *s)
if (manifest->still_checksumming)
{
if (pg_cryptohash_update(manifest->manifest_ctx, (uint8 *) s, len) < 0)
- elog(ERROR, "failed to update checksum of backup manifest");
+ elog(ERROR, "failed to update checksum of backup manifest: %s",
+ pg_cryptohash_error(manifest->manifest_ctx));
}
BufFileWrite(manifest->buffile, s, len);
manifest->manifest_size += len;
diff --git a/src/backend/utils/adt/cryptohashfuncs.c b/src/backend/utils/adt/cryptohashfuncs.c
index 6a0f0258e6..a972a05fcf 100644
--- a/src/backend/utils/adt/cryptohashfuncs.c
+++ b/src/backend/utils/adt/cryptohashfuncs.c
@@ -35,15 +35,17 @@ md5_text(PG_FUNCTION_ARGS)
text *in_text = PG_GETARG_TEXT_PP(0);
size_t len;
char hexsum[MD5_HASH_LEN + 1];
+ char *errstr = NULL;
/* Calculate the length of the buffer using varlena metadata */
len = VARSIZE_ANY_EXHDR(in_text);
/* get the hash result */
- if (pg_md5_hash(VARDATA_ANY(in_text), len, hexsum) == false)
+ if (pg_md5_hash(VARDATA_ANY(in_text), len, hexsum, &errstr) == false)
ereport(ERROR,
- (errcode(ERRCODE_OUT_OF_MEMORY),
- errmsg("out of memory")));
+ (errcode(ERRCODE_INTERNAL_ERROR),
+ errmsg("could not compute %s hash: %s", "MD5",
+ errstr)));
/* convert to text and return it */
PG_RETURN_TEXT_P(cstring_to_text(hexsum));
@@ -58,12 +60,14 @@ md5_bytea(PG_FUNCTION_ARGS)
bytea *in = PG_GETARG_BYTEA_PP(0);
size_t len;
char hexsum[MD5_HASH_LEN + 1];
+ char *errstr = NULL;
len = VARSIZE_ANY_EXHDR(in);
- if (pg_md5_hash(VARDATA_ANY(in), len, hexsum) == false)
+ if (pg_md5_hash(VARDATA_ANY(in), len, hexsum, &errstr) == false)
ereport(ERROR,
- (errcode(ERRCODE_OUT_OF_MEMORY),
- errmsg("out of memory")));
+ (errcode(ERRCODE_INTERNAL_ERROR),
+ errmsg("could not compute %s hash: %s", "MD5",
+ errstr)));
PG_RETURN_TEXT_P(cstring_to_text(hexsum));
}
@@ -111,12 +115,15 @@ cryptohash_internal(pg_cryptohash_type type, bytea *input)
ctx = pg_cryptohash_create(type);
if (pg_cryptohash_init(ctx) < 0)
- elog(ERROR, "could not initialize %s context", typestr);
+ elog(ERROR, "could not initialize %s context: %s", typestr,
+ pg_cryptohash_error(ctx));
if (pg_cryptohash_update(ctx, data, len) < 0)
- elog(ERROR, "could not update %s context", typestr);
+ elog(ERROR, "could not update %s context: %s", typestr,
+ pg_cryptohash_error(ctx));
if (pg_cryptohash_final(ctx, (unsigned char *) VARDATA(result),
digest_len) < 0)
- elog(ERROR, "could not finalize %s context", typestr);
+ elog(ERROR, "could not finalize %s context: %s", typestr,
+ pg_cryptohash_error(ctx));
pg_cryptohash_free(ctx);
SET_VARSIZE(result, digest_len + VARHDRSZ);
diff --git a/src/common/cryptohash.c b/src/common/cryptohash.c
index 0dab74a094..1115365c85 100644
--- a/src/common/cryptohash.c
+++ b/src/common/cryptohash.c
@@ -40,10 +40,18 @@
#define FREE(ptr) free(ptr)
#endif
+/* Set of error states */
+typedef enum pg_cryptohash_errno
+{
+ PG_CRYPTOHASH_ERROR_NONE = 0,
+ PG_CRYPTOHASH_ERROR_DEST_LEN
+} pg_cryptohash_errno;
+
/* Internal pg_cryptohash_ctx structure */
struct pg_cryptohash_ctx
{
pg_cryptohash_type type;
+ pg_cryptohash_errno error;
union
{
@@ -76,9 +84,10 @@ pg_cryptohash_create(pg_cryptohash_type type)
ctx = ALLOC(sizeof(pg_cryptohash_ctx));
if (ctx == NULL)
return NULL;
+
memset(ctx, 0, sizeof(pg_cryptohash_ctx));
ctx->type = type;
-
+ ctx->error = PG_CRYPTOHASH_ERROR_NONE;
return ctx;
}
@@ -174,32 +183,50 @@ pg_cryptohash_final(pg_cryptohash_ctx *ctx, uint8 *dest, size_t len)
{
case PG_MD5:
if (len < MD5_DIGEST_LENGTH)
+ {
+ ctx->error = PG_CRYPTOHASH_ERROR_DEST_LEN;
return -1;
+ }
pg_md5_final(&ctx->data.md5, dest);
break;
case PG_SHA1:
if (len < SHA1_DIGEST_LENGTH)
+ {
+ ctx->error = PG_CRYPTOHASH_ERROR_DEST_LEN;
return -1;
+ }
pg_sha1_final(&ctx->data.sha1, dest);
break;
case PG_SHA224:
if (len < PG_SHA224_DIGEST_LENGTH)
+ {
+ ctx->error = PG_CRYPTOHASH_ERROR_DEST_LEN;
return -1;
+ }
pg_sha224_final(&ctx->data.sha224, dest);
break;
case PG_SHA256:
if (len < PG_SHA256_DIGEST_LENGTH)
+ {
+ ctx->error = PG_CRYPTOHASH_ERROR_DEST_LEN;
return -1;
+ }
pg_sha256_final(&ctx->data.sha256, dest);
break;
case PG_SHA384:
if (len < PG_SHA384_DIGEST_LENGTH)
+ {
+ ctx->error = PG_CRYPTOHASH_ERROR_DEST_LEN;
return -1;
+ }
pg_sha384_final(&ctx->data.sha384, dest);
break;
case PG_SHA512:
if (len < PG_SHA512_DIGEST_LENGTH)
+ {
+ ctx->error = PG_CRYPTOHASH_ERROR_DEST_LEN;
return -1;
+ }
pg_sha512_final(&ctx->data.sha512, dest);
break;
}
@@ -221,3 +248,31 @@ pg_cryptohash_free(pg_cryptohash_ctx *ctx)
explicit_bzero(ctx, sizeof(pg_cryptohash_ctx));
FREE(ctx);
}
+
+/*
+ * pg_cryptohash_error
+ *
+ * Returns a static string providing errors about an error that
+ * happened during a computation.
+ */
+char *
+pg_cryptohash_error(pg_cryptohash_ctx *ctx)
+{
+ /*
+ * This implementation would never fail because of an out-of-memory
+ * error, except when creating the context.
+ */
+ if (ctx == NULL)
+ return _("out of memory");
+
+ switch (ctx->error)
+ {
+ case PG_CRYPTOHASH_ERROR_NONE:
+ return _("success");
+ case PG_CRYPTOHASH_ERROR_DEST_LEN:
+ return _("destination buffer too small");
+ }
+
+ Assert(false);
+ return NULL;
+}
diff --git a/src/common/cryptohash_openssl.c b/src/common/cryptohash_openssl.c
index 643cc7aea2..12843809ca 100644
--- a/src/common/cryptohash_openssl.c
+++ b/src/common/cryptohash_openssl.c
@@ -46,6 +46,14 @@
#define FREE(ptr) free(ptr)
#endif
+/* Set of error states */
+typedef enum pg_cryptohash_errno
+{
+ PG_CRYPTOHASH_ERROR_NONE = 0,
+ PG_CRYPTOHASH_ERROR_DEST_LEN,
+ PG_CRYPTOHASH_ERROR_OPENSSL
+} pg_cryptohash_errno;
+
/*
* Internal pg_cryptohash_ctx structure.
*
@@ -55,6 +63,7 @@
struct pg_cryptohash_ctx
{
pg_cryptohash_type type;
+ pg_cryptohash_errno error;
EVP_MD_CTX *evpctx;
@@ -88,6 +97,7 @@ pg_cryptohash_create(pg_cryptohash_type type)
return NULL;
memset(ctx, 0, sizeof(pg_cryptohash_ctx));
ctx->type = type;
+ ctx->error = PG_CRYPTOHASH_ERROR_NONE;
/*
* Initialization takes care of assigning the correct type for OpenSSL.
@@ -153,7 +163,10 @@ pg_cryptohash_init(pg_cryptohash_ctx *ctx)
/* OpenSSL internals return 1 on success, 0 on failure */
if (status <= 0)
+ {
+ ctx->error = PG_CRYPTOHASH_ERROR_OPENSSL;
return -1;
+ }
return 0;
}
@@ -174,7 +187,10 @@ pg_cryptohash_update(pg_cryptohash_ctx *ctx, const uint8 *data, size_t len)
/* OpenSSL internals return 1 on success, 0 on failure */
if (status <= 0)
+ {
+ ctx->error = PG_CRYPTOHASH_ERROR_OPENSSL;
return -1;
+ }
return 0;
}
@@ -195,27 +211,45 @@ pg_cryptohash_final(pg_cryptohash_ctx *ctx, uint8 *dest, size_t len)
{
case PG_MD5:
if (len < MD5_DIGEST_LENGTH)
+ {
+ ctx->error = PG_CRYPTOHASH_ERROR_DEST_LEN;
return -1;
+ }
break;
case PG_SHA1:
if (len < SHA1_DIGEST_LENGTH)
+ {
+ ctx->error = PG_CRYPTOHASH_ERROR_DEST_LEN;
return -1;
+ }
break;
case PG_SHA224:
if (len < PG_SHA224_DIGEST_LENGTH)
+ {
+ ctx->error = PG_CRYPTOHASH_ERROR_DEST_LEN;
return -1;
+ }
break;
case PG_SHA256:
if (len < PG_SHA256_DIGEST_LENGTH)
+ {
+ ctx->error = PG_CRYPTOHASH_ERROR_DEST_LEN;
return -1;
+ }
break;
case PG_SHA384:
if (len < PG_SHA384_DIGEST_LENGTH)
+ {
+ ctx->error = PG_CRYPTOHASH_ERROR_DEST_LEN;
return -1;
+ }
break;
case PG_SHA512:
if (len < PG_SHA512_DIGEST_LENGTH)
+ {
+ ctx->error = PG_CRYPTOHASH_ERROR_DEST_LEN;
return -1;
+ }
break;
}
@@ -223,7 +257,10 @@ pg_cryptohash_final(pg_cryptohash_ctx *ctx, uint8 *dest, size_t len)
/* OpenSSL internals return 1 on success, 0 on failure */
if (status <= 0)
+ {
+ ctx->error = PG_CRYPTOHASH_ERROR_OPENSSL;
return -1;
+ }
return 0;
}
@@ -248,3 +285,34 @@ pg_cryptohash_free(pg_cryptohash_ctx *ctx)
explicit_bzero(ctx, sizeof(pg_cryptohash_ctx));
FREE(ctx);
}
+
+/*
+ * pg_cryptohash_error
+ *
+ * Returns a static string providing errors about an error that
+ * happened during a computation.
+ */
+char *
+pg_cryptohash_error(pg_cryptohash_ctx *ctx)
+{
+ /*
+ * This implementation would never fail because of an out-of-memory
+ * error, except when creating the context.
+ */
+ if (ctx == NULL)
+ return _("out of memory");
+
+ switch (ctx->error)
+ {
+ case PG_CRYPTOHASH_ERROR_NONE:
+ return _("success");
+ case PG_CRYPTOHASH_ERROR_DEST_LEN:
+ return _("destination buffer too small");
+ case PG_CRYPTOHASH_ERROR_OPENSSL:
+ return _("OpenSSL failure");
+ }
+
+ /* assume that the default is out-of-memory, anyway */
+ Assert(false);
+ return NULL;
+}
diff --git a/src/common/md5_common.c b/src/common/md5_common.c
index 2114890eff..18041a5552 100644
--- a/src/common/md5_common.c
+++ b/src/common/md5_common.c
@@ -67,7 +67,7 @@ bytesToHex(uint8 b[16], char *s)
*/
bool
-pg_md5_hash(const void *buff, size_t len, char *hexsum)
+pg_md5_hash(const void *buff, size_t len, char *hexsum, char **errstr)
{
uint8 sum[MD5_DIGEST_LENGTH];
pg_cryptohash_ctx *ctx;
@@ -80,6 +80,7 @@ pg_md5_hash(const void *buff, size_t len, char *hexsum)
pg_cryptohash_update(ctx, buff, len) < 0 ||
pg_cryptohash_final(ctx, sum, sizeof(sum)) < 0)
{
+ *errstr = pg_cryptohash_error(ctx);
pg_cryptohash_free(ctx);
return false;
}
@@ -90,18 +91,23 @@ pg_md5_hash(const void *buff, size_t len, char *hexsum)
}
bool
-pg_md5_binary(const void *buff, size_t len, void *outbuf)
+pg_md5_binary(const void *buff, size_t len, void *outbuf, char **errstr)
{
pg_cryptohash_ctx *ctx;
+ *errstr = NULL;
ctx = pg_cryptohash_create(PG_MD5);
if (ctx == NULL)
+ {
+ *errstr = pg_cryptohash_error(NULL); /* returns OOM */
return false;
+ }
if (pg_cryptohash_init(ctx) < 0 ||
pg_cryptohash_update(ctx, buff, len) < 0 ||
pg_cryptohash_final(ctx, outbuf, MD5_DIGEST_LENGTH) < 0)
{
+ *errstr = pg_cryptohash_error(ctx);
pg_cryptohash_free(ctx);
return false;
}
@@ -118,11 +124,12 @@ pg_md5_binary(const void *buff, size_t len, void *outbuf)
* Output format is "md5" followed by a 32-hex-digit MD5 checksum.
* Hence, the output buffer "buf" must be at least 36 bytes long.
*
- * Returns true if okay, false on error (out of memory).
+ * Returns true if okay, false on error with *errstr providing some
+ * error context.
*/
bool
pg_md5_encrypt(const char *passwd, const char *salt, size_t salt_len,
- char *buf)
+ char *buf, char **errstr)
{
size_t passwd_len = strlen(passwd);
@@ -131,7 +138,10 @@ pg_md5_encrypt(const char *passwd, const char *salt, size_t salt_len,
bool ret;
if (!crypt_buf)
+ {
+ *errstr = _("out of memory");
return false;
+ }
/*
* Place salt at the end because it may be known by users trying to crack
@@ -141,7 +151,7 @@ pg_md5_encrypt(const char *passwd, const char *salt, size_t salt_len,
memcpy(crypt_buf + passwd_len, salt, salt_len);
strcpy(buf, "md5");
- ret = pg_md5_hash(crypt_buf, passwd_len + salt_len, buf + 3);
+ ret = pg_md5_hash(crypt_buf, passwd_len + salt_len, buf + 3, errstr);
free(crypt_buf);
diff --git a/src/interfaces/libpq/fe-auth.c b/src/interfaces/libpq/fe-auth.c
index 3421ed4685..45c28bfb17 100644
--- a/src/interfaces/libpq/fe-auth.c
+++ b/src/interfaces/libpq/fe-auth.c
@@ -790,6 +790,7 @@ pg_password_sendauth(PGconn *conn, const char *password, AuthRequest areq)
case AUTH_REQ_MD5:
{
char *crypt_pwd2;
+ char *errstr;
/* Allocate enough space for two MD5 hashes */
crypt_pwd = malloc(2 * (MD5_PASSWD_LEN + 1));
@@ -802,14 +803,21 @@ pg_password_sendauth(PGconn *conn, const char *password, AuthRequest areq)
crypt_pwd2 = crypt_pwd + MD5_PASSWD_LEN + 1;
if (!pg_md5_encrypt(password, conn->pguser,
- strlen(conn->pguser), crypt_pwd2))
+ strlen(conn->pguser), crypt_pwd2,
+ &errstr))
{
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("could not encrypt password: %s\n"),
+ errstr);
free(crypt_pwd);
return STATUS_ERROR;
}
if (!pg_md5_encrypt(crypt_pwd2 + strlen("md5"), md5Salt,
- 4, crypt_pwd))
+ 4, crypt_pwd, &errstr))
{
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("could not encrypt password: %s\n"),
+ errstr);
free(crypt_pwd);
return STATUS_ERROR;
}
@@ -1175,12 +1183,13 @@ char *
PQencryptPassword(const char *passwd, const char *user)
{
char *crypt_pwd;
+ char *errstr = NULL;
crypt_pwd = malloc(MD5_PASSWD_LEN + 1);
if (!crypt_pwd)
return NULL;
- if (!pg_md5_encrypt(passwd, user, strlen(user), crypt_pwd))
+ if (!pg_md5_encrypt(passwd, user, strlen(user), crypt_pwd, &errstr))
{
free(crypt_pwd);
return NULL;
@@ -1287,8 +1296,13 @@ PQencryptPasswordConn(PGconn *conn, const char *passwd, const char *user,
crypt_pwd = malloc(MD5_PASSWD_LEN + 1);
if (crypt_pwd)
{
- if (!pg_md5_encrypt(passwd, user, strlen(user), crypt_pwd))
+ char *errstr = NULL;
+
+ if (!pg_md5_encrypt(passwd, user, strlen(user), crypt_pwd, &errstr))
{
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("could not encrypt password: %s\n"),
+ errstr);
free(crypt_pwd);
crypt_pwd = NULL;
}
diff --git a/contrib/uuid-ossp/uuid-ossp.c b/contrib/uuid-ossp/uuid-ossp.c
index f9335f2863..f52f007a08 100644
--- a/contrib/uuid-ossp/uuid-ossp.c
+++ b/contrib/uuid-ossp/uuid-ossp.c
@@ -319,14 +319,17 @@ uuid_generate_internal(int v, unsigned char *ns, const char *ptr, int len)
pg_cryptohash_ctx *ctx = pg_cryptohash_create(PG_MD5);
if (pg_cryptohash_init(ctx) < 0)
- elog(ERROR, "could not initialize %s context", "MD5");
+ elog(ERROR, "could not initialize %s context: %s", "MD5",
+ pg_cryptohash_error(ctx));
if (pg_cryptohash_update(ctx, ns, sizeof(uu)) < 0 ||
pg_cryptohash_update(ctx, (unsigned char *) ptr, len) < 0)
- elog(ERROR, "could not update %s context", "MD5");
+ elog(ERROR, "could not update %s context: %s", "MD5",
+ pg_cryptohash_error(ctx));
/* we assume sizeof MD5 result is 16, same as UUID size */
if (pg_cryptohash_final(ctx, (unsigned char *) &uu,
sizeof(uu)) < 0)
- elog(ERROR, "could not finalize %s context", "MD5");
+ elog(ERROR, "could not finalize %s context: %s", "MD5",
+ pg_cryptohash_error(ctx));
pg_cryptohash_free(ctx);
}
else
@@ -335,12 +338,15 @@ uuid_generate_internal(int v, unsigned char *ns, const char *ptr, int len)
unsigned char sha1result[SHA1_DIGEST_LENGTH];
if (pg_cryptohash_init(ctx) < 0)
- elog(ERROR, "could not initialize %s context", "SHA1");
+ elog(ERROR, "could not initialize %s context: %s", "SHA1",
+ pg_cryptohash_error(ctx));
if (pg_cryptohash_update(ctx, ns, sizeof(uu)) < 0 ||
pg_cryptohash_update(ctx, (unsigned char *) ptr, len) < 0)
- elog(ERROR, "could not update %s context", "SHA1");
+ elog(ERROR, "could not update %s context: %s", "SHA1",
+ pg_cryptohash_error(ctx));
if (pg_cryptohash_final(ctx, sha1result, sizeof(sha1result)) < 0)
- elog(ERROR, "could not finalize %s context", "SHA1");
+ elog(ERROR, "could not finalize %s context: %s", "SHA1",
+ pg_cryptohash_error(ctx));
pg_cryptohash_free(ctx);
memcpy(&uu, sha1result, sizeof(uu));
--
2.34.1