Follow-up fixes for SHA-2 patch (commit 749a9e20c).
authorTom Lane <[email protected]>
Mon, 7 Apr 2025 18:14:28 +0000 (14:14 -0400)
committerTom Lane <[email protected]>
Mon, 7 Apr 2025 18:14:28 +0000 (14:14 -0400)
This changes the check for valid characters in the salt string to
only allow plain ASCII letters and digits.  The previous coding was
locale-dependent which doesn't really seem like a great idea here;
moreover it could not work correctly in multibyte encodings.

This fixes a careless pointer-use-after-pfree, too.

Reported-by: Tom Lane <[email protected]>
Reported-by: Andres Freund <[email protected]>
Author: Bernd Helmle <[email protected]>
Discussion: https://postgr.es/m/6fab35422df6b6b9727fdcc243c5fa1c667dd3b5[email protected]

contrib/pgcrypto/crypt-sha.c

index 7e9440ca78439afb963ff4e61175deaed0210d25..7ec21771a83b7a462384e67fa7f3fa4347ab43dd 100644 (file)
@@ -46,6 +46,7 @@
 #include "postgres.h"
 
 #include "common/string.h"
+#include "mb/pg_wchar.h"
 #include "miscadmin.h"
 
 #include "px-crypt.h"
@@ -58,7 +59,7 @@ typedef enum
    PGCRYPTO_SHA_UNKOWN
 } PGCRYPTO_SHA_t;
 
-static unsigned char _crypt_itoa64[64 + 1] =
+static const char _crypt_itoa64[64 + 1] =
 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
 
 /*
@@ -321,10 +322,13 @@ px_crypt_shacrypt(const char *pw, const char *salt, char *passwd, unsigned dstle
 
        if (*ep != '$')
        {
-           if (isalpha(*ep) || isdigit(*ep) || (*ep == '.') || (*ep == '/'))
+           if (strchr(_crypt_itoa64, *ep) != NULL)
                appendStringInfoCharMacro(decoded_salt, *ep);
            else
-               elog(ERROR, "invalid character in salt string: \"%c\"", *ep);
+               ereport(ERROR,
+                       errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                       errmsg("invalid character in salt string: \"%.*s\"",
+                              pg_mblen(ep), ep));
        }
        else
        {
@@ -602,8 +606,6 @@ px_crypt_shacrypt(const char *pw, const char *salt, char *passwd, unsigned dstle
            elog(ERROR, "unsupported digest length");
    }
 
-   *cp = '\0';
-
    /*
     * Copy over result to specified buffer.
     *