Made the gnutls password encryption work on Win32.
[claws.git] / src / password.c
index 69d8c01..7e37e28 100644 (file)
 #include <glib.h>
 #include <glib/gi18n.h>
 
 #include <glib.h>
 #include <glib/gi18n.h>
 
-#ifdef G_OS_UNIX
+#if defined G_OS_UNIX
 #include <fcntl.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <unistd.h>
+#elif defined G_OS_WIN32
+#include <windows.h>
+#include <wincrypt.h>
 #endif
 
 #include "common/passcrypt.h"
 #endif
 
 #include "common/passcrypt.h"
+#include "common/plugin.h"
 #include "common/utils.h"
 #include "account.h"
 #include "alertpanel.h"
 #include "common/utils.h"
 #include "account.h"
 #include "alertpanel.h"
@@ -117,6 +121,11 @@ const gboolean master_password_is_correct(const gchar *input)
        return FALSE;
 }
 
        return FALSE;
 }
 
+gboolean master_password_is_entered()
+{
+       return (_master_password == NULL) ? FALSE : TRUE;
+}
+
 void master_password_forget()
 {
        /* If master password is currently in memory (entered by user),
 void master_password_forget()
 {
        /* If master password is currently in memory (entered by user),
@@ -205,6 +214,11 @@ void master_password_change(const gchar *newp)
                }
        }
 
                }
        }
 
+       /* Now reencrypt all plugins passwords fields 
+        * FIXME: Unloaded plugins won't be able to update their stored passwords
+        */
+       plugins_master_password_change(oldp, newp);
+
        master_password_forget();
 }
 #endif
        master_password_forget();
 }
 #endif
@@ -260,8 +274,10 @@ gchar *password_encrypt_gnutls(const gchar *password,
        gnutls_datum_t key, iv;
        int ivlen, keylen, digestlen, blocklen, ret, i;
        unsigned char hashbuf[BUFSIZE], *buf, *encbuf, *base, *output;
        gnutls_datum_t key, iv;
        int ivlen, keylen, digestlen, blocklen, ret, i;
        unsigned char hashbuf[BUFSIZE], *buf, *encbuf, *base, *output;
-#ifdef G_OS_UNIX
+#if defined G_OS_UNIX
        int rnd;
        int rnd;
+#elif defined G_OS_WIN32
+       HCRYPTPROV rnd;
 #endif
 
        g_return_val_if_fail(password != NULL, NULL);
 #endif
 
        g_return_val_if_fail(password != NULL, NULL);
@@ -288,38 +304,48 @@ gchar *password_encrypt_gnutls(const gchar *password,
        memcpy(key.data, &hashbuf, keylen);
        key.size = keylen;
 
        memcpy(key.data, &hashbuf, keylen);
        key.size = keylen;
 
-#ifdef G_OS_UNIX
        /* Prepare our source of random data. */
        /* Prepare our source of random data. */
+#if defined G_OS_UNIX
        rnd = open("/dev/urandom", O_RDONLY);
        if (rnd == -1) {
                perror("fopen on /dev/urandom");
        rnd = open("/dev/urandom", O_RDONLY);
        if (rnd == -1) {
                perror("fopen on /dev/urandom");
+#elif defined G_OS_WIN32
+       if (!CryptAcquireContext(&rnd, NULL, NULL, PROV_RSA_FULL, 0) &&
+                       !CryptAcquireContext(&rnd, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) {
+               debug_print("Could not acquire a CSP handle.\n");
+#endif
                g_free(key.data);
                g_free(iv.data);
                return NULL;
        }
                g_free(key.data);
                g_free(iv.data);
                return NULL;
        }
-#endif
 
        /* Prepare random IV for cipher */
        iv.data = malloc(ivlen);
        iv.size = ivlen;
 
        /* Prepare random IV for cipher */
        iv.data = malloc(ivlen);
        iv.size = ivlen;
-#ifdef G_OS_UNIX
+#if defined G_OS_UNIX
        ret = read(rnd, iv.data, ivlen);
        if (ret != ivlen) {
                perror("read into iv");
        ret = read(rnd, iv.data, ivlen);
        if (ret != ivlen) {
                perror("read into iv");
+               close(rnd);
+#elif defined G_OS_WIN32
+       if (!CryptGenRandom(rnd, ivlen, iv.data)) {
+               debug_print("Could not read random data for IV\n");
+               CryptReleaseContext(rnd, 0);
+#endif
                g_free(key.data);
                g_free(iv.data);
                g_free(key.data);
                g_free(iv.data);
-               close(rnd);
                return NULL;
        }
                return NULL;
        }
-#endif
 
        /* Initialize the encryption */
        ret = gnutls_cipher_init(&handle, algo, &key, &iv);
        if (ret < 0) {
                g_free(key.data);
                g_free(iv.data);
 
        /* Initialize the encryption */
        ret = gnutls_cipher_init(&handle, algo, &key, &iv);
        if (ret < 0) {
                g_free(key.data);
                g_free(iv.data);
-#ifdef G_OS_UNIX
+#if defined G_OS_UNIX
                close(rnd);
                close(rnd);
+#elif defined G_OS_WIN32
+               CryptReleaseContext(rnd, 0);
 #endif
                return NULL;
        }
 #endif
                return NULL;
        }
@@ -328,20 +354,28 @@ gchar *password_encrypt_gnutls(const gchar *password,
         * rest with zero bytes. */
        buf = malloc(BUFSIZE + blocklen);
        memset(buf, 0, BUFSIZE);
         * rest with zero bytes. */
        buf = malloc(BUFSIZE + blocklen);
        memset(buf, 0, BUFSIZE);
-#ifdef G_OS_UNIX
+#if defined G_OS_UNIX
        ret = read(rnd, buf, blocklen);
        if (ret != blocklen) {
                perror("read into buffer");
        ret = read(rnd, buf, blocklen);
        if (ret != blocklen) {
                perror("read into buffer");
+               close(rnd);
+#elif defined G_OS_WIN32
+       if (!CryptGenRandom(rnd, blocklen, buf)) {
+               debug_print("Could not read random data for IV\n");
+               CryptReleaseContext(rnd, 0);
+#endif
                g_free(buf);
                g_free(key.data);
                g_free(iv.data);
                g_free(buf);
                g_free(key.data);
                g_free(iv.data);
-               close(rnd);
                gnutls_cipher_deinit(handle);
                return NULL;
        }
 
        /* We don't need any more random data. */
                gnutls_cipher_deinit(handle);
                return NULL;
        }
 
        /* We don't need any more random data. */
+#if defined G_OS_UNIX
        close(rnd);
        close(rnd);
+#elif defined G_OS_WIN32
+       CryptReleaseContext(rnd, 0);
 #endif
 
        memcpy(buf + blocklen, password, strlen(password));
 #endif
 
        memcpy(buf + blocklen, password, strlen(password));
@@ -387,8 +421,10 @@ gchar *password_decrypt_gnutls(const gchar *password,
        int ivlen, keylen, digestlen, blocklen, ret, i;
        gsize len;
        unsigned char hashbuf[BUFSIZE], *buf;
        int ivlen, keylen, digestlen, blocklen, ret, i;
        gsize len;
        unsigned char hashbuf[BUFSIZE], *buf;
-#ifdef G_OS_UNIX
+#if defined G_OS_UNIX
        int rnd;
        int rnd;
+#elif defined G_OS_WIN32
+       HCRYPTPROV rnd;
 #endif
 
        g_return_val_if_fail(password != NULL, NULL);
 #endif
 
        g_return_val_if_fail(password != NULL, NULL);
@@ -441,34 +477,46 @@ gchar *password_decrypt_gnutls(const gchar *password,
        memcpy(key.data, &hashbuf, keylen);
        key.size = keylen;
 
        memcpy(key.data, &hashbuf, keylen);
        key.size = keylen;
 
-#ifdef G_OS_UNIX
        /* Prepare our source of random data. */
        /* Prepare our source of random data. */
+#if defined G_OS_UNIX
        rnd = open("/dev/urandom", O_RDONLY);
        if (rnd == -1) {
                perror("fopen on /dev/urandom");
        rnd = open("/dev/urandom", O_RDONLY);
        if (rnd == -1) {
                perror("fopen on /dev/urandom");
+#elif defined G_OS_WIN32
+       if (!CryptAcquireContext(&rnd, NULL, NULL, PROV_RSA_FULL, 0) &&
+                       !CryptAcquireContext(&rnd, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) {
+               debug_print("Could not acquire a CSP handle.\n");
+#endif
                g_free(key.data);
                g_free(iv.data);
                g_strfreev(tokens);
                return NULL;
        }
                g_free(key.data);
                g_free(iv.data);
                g_strfreev(tokens);
                return NULL;
        }
-#endif
 
        /* Prepare random IV for cipher */
        iv.data = malloc(ivlen);
        iv.size = ivlen;
 
        /* Prepare random IV for cipher */
        iv.data = malloc(ivlen);
        iv.size = ivlen;
-#ifdef G_OS_UNIX
+#if defined G_OS_UNIX
        ret = read(rnd, iv.data, ivlen);
        if (ret != ivlen) {
                perror("read into iv");
        ret = read(rnd, iv.data, ivlen);
        if (ret != ivlen) {
                perror("read into iv");
+               close(rnd);
+#elif defined G_OS_WIN32
+       if (!CryptGenRandom(rnd, ivlen, iv.data)) {
+               debug_print("Could not read random data for IV\n");
+               CryptReleaseContext(rnd, 0);
+#endif
                g_free(key.data);
                g_free(iv.data);
                g_strfreev(tokens);
                g_free(key.data);
                g_free(iv.data);
                g_strfreev(tokens);
-               close(rnd);
                return NULL;
        }
 
        /* We don't need any more random data. */
                return NULL;
        }
 
        /* We don't need any more random data. */
+#if defined G_OS_UNIX
        close(rnd);
        close(rnd);
+#elif defined G_OS_WIN32
+       CryptReleaseContext(rnd, 0);
 #endif
 
        /* Prepare encrypted password string for decryption. */
 #endif
 
        /* Prepare encrypted password string for decryption. */