mirror of
https://github.com/postgres/postgres.git
synced 2025-09-02 04:21:28 +03:00
Revert error handling improvements for cryptohashes
This reverts commitsab27df2
,af8d530
and3a0cced
, that introduced pg_cryptohash_error(). In order to make the core code able to pass down the new error types that this introduced, some of the MD5-related routines had to be reworked, causing an ABI breakage, but we found that some external extensions rely on them. Maintaining compatibility outweights the error report benefits, so just revert the change in v14. Reported-by: Laurenz Albe Discussion: https://postgr.es/m/9f0c0a96d28cf14fc87296bbe67061c14eb53ae8.camel@cybertec.at
This commit is contained in:
@@ -40,18 +40,10 @@
|
||||
#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
|
||||
{
|
||||
@@ -84,10 +76,9 @@ 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;
|
||||
}
|
||||
|
||||
@@ -183,50 +174,32 @@ 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;
|
||||
}
|
||||
@@ -248,31 +221,3 @@ pg_cryptohash_free(pg_cryptohash_ctx *ctx)
|
||||
explicit_bzero(ctx, sizeof(pg_cryptohash_ctx));
|
||||
FREE(ctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* pg_cryptohash_error
|
||||
*
|
||||
* Returns a static string providing details about an error that
|
||||
* happened during a computation.
|
||||
*/
|
||||
const 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 _("success");
|
||||
}
|
||||
|
@@ -21,7 +21,6 @@
|
||||
#include "postgres_fe.h"
|
||||
#endif
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#include "common/cryptohash.h"
|
||||
@@ -47,14 +46,6 @@
|
||||
#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.
|
||||
*
|
||||
@@ -64,8 +55,6 @@ typedef enum pg_cryptohash_errno
|
||||
struct pg_cryptohash_ctx
|
||||
{
|
||||
pg_cryptohash_type type;
|
||||
pg_cryptohash_errno error;
|
||||
const char *errreason;
|
||||
|
||||
EVP_MD_CTX *evpctx;
|
||||
|
||||
@@ -74,19 +63,6 @@ struct pg_cryptohash_ctx
|
||||
#endif
|
||||
};
|
||||
|
||||
static const char *
|
||||
SSLerrmessage(unsigned long ecode)
|
||||
{
|
||||
if (ecode == 0)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* This may return NULL, but we would fall back to a default error path if
|
||||
* that were the case.
|
||||
*/
|
||||
return ERR_reason_error_string(ecode);
|
||||
}
|
||||
|
||||
/*
|
||||
* pg_cryptohash_create
|
||||
*
|
||||
@@ -112,8 +88,6 @@ 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;
|
||||
ctx->errreason = NULL;
|
||||
|
||||
/*
|
||||
* Initialization takes care of assigning the correct type for OpenSSL.
|
||||
@@ -179,11 +153,7 @@ pg_cryptohash_init(pg_cryptohash_ctx *ctx)
|
||||
|
||||
/* OpenSSL internals return 1 on success, 0 on failure */
|
||||
if (status <= 0)
|
||||
{
|
||||
ctx->errreason = SSLerrmessage(ERR_get_error());
|
||||
ctx->error = PG_CRYPTOHASH_ERROR_OPENSSL;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -204,11 +174,7 @@ 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->errreason = SSLerrmessage(ERR_get_error());
|
||||
ctx->error = PG_CRYPTOHASH_ERROR_OPENSSL;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -229,45 +195,27 @@ 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;
|
||||
}
|
||||
|
||||
@@ -275,11 +223,7 @@ 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->errreason = SSLerrmessage(ERR_get_error());
|
||||
ctx->error = PG_CRYPTOHASH_ERROR_OPENSSL;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -304,40 +248,3 @@ pg_cryptohash_free(pg_cryptohash_ctx *ctx)
|
||||
explicit_bzero(ctx, sizeof(pg_cryptohash_ctx));
|
||||
FREE(ctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* pg_cryptohash_error
|
||||
*
|
||||
* Returns a static string providing details about an error that
|
||||
* happened during a computation.
|
||||
*/
|
||||
const 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");
|
||||
|
||||
/*
|
||||
* If a reason is provided, rely on it, else fallback to any error code
|
||||
* set.
|
||||
*/
|
||||
if (ctx->errreason)
|
||||
return ctx->errreason;
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
Assert(false); /* cannot be reached */
|
||||
return _("success");
|
||||
}
|
||||
|
@@ -67,7 +67,7 @@ bytesToHex(uint8 b[16], char *s)
|
||||
*/
|
||||
|
||||
bool
|
||||
pg_md5_hash(const void *buff, size_t len, char *hexsum, const char **errstr)
|
||||
pg_md5_hash(const void *buff, size_t len, char *hexsum)
|
||||
{
|
||||
uint8 sum[MD5_DIGEST_LENGTH];
|
||||
pg_cryptohash_ctx *ctx;
|
||||
@@ -80,7 +80,6 @@ pg_md5_hash(const void *buff, size_t len, char *hexsum, const char **errstr)
|
||||
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;
|
||||
}
|
||||
@@ -91,23 +90,18 @@ pg_md5_hash(const void *buff, size_t len, char *hexsum, const char **errstr)
|
||||
}
|
||||
|
||||
bool
|
||||
pg_md5_binary(const void *buff, size_t len, void *outbuf, const char **errstr)
|
||||
pg_md5_binary(const void *buff, size_t len, void *outbuf)
|
||||
{
|
||||
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;
|
||||
}
|
||||
@@ -124,12 +118,11 @@ pg_md5_binary(const void *buff, size_t len, void *outbuf, const char **errstr)
|
||||
* 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 with *errstr providing some
|
||||
* error context.
|
||||
* Returns true if okay, false on error (out of memory).
|
||||
*/
|
||||
bool
|
||||
pg_md5_encrypt(const char *passwd, const char *salt, size_t salt_len,
|
||||
char *buf, const char **errstr)
|
||||
char *buf)
|
||||
{
|
||||
size_t passwd_len = strlen(passwd);
|
||||
|
||||
@@ -138,10 +131,7 @@ 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
|
||||
@@ -151,7 +141,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, errstr);
|
||||
ret = pg_md5_hash(crypt_buf, passwd_len + salt_len, buf + 3);
|
||||
|
||||
free(crypt_buf);
|
||||
|
||||
|
Reference in New Issue
Block a user