Close PRNG source after reading our PBKDF2 salt from it.
[claws.git] / src / password.c
1 /*
2  * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 2016 The Claws Mail Team
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #include "claws-features.h"
23 #endif
24
25 #ifdef PASSWORD_CRYPTO_GNUTLS
26 # include <gnutls/gnutls.h>
27 # include <gnutls/crypto.h>
28 #endif
29
30 #include <glib.h>
31 #include <glib/gi18n.h>
32
33 #if defined G_OS_UNIX
34 #include <fcntl.h>
35 #include <unistd.h>
36 #elif defined G_OS_WIN32
37 #include <windows.h>
38 #include <wincrypt.h>
39 #endif
40
41 #include "common/passcrypt.h"
42 #include "common/plugin.h"
43 #include "common/pkcs5_pbkdf2.h"
44 #include "common/utils.h"
45 #include "account.h"
46 #include "alertpanel.h"
47 #include "inputdialog.h"
48 #include "password.h"
49 #include "passwordstore.h"
50 #include "prefs_common.h"
51
52 #ifndef PASSWORD_CRYPTO_OLD
53 static gchar *_master_passphrase = NULL;
54
55 /* Length of stored key derivation, before base64. */
56 #define KD_LENGTH 64
57
58 /* Length of randomly generated and saved salt, used for key derivation.
59  * Also before base64. */
60 #define KD_SALT_LENGTH 64
61
62 static void _generate_salt()
63 {
64 #if defined G_OS_UNIX
65         int rnd;
66 #elif defined G_OS_WIN32
67         HCRYPTPROV rnd;
68 #endif
69         gint ret;
70         guchar salt[KD_SALT_LENGTH];
71
72         if (prefs_common_get_prefs()->master_passphrase_salt != NULL) {
73                 g_free(prefs_common_get_prefs()->master_passphrase_salt);
74         }
75
76         /* Prepare our source of random data. */
77 #if defined G_OS_UNIX
78         rnd = open("/dev/urandom", O_RDONLY);
79         if (rnd == -1) {
80                 perror("fopen on /dev/urandom");
81 #elif defined G_OS_WIN32
82         if (!CryptAcquireContext(&rnd, NULL, NULL, PROV_RSA_FULL, 0) &&
83                         !CryptAcquireContext(&rnd, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) {
84                 debug_print("Could not acquire a CSP handle.\n");
85 #endif
86                 return;
87         }
88
89 #if defined G_OS_UNIX
90         ret = read(rnd, salt, KD_SALT_LENGTH);
91         if (ret != KD_SALT_LENGTH) {
92                 perror("read into salt");
93                 close(rnd);
94 #elif defined G_OS_WIN32
95         if (!CryptGenRandom(rnd, KD_SALT_LENGTH, salt)) {
96                 debug_print("Could not read random data for salt\n");
97                 CryptReleaseContext(rnd, 0);
98 #endif
99                 return;
100         }
101
102 #if defined G_OS_UNIX
103         close(rnd);
104 #elif defined G_OS_WIN32
105         CryptReleaseContext(rnd, 0);
106 #endif
107
108         prefs_common_get_prefs()->master_passphrase_salt =
109                 g_base64_encode(salt, KD_SALT_LENGTH);
110 }
111
112 #undef KD_SALT_LENGTH
113
114 static guchar *_make_key_deriv(const gchar *passphrase, guint rounds)
115 {
116         guchar *kd, *salt;
117         gchar *saltpref = prefs_common_get_prefs()->master_passphrase_salt;
118         gsize saltlen;
119         gint ret;
120
121         /* Grab our salt, generating and saving a new random one if needed. */
122         if (saltpref == NULL || strlen(saltpref) == 0) {
123                 _generate_salt();
124                 saltpref = prefs_common_get_prefs()->master_passphrase_salt;
125         }
126         salt = g_base64_decode(saltpref, &saltlen);
127         kd = g_malloc0(KD_LENGTH);
128
129         ret = pkcs5_pbkdf2(passphrase, strlen(passphrase), salt, saltlen,
130                         kd, KD_LENGTH, rounds);
131
132         g_free(salt);
133
134         if (ret == 0) {
135                 return kd;
136         }
137
138         g_free(kd);
139         return NULL;
140 }
141
142 static const gchar *master_passphrase()
143 {
144         gchar *input;
145         gboolean end = FALSE;
146
147         if (!prefs_common_get_prefs()->use_master_passphrase) {
148                 return PASSCRYPT_KEY;
149         }
150
151         if (_master_passphrase != NULL) {
152                 debug_print("Master passphrase is in memory, offering it.\n");
153                 return _master_passphrase;
154         }
155
156         while (!end) {
157                 input = input_dialog_with_invisible(_("Input master passphrase"),
158                                 _("Input master passphrase"), NULL);
159
160                 if (input == NULL) {
161                         debug_print("Cancel pressed at master passphrase dialog.\n");
162                         break;
163                 }
164
165                 if (master_passphrase_is_correct(input)) {
166                         debug_print("Entered master passphrase seems to be correct, remembering it.\n");
167                         _master_passphrase = input;
168                         end = TRUE;
169                 } else {
170                         alertpanel_error(_("Incorrect master passphrase."));
171                 }
172         }
173
174         return _master_passphrase;
175 }
176
177 const gboolean master_passphrase_is_set()
178 {
179         if (prefs_common_get_prefs()->master_passphrase == NULL
180                         || strlen(prefs_common_get_prefs()->master_passphrase) == 0)
181                 return FALSE;
182
183         return TRUE;
184 }
185
186 const gboolean master_passphrase_is_correct(const gchar *input)
187 {
188         guchar *kd, *input_kd;
189         gchar **tokens;
190         gchar *stored_kd = prefs_common_get_prefs()->master_passphrase;
191         gsize kd_len;
192         guint rounds = 0;
193         gint ret;
194
195         g_return_val_if_fail(stored_kd != NULL && strlen(stored_kd) > 0, FALSE);
196         g_return_val_if_fail(input != NULL, FALSE);
197
198         if (stored_kd == NULL)
199                 return FALSE;
200
201         tokens = g_strsplit_set(stored_kd, "{}", 3);
202         if (tokens[0] == NULL ||
203                         strlen(tokens[0]) != 0 || /* nothing before { */
204                         tokens[1] == NULL ||
205                         strncmp(tokens[1], "PBKDF2-HMAC-SHA1,", 17) || /* correct tag */
206                         strlen(tokens[1]) <= 17 || /* something after , */
207                         (rounds = atoi(tokens[1] + 17)) <= 0 || /* valid rounds # */
208                         tokens[2] == NULL ||
209                         strlen(tokens[2]) == 0) { /* string continues after } */
210                 debug_print("Mangled master_passphrase format in config, can not use it.\n");
211                 g_strfreev(tokens);
212                 return FALSE;
213         }
214
215         stored_kd = tokens[2];
216         kd = g_base64_decode(stored_kd, &kd_len); /* should be 64 */
217         g_strfreev(tokens);
218
219         if (kd_len != KD_LENGTH) {
220                 debug_print("master_passphrase is %ld bytes long, should be %d.\n",
221                                 kd_len, KD_LENGTH);
222                 g_free(kd);
223                 return FALSE;
224         }
225
226         input_kd = _make_key_deriv(input, rounds);
227         ret = memcmp(kd, input_kd, kd_len);
228
229         g_free(input_kd);
230         g_free(kd);
231
232         if (ret == 0)
233                 return TRUE;
234
235         return FALSE;
236 }
237
238 gboolean master_passphrase_is_entered()
239 {
240         return (_master_passphrase == NULL) ? FALSE : TRUE;
241 }
242
243 void master_passphrase_forget()
244 {
245         /* If master passphrase is currently in memory (entered by user),
246          * get rid of it. User will have to enter the new one again. */
247         if (_master_passphrase != NULL) {
248                 memset(_master_passphrase, 0, strlen(_master_passphrase));
249                 g_free(_master_passphrase);
250                 _master_passphrase = NULL;
251         }
252 }
253
254 void master_passphrase_change(const gchar *oldp, const gchar *newp)
255 {
256         guchar *kd;
257         gchar *base64_kd;
258         guint rounds = prefs_common_get_prefs()->master_passphrase_pbkdf2_rounds;
259
260         g_return_if_fail(rounds > 0);
261
262         if (oldp == NULL) {
263                 /* If oldp is NULL, make sure the user has to enter the
264                  * current master passphrase before being able to change it. */
265                 master_passphrase_forget();
266                 oldp = master_passphrase();
267         }
268         g_return_if_fail(oldp != NULL);
269
270         /* Update master passphrase hash in prefs */
271         if (prefs_common_get_prefs()->master_passphrase != NULL)
272                 g_free(prefs_common_get_prefs()->master_passphrase);
273
274         if (newp != NULL) {
275                 debug_print("Storing key derivation of new master passphrase\n");
276                 kd = _make_key_deriv(newp, rounds);
277                 base64_kd = g_base64_encode(kd, 64);
278                 prefs_common_get_prefs()->master_passphrase =
279                         g_strdup_printf("{PBKDF2-HMAC-SHA1,%d}%s", rounds, base64_kd);
280                 g_free(kd);
281                 g_free(base64_kd);
282         } else {
283                 debug_print("Setting master_passphrase to NULL\n");
284                 prefs_common_get_prefs()->master_passphrase = NULL;
285         }
286
287         /* Now go over all accounts, reencrypting their passwords using
288          * the new master passphrase. */
289
290         if (oldp == NULL)
291                 oldp = PASSCRYPT_KEY;
292         if (newp == NULL)
293                 newp = PASSCRYPT_KEY;
294
295         debug_print("Reencrypting all account passwords...\n");
296         passwd_store_reencrypt_all(oldp, newp);
297
298         /* Now reencrypt all plugins passwords fields 
299          * FIXME: Unloaded plugins won't be able to update their stored passwords
300          */
301         plugins_master_passphrase_change(oldp, newp);
302
303         master_passphrase_forget();
304 }
305 #endif
306
307 gchar *password_encrypt_old(const gchar *password)
308 {
309         if (!password || strlen(password) == 0) {
310                 return NULL;
311         }
312
313         gchar *encrypted = g_strdup(password);
314         gchar *encoded, *result;
315         gsize len = strlen(password);
316
317         passcrypt_encrypt(encrypted, len);
318         encoded = g_base64_encode(encrypted, len);
319         g_free(encrypted);
320         result = g_strconcat("!", encoded, NULL);
321         g_free(encoded);
322
323         return result;
324 }
325
326 gchar *password_decrypt_old(const gchar *password)
327 {
328         if (!password || strlen(password) == 0) {
329                 return NULL;
330         }
331
332         if (*password != '!' || strlen(password) < 2) {
333                 return NULL;
334         }
335
336         gsize len;
337         gchar *decrypted = g_base64_decode(password + 1, &len);
338
339         passcrypt_decrypt(decrypted, len);
340         return decrypted;
341 }
342
343 #ifdef PASSWORD_CRYPTO_GNUTLS
344 #define BUFSIZE 128
345
346 /* Since we can't count on having GnuTLS new enough to have
347  * gnutls_cipher_get_iv_size(), we hardcode the IV length for now. */
348 #define IVLEN 16
349
350 gchar *password_encrypt_gnutls(const gchar *password,
351                 const gchar *encryption_passphrase)
352 {
353         /* Another, slightly inferior combination is AES-128-CBC + SHA-256.
354          * Any block cipher in CBC mode with keysize N and a hash algo with
355          * digest length 2*N would do. */
356         gnutls_cipher_algorithm_t algo = GNUTLS_CIPHER_AES_256_CBC;
357         gnutls_digest_algorithm_t digest = GNUTLS_DIG_SHA512;
358         gnutls_cipher_hd_t handle;
359         gnutls_datum_t key, iv;
360         int keylen, digestlen, blocklen, ret, i;
361         unsigned char hashbuf[BUFSIZE], *buf, *encbuf, *base, *output;
362 #if defined G_OS_UNIX
363         int rnd;
364 #elif defined G_OS_WIN32
365         HCRYPTPROV rnd;
366 #endif
367
368         g_return_val_if_fail(password != NULL, NULL);
369         g_return_val_if_fail(encryption_passphrase != NULL, NULL);
370
371 /*      ivlen = gnutls_cipher_get_iv_size(algo);*/
372         keylen = gnutls_cipher_get_key_size(algo);
373         blocklen = gnutls_cipher_get_block_size(algo);
374         digestlen = gnutls_hash_get_len(digest);
375
376         /* Prepare key for cipher - first half of hash of passkey XORed with
377          * the second. */
378         memset(&hashbuf, 0, BUFSIZE);
379         if ((ret = gnutls_hash_fast(digest, encryption_passphrase,
380                                         strlen(encryption_passphrase), &hashbuf)) < 0) {
381                 debug_print("Hashing passkey failed: %s\n", gnutls_strerror(ret));
382                 return NULL;
383         }
384         for (i = 0; i < digestlen/2; i++) {
385                 hashbuf[i] = hashbuf[i] ^ hashbuf[i+digestlen/2];
386         }
387
388         key.data = malloc(keylen);
389         memcpy(key.data, &hashbuf, keylen);
390         key.size = keylen;
391
392         /* Prepare our source of random data. */
393 #if defined G_OS_UNIX
394         rnd = open("/dev/urandom", O_RDONLY);
395         if (rnd == -1) {
396                 perror("fopen on /dev/urandom");
397 #elif defined G_OS_WIN32
398         if (!CryptAcquireContext(&rnd, NULL, NULL, PROV_RSA_FULL, 0) &&
399                         !CryptAcquireContext(&rnd, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) {
400                 debug_print("Could not acquire a CSP handle.\n");
401 #endif
402                 g_free(key.data);
403                 return NULL;
404         }
405
406         /* Prepare random IV for cipher */
407         iv.data = malloc(IVLEN);
408         iv.size = IVLEN;
409 #if defined G_OS_UNIX
410         ret = read(rnd, iv.data, IVLEN);
411         if (ret != IVLEN) {
412                 perror("read into iv");
413                 close(rnd);
414 #elif defined G_OS_WIN32
415         if (!CryptGenRandom(rnd, IVLEN, iv.data)) {
416                 debug_print("Could not read random data for IV\n");
417                 CryptReleaseContext(rnd, 0);
418 #endif
419                 g_free(key.data);
420                 g_free(iv.data);
421                 return NULL;
422         }
423
424         /* Initialize the encryption */
425         ret = gnutls_cipher_init(&handle, algo, &key, &iv);
426         if (ret < 0) {
427                 g_free(key.data);
428                 g_free(iv.data);
429 #if defined G_OS_UNIX
430                 close(rnd);
431 #elif defined G_OS_WIN32
432                 CryptReleaseContext(rnd, 0);
433 #endif
434                 return NULL;
435         }
436
437         /* Fill buf with one block of random data, our password, pad the
438          * rest with zero bytes. */
439         buf = malloc(BUFSIZE + blocklen);
440         memset(buf, 0, BUFSIZE);
441 #if defined G_OS_UNIX
442         ret = read(rnd, buf, blocklen);
443         if (ret != blocklen) {
444                 perror("read into buffer");
445                 close(rnd);
446 #elif defined G_OS_WIN32
447         if (!CryptGenRandom(rnd, blocklen, buf)) {
448                 debug_print("Could not read random data for IV\n");
449                 CryptReleaseContext(rnd, 0);
450 #endif
451                 g_free(buf);
452                 g_free(key.data);
453                 g_free(iv.data);
454                 gnutls_cipher_deinit(handle);
455                 return NULL;
456         }
457
458         /* We don't need any more random data. */
459 #if defined G_OS_UNIX
460         close(rnd);
461 #elif defined G_OS_WIN32
462         CryptReleaseContext(rnd, 0);
463 #endif
464
465         memcpy(buf + blocklen, password, strlen(password));
466
467         /* Encrypt into encbuf */
468         encbuf = malloc(BUFSIZE + blocklen);
469         memset(encbuf, 0, BUFSIZE + blocklen);
470         ret = gnutls_cipher_encrypt2(handle, buf, BUFSIZE + blocklen,
471                         encbuf, BUFSIZE + blocklen);
472         if (ret < 0) {
473                 g_free(key.data);
474                 g_free(iv.data);
475                 g_free(buf);
476                 g_free(encbuf);
477                 gnutls_cipher_deinit(handle);
478                 return NULL;
479         }
480
481         /* Cleanup */
482         gnutls_cipher_deinit(handle);
483         g_free(key.data);
484         g_free(iv.data);
485         g_free(buf);
486
487         /* And finally prepare the resulting string:
488          * "{algorithm}base64encodedciphertext" */
489         base = g_base64_encode(encbuf, BUFSIZE);
490         g_free(encbuf);
491         output = g_strdup_printf("{%s}%s", gnutls_cipher_get_name(algo), base);
492         g_free(base);
493
494         return output;
495 }
496
497 gchar *password_decrypt_gnutls(const gchar *password,
498                 const gchar *decryption_passphrase)
499 {
500         gchar **tokens, *tmp;
501         gnutls_cipher_algorithm_t algo;
502         gnutls_digest_algorithm_t digest = GNUTLS_DIG_UNKNOWN;
503         gnutls_cipher_hd_t handle;
504         gnutls_datum_t key, iv;
505         int keylen, digestlen, blocklen, ret, i;
506         gsize len;
507         unsigned char hashbuf[BUFSIZE], *buf;
508 #if defined G_OS_UNIX
509         int rnd;
510 #elif defined G_OS_WIN32
511         HCRYPTPROV rnd;
512 #endif
513
514         g_return_val_if_fail(password != NULL, NULL);
515         g_return_val_if_fail(decryption_passphrase != NULL, NULL);
516
517         tokens = g_strsplit_set(password, "{}", 3);
518
519         /* Parse the string, retrieving algorithm and encrypted data.
520          * We expect "{algorithm}base64encodedciphertext". */
521         if (strlen(tokens[0]) != 0 ||
522                         (algo = gnutls_cipher_get_id(tokens[1])) == GNUTLS_CIPHER_UNKNOWN ||
523                         strlen(tokens[2]) == 0)
524                 return NULL;
525
526         /* Our hash algo needs to have digest length twice as long as our
527          * cipher algo's key length. */
528         if (algo == GNUTLS_CIPHER_AES_256_CBC) {
529                 debug_print("Using AES-256-CBC + SHA-512 for decryption\n");
530                 digest = GNUTLS_DIG_SHA512;
531         } else if (algo == GNUTLS_CIPHER_AES_128_CBC) {
532                 debug_print("Using AES-128-CBC + SHA-256 for decryption\n");
533                 digest = GNUTLS_DIG_SHA256;
534         }
535         if (digest == GNUTLS_DIG_UNKNOWN) {
536                 debug_print("Password is encrypted with unsupported cipher, giving up.\n");
537                 g_strfreev(tokens);
538                 return NULL;
539         }
540
541 /*      ivlen = gnutls_cipher_get_iv_size(algo); */
542         keylen = gnutls_cipher_get_key_size(algo);
543         blocklen = gnutls_cipher_get_block_size(algo);
544         digestlen = gnutls_hash_get_len(digest);
545
546         /* Prepare key for cipher - first half of hash of passkey XORed with
547          * the second. AES-256 has key length 32 and length of SHA-512 hash
548          * is exactly twice that, 64. */
549         memset(&hashbuf, 0, BUFSIZE);
550         if ((ret = gnutls_hash_fast(digest, decryption_passphrase,
551                                         strlen(decryption_passphrase), &hashbuf)) < 0) {
552                 debug_print("Hashing passkey failed: %s\n", gnutls_strerror(ret));
553                 g_strfreev(tokens);
554                 return NULL;
555         }
556         for (i = 0; i < digestlen/2; i++) {
557                 hashbuf[i] = hashbuf[i] ^ hashbuf[i+digestlen/2];
558         }
559
560         key.data = malloc(keylen);
561         memcpy(key.data, &hashbuf, keylen);
562         key.size = keylen;
563
564         /* Prepare our source of random data. */
565 #if defined G_OS_UNIX
566         rnd = open("/dev/urandom", O_RDONLY);
567         if (rnd == -1) {
568                 perror("fopen on /dev/urandom");
569 #elif defined G_OS_WIN32
570         if (!CryptAcquireContext(&rnd, NULL, NULL, PROV_RSA_FULL, 0) &&
571                         !CryptAcquireContext(&rnd, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) {
572                 debug_print("Could not acquire a CSP handle.\n");
573 #endif
574                 g_free(key.data);
575                 g_strfreev(tokens);
576                 return NULL;
577         }
578
579         /* Prepare random IV for cipher */
580         iv.data = malloc(IVLEN);
581         iv.size = IVLEN;
582 #if defined G_OS_UNIX
583         ret = read(rnd, iv.data, IVLEN);
584         if (ret != IVLEN) {
585                 perror("read into iv");
586                 close(rnd);
587 #elif defined G_OS_WIN32
588         if (!CryptGenRandom(rnd, IVLEN, iv.data)) {
589                 debug_print("Could not read random data for IV\n");
590                 CryptReleaseContext(rnd, 0);
591 #endif
592                 g_free(key.data);
593                 g_free(iv.data);
594                 g_strfreev(tokens);
595                 return NULL;
596         }
597
598         /* We don't need any more random data. */
599 #if defined G_OS_UNIX
600         close(rnd);
601 #elif defined G_OS_WIN32
602         CryptReleaseContext(rnd, 0);
603 #endif
604
605         /* Prepare encrypted password string for decryption. */
606         tmp = g_base64_decode(tokens[2], &len);
607         g_strfreev(tokens);
608
609         /* Initialize the decryption */
610         ret = gnutls_cipher_init(&handle, algo, &key, &iv);
611         if (ret < 0) {
612                 debug_print("Cipher init failed: %s\n", gnutls_strerror(ret));
613                 g_free(key.data);
614                 g_free(iv.data);
615                 return NULL;
616         }
617
618         buf = malloc(BUFSIZE + blocklen);
619         memset(buf, 0, BUFSIZE + blocklen);
620         ret = gnutls_cipher_decrypt2(handle, tmp, len,
621                         buf, BUFSIZE + blocklen);
622         if (ret < 0) {
623                 debug_print("Decryption failed: %s\n", gnutls_strerror(ret));
624                 g_free(key.data);
625                 g_free(iv.data);
626                 g_free(buf);
627                 gnutls_cipher_deinit(handle);
628                 return NULL;
629         }
630
631         /* Cleanup */
632         gnutls_cipher_deinit(handle);
633         g_free(key.data);
634         g_free(iv.data);
635
636         tmp = g_strndup(buf + blocklen, MIN(strlen(buf + blocklen), BUFSIZE));
637         g_free(buf);
638         return tmp;
639 }
640
641 #undef BUFSIZE
642
643 #endif
644
645 gchar *password_encrypt(const gchar *password,
646                 const gchar *encryption_passphrase)
647 {
648         if (password == NULL || strlen(password) == 0) {
649                 return NULL;
650         }
651
652 #ifndef PASSWORD_CRYPTO_OLD
653         if (encryption_passphrase == NULL)
654                 encryption_passphrase = master_passphrase();
655
656         return password_encrypt_real(password, encryption_passphrase);
657 #else
658         return password_encrypt_old(password);
659 #endif
660 }
661
662 gchar *password_decrypt(const gchar *password,
663                 const gchar *decryption_passphrase)
664 {
665         if (password == NULL || strlen(password) == 0) {
666                 return NULL;
667         }
668
669         /* First, check if the password was possibly decrypted using old,
670          * obsolete method */
671         if (*password == '!') {
672                 debug_print("Trying to decrypt password using the old method...\n");
673                 return password_decrypt_old(password);
674         }
675
676         /* Try available crypto backend */
677 #ifndef PASSWORD_CRYPTO_OLD
678         if (decryption_passphrase == NULL)
679                 decryption_passphrase = master_passphrase();
680
681         if (*password == '{') {
682                 debug_print("Trying to decrypt password...\n");
683                 return password_decrypt_real(password, decryption_passphrase);
684         }
685 #endif
686
687         /* Fallback, in case the configuration is really old and
688          * stored password in plaintext */
689         debug_print("Assuming password was stored plaintext, returning it unchanged\n");
690         return g_strdup(password);
691 }