commit f1394c40f47d552f714821dc0e1281cb89c3450c
parent 52fd858d5a8607f8044fb5977c8a2e0358284e30
Author: Andrej Kacian <ticho@claws-mail.org>
Date: Thu, 6 Sep 2018 22:11:05 +0200
Handle corrupted decrypted passwords gracefully.
Check whether the decrypted password is a valid UTF-8
string, and return an empty string if not, instead of
returning garbage, probably not NULL-terminated data,
and causing problems down the road.
Diffstat:
1 file changed, 24 insertions(+), 1 deletion(-)
diff --git a/src/password.c b/src/password.c
@@ -418,6 +418,7 @@ gchar *password_decrypt_gnutls(const gchar *password,
unsigned char *buf;
guint rounds;
size_t commapos;
+ gboolean valid_utf8;
g_return_val_if_fail(password != NULL, NULL);
g_return_val_if_fail(decryption_passphrase != NULL, NULL);
@@ -522,7 +523,29 @@ gchar *password_decrypt_gnutls(const gchar *password,
g_free(iv.data);
/* 'buf+blocklen' should now be pointing to the plaintext
- * password string. The first block contains random data from the IV. */
+ * password string.
+ * (The first block contains random data from the IV.)
+ *
+ * At this point, it should be a valid UTF-8 string. Let's make sure. */
+
+ /* First, let's assume there's just garbage and play it safe
+ * by looking for a first NULL byte within the decrypted range.
+ * (We could really use g_strchr_len() here instead, but Glib
+ * doesn't have that.) */
+ if (!g_strstr_len(buf + blocklen, len - blocklen, "\0")) {
+ debug_print("Could not find a NULL byte in the decrypted password.\n");
+ valid_utf8 = FALSE;
+ } else {
+ /* There is a NULL byte, we can rely on strlen() returning
+ * a sane value, so we don't read past the end of the allocated
+ * buffer. */
+ valid_utf8 = g_utf8_validate(buf + blocklen, strlen(buf + blocklen), NULL);
+ }
+
+ if (!valid_utf8)
+ debug_print("Decrypted password is not a valid UTF-8 string!\n");
+ cm_return_val_if_fail(valid_utf8, NULL);
+
tmp = g_strndup(buf + blocklen, strlen(buf + blocklen));
memset(buf, 0, len);
g_free(buf);