aboutsummaryrefslogtreecommitdiff
path: root/src/common/scram-common.c
diff options
context:
space:
mode:
authorMichael Paquier <michael@paquier.xyz>2019-07-04 16:08:09 +0900
committerMichael Paquier <michael@paquier.xyz>2019-07-04 16:08:09 +0900
commitcfc40d384ae51ea2886d599d2008ae57b529e6ea (patch)
tree725bf1bb55c99ead091f16ff9ccfc542ef7a2855 /src/common/scram-common.c
parentd5ab9a891cb590aad4278026b2edda685f2524a2 (diff)
downloadpostgresql-cfc40d384ae51ea2886d599d2008ae57b529e6ea.tar.gz
postgresql-cfc40d384ae51ea2886d599d2008ae57b529e6ea.zip
Introduce safer encoding and decoding routines for base64.c
This is a follow-up refactoring after 09ec55b and b674211, which has proved that the encoding and decoding routines used by SCRAM have a poor interface when it comes to check after buffer overflows. This adds an extra argument in the shape of the length of the result buffer for each routine, which is used for overflow checks when encoding or decoding an input string. The original idea comes from Tom Lane. As a result of that, the encoding routine can now fail, so all its callers are adjusted to generate proper error messages in case of problems. On failure, the result buffer gets zeroed. Author: Michael Paquier Reviewed-by: Daniel Gustafsson Discussion: https://postgr.es/m/20190623132535.GB1628@paquier.xyz
Diffstat (limited to 'src/common/scram-common.c')
-rw-r--r--src/common/scram-common.c59
1 files changed, 53 insertions, 6 deletions
diff --git a/src/common/scram-common.c b/src/common/scram-common.c
index c30dfc97dca..dff9723e67f 100644
--- a/src/common/scram-common.c
+++ b/src/common/scram-common.c
@@ -198,6 +198,10 @@ scram_build_verifier(const char *salt, int saltlen, int iterations,
char *result;
char *p;
int maxlen;
+ int encoded_salt_len;
+ int encoded_stored_len;
+ int encoded_server_len;
+ int encoded_result;
if (iterations <= 0)
iterations = SCRAM_DEFAULT_ITERATIONS;
@@ -215,11 +219,15 @@ scram_build_verifier(const char *salt, int saltlen, int iterations,
* SCRAM-SHA-256$<iteration count>:<salt>$<StoredKey>:<ServerKey>
*----------
*/
+ encoded_salt_len = pg_b64_enc_len(saltlen);
+ encoded_stored_len = pg_b64_enc_len(SCRAM_KEY_LEN);
+ encoded_server_len = pg_b64_enc_len(SCRAM_KEY_LEN);
+
maxlen = strlen("SCRAM-SHA-256") + 1
+ 10 + 1 /* iteration count */
- + pg_b64_enc_len(saltlen) + 1 /* Base64-encoded salt */
- + pg_b64_enc_len(SCRAM_KEY_LEN) + 1 /* Base64-encoded StoredKey */
- + pg_b64_enc_len(SCRAM_KEY_LEN) + 1; /* Base64-encoded ServerKey */
+ + encoded_salt_len + 1 /* Base64-encoded salt */
+ + encoded_stored_len + 1 /* Base64-encoded StoredKey */
+ + encoded_server_len + 1; /* Base64-encoded ServerKey */
#ifdef FRONTEND
result = malloc(maxlen);
@@ -231,11 +239,50 @@ scram_build_verifier(const char *salt, int saltlen, int iterations,
p = result + sprintf(result, "SCRAM-SHA-256$%d:", iterations);
- p += pg_b64_encode(salt, saltlen, p);
+ /* salt */
+ encoded_result = pg_b64_encode(salt, saltlen, p, encoded_salt_len);
+ if (encoded_result < 0)
+ {
+#ifdef FRONTEND
+ free(result);
+ return NULL;
+#else
+ elog(ERROR, "could not encode salt");
+#endif
+ }
+ p += encoded_result;
*(p++) = '$';
- p += pg_b64_encode((char *) stored_key, SCRAM_KEY_LEN, p);
+
+ /* stored key */
+ encoded_result = pg_b64_encode((char *) stored_key, SCRAM_KEY_LEN, p,
+ encoded_stored_len);
+ if (encoded_result < 0)
+ {
+#ifdef FRONTEND
+ free(result);
+ return NULL;
+#else
+ elog(ERROR, "could not encode stored key");
+#endif
+ }
+
+ p += encoded_result;
*(p++) = ':';
- p += pg_b64_encode((char *) server_key, SCRAM_KEY_LEN, p);
+
+ /* server key */
+ encoded_result = pg_b64_encode((char *) server_key, SCRAM_KEY_LEN, p,
+ encoded_server_len);
+ if (encoded_result < 0)
+ {
+#ifdef FRONTEND
+ free(result);
+ return NULL;
+#else
+ elog(ERROR, "could not encode server key");
+#endif
+ }
+
+ p += encoded_result;
*(p++) = '\0';
Assert(p - result <= maxlen);