d48b05448825d51a4471b5f4506291694701844e
[claws.git] / src / plugins / pgpcore / sgpgme.c
1 /*
2  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 1999-2006 Hiroyuki Yamamoto & the Sylpheed-Claws 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 2 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, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19  
20 #ifdef HAVE_CONFIG_H
21 #  include "config.h"
22 #endif
23  
24 #ifdef USE_GPGME
25
26 #include <time.h>
27 #include <gtk/gtk.h>
28 #include <gpgme.h>
29 #include <glib.h>
30 #include <glib/gi18n.h>
31 #include <stdio.h>
32 #include <errno.h>
33 #ifndef G_OS_WIN32
34 #include <sys/mman.h>
35 #endif
36 #if HAVE_LOCALE_H
37 #  include <locale.h>
38 #endif
39
40 #include "sgpgme.h"
41 #include "privacy.h"
42 #include "prefs_common.h"
43 #include "utils.h"
44 #include "alertpanel.h"
45 #include "passphrase.h"
46 #include "prefs_gpg.h"
47 #include "account.h"
48 #include "select-keys.h"
49
50 static void sgpgme_disable_all(void)
51 {
52     /* FIXME: set a flag, so that we don't bother the user with failed
53      * gpgme messages */
54 }
55
56 gpgme_verify_result_t sgpgme_verify_signature(gpgme_ctx_t ctx, gpgme_data_t sig, 
57                                         gpgme_data_t plain, gpgme_data_t dummy)
58 {
59         gpgme_verify_result_t status = NULL;
60         gpgme_error_t err;
61
62         if ((err = gpgme_op_verify(ctx, sig, plain, dummy)) != GPG_ERR_NO_ERROR) {
63                 debug_print("op_verify err %s\n", gpgme_strerror(err));
64                 privacy_set_error(gpgme_strerror(err));
65                 return GINT_TO_POINTER(-GPG_ERR_SYSTEM_ERROR);
66                 
67         }
68         status = gpgme_op_verify_result(ctx);
69
70         return status;
71 }
72
73 SignatureStatus sgpgme_sigstat_gpgme_to_privacy(gpgme_ctx_t ctx, gpgme_verify_result_t status)
74 {
75         unsigned long validity = 0;
76         gpgme_signature_t sig = NULL;
77         
78         if (GPOINTER_TO_INT(status) == -GPG_ERR_SYSTEM_ERROR) {
79                 debug_print("system error\n");
80                 return SIGNATURE_CHECK_FAILED;
81         }
82
83         if (status == NULL) {
84                 debug_print("status == NULL\n");
85                 return SIGNATURE_UNCHECKED;
86         }
87         sig = status->signatures;
88
89         if (sig == NULL) {
90                 debug_print("sig == NULL\n");
91                 return SIGNATURE_UNCHECKED;
92         }
93         validity = sig->validity;
94
95         debug_print("err code %d\n", gpg_err_code(sig->status));
96         switch (gpg_err_code(sig->status)) {
97         case GPG_ERR_NO_ERROR:
98                 switch (gpg_err_code(sig->validity)) {
99                 case GPGME_VALIDITY_NEVER:
100                         return SIGNATURE_INVALID;
101                 case GPGME_VALIDITY_UNKNOWN:
102                 case GPGME_VALIDITY_UNDEFINED:
103                 case GPGME_VALIDITY_MARGINAL:
104                 case GPGME_VALIDITY_FULL:
105                 case GPGME_VALIDITY_ULTIMATE:
106                         return SIGNATURE_OK;
107                 default:
108                         return SIGNATURE_CHECK_FAILED;
109                 }
110         case GPG_ERR_SIG_EXPIRED:
111         case GPG_ERR_KEY_EXPIRED:
112                 return SIGNATURE_WARN;
113         case GPG_ERR_BAD_SIGNATURE:
114                 return SIGNATURE_INVALID;
115         case GPG_ERR_NO_PUBKEY:
116                 return SIGNATURE_CHECK_FAILED;
117         default:
118                 return SIGNATURE_CHECK_FAILED;
119         }
120         return SIGNATURE_CHECK_FAILED;
121 }
122
123 static const gchar *get_validity_str(unsigned long validity)
124 {
125         switch (gpg_err_code(validity)) {
126         case GPGME_VALIDITY_UNKNOWN:
127                 return _("Unknown");
128         case GPGME_VALIDITY_UNDEFINED:
129                 return _("Undefined");
130         case GPGME_VALIDITY_NEVER:
131                 return _("Never");
132         case GPGME_VALIDITY_MARGINAL:
133                 return _("Marginal");
134         case GPGME_VALIDITY_FULL:
135                 return _("Full");
136         case GPGME_VALIDITY_ULTIMATE:
137                 return _("Ultimate");
138         default:
139                 return _("Error");
140         }
141 }
142
143 static gchar *extract_name(const char *uid)
144 {
145         if (uid == NULL)
146                 return NULL;
147         if (!strncmp(uid, "CN=", 3)) {
148                 gchar *result = g_strdup(uid+3);
149                 if (strstr(result, ","))
150                         *(strstr(result, ",")) = '\0';
151                 return result;
152         } else if (strstr(uid, ",CN=")) {
153                 gchar *result = g_strdup(strstr(uid, ",CN=")+4);
154                 if (strstr(result, ","))
155                         *(strstr(result, ",")) = '\0';
156                 return result;
157         } else {
158                 return g_strdup(uid);
159         }
160 }
161 gchar *sgpgme_sigstat_info_short(gpgme_ctx_t ctx, gpgme_verify_result_t status)
162 {
163         gpgme_signature_t sig = NULL;
164         gchar *uname = NULL;
165         gpgme_key_t key;
166         gchar *result = NULL;
167         gpgme_error_t err = 0;
168         static gboolean warned = FALSE;
169
170         if (GPOINTER_TO_INT(status) == -GPG_ERR_SYSTEM_ERROR) {
171                 return g_strdup_printf(_("The signature can't be checked - %s"), privacy_get_error());
172         }
173
174         if (status == NULL) {
175                 return g_strdup(_("The signature has not been checked."));
176         }
177         sig = status->signatures;
178         if (sig == NULL) {
179                 return g_strdup(_("The signature has not been checked."));
180         }
181
182         err = gpgme_get_key(ctx, sig->fpr, &key, 0);
183         if (gpg_err_code(err) == GPG_ERR_NO_AGENT) {
184                 if (!warned)
185                         alertpanel_error(_("PGP Core: Can't get key - no gpg-agent running."));
186                 else
187                         g_warning(_("PGP Core: Can't get key - no gpg-agent running."));
188                 warned = TRUE;
189         }
190         if (key)
191                 uname = extract_name(key->uids->uid);
192         else
193                 uname = g_strdup("<?>");
194         switch (gpg_err_code(sig->status)) {
195         case GPG_ERR_NO_ERROR:
196                 switch (gpg_err_code(sig->validity)) {
197                 case GPGME_VALIDITY_MARGINAL:
198                 case GPGME_VALIDITY_FULL:
199                 case GPGME_VALIDITY_ULTIMATE:
200                         result = g_strdup_printf(_("Good signature from %s."), uname);
201                         break;
202                 case GPGME_VALIDITY_UNKNOWN:
203                 case GPGME_VALIDITY_UNDEFINED:
204                 case GPGME_VALIDITY_NEVER:
205                 default:
206                         result = g_strdup_printf(_("Good signature (untrusted) from %s."), uname);
207                         break;
208                 }
209                 break;
210         case GPG_ERR_SIG_EXPIRED:
211                 result = g_strdup_printf(_("Expired signature from %s."), uname);
212                 break;
213         case GPG_ERR_KEY_EXPIRED:
214                 result = g_strdup_printf(_("Expired key from %s."), uname);
215                 break;
216         case GPG_ERR_BAD_SIGNATURE:
217                 result = g_strdup_printf(_("Bad signature from %s."), uname);
218                 break;
219         case GPG_ERR_NO_PUBKEY: {
220                 gchar *id = g_strdup(sig->fpr + strlen(sig->fpr)-8);
221                 result = g_strdup_printf(_("Key 0x%s not available to verify this signature."), id);
222                 g_free(id);
223                 break;
224                 }
225         default:
226                 result = g_strdup(_("The signature has not been checked."));
227                 break;
228         }
229         if (result == NULL)
230                 result = g_strdup(_("Error"));
231         g_free(uname);
232         return result;
233 }
234
235 gchar *sgpgme_sigstat_info_full(gpgme_ctx_t ctx, gpgme_verify_result_t status)
236 {
237         gint i = 0;
238         gchar *ret;
239         GString *siginfo;
240         gpgme_signature_t sig = status->signatures;
241         
242         siginfo = g_string_sized_new(64);
243         while (sig) {
244                 gpgme_user_id_t user = NULL;
245                 gpgme_key_t key;
246
247                 const gchar *keytype, *keyid, *uid;
248                 
249                 gpgme_get_key(ctx, sig->fpr, &key, 0);
250
251                 if (key) {
252                         user = key->uids;
253                         keytype = gpgme_pubkey_algo_name(
254                                         key->subkeys->pubkey_algo);
255                         keyid = key->subkeys->keyid;
256                         uid = user->uid;
257                 } else {
258                         keytype = "?";
259                         keyid = "?";
260                         uid = "?";
261                 }
262                 g_string_append_printf(siginfo,
263                         _("Signature made using %s key ID %s\n"),
264                         keytype, keyid);
265                 
266                 switch (gpg_err_code(sig->status)) {
267                 case GPG_ERR_NO_ERROR:
268                 case GPG_ERR_KEY_EXPIRED:
269                         g_string_append_printf(siginfo,
270                                 _("Good signature from \"%s\" (Trust: %s)\n"),
271                                 uid, get_validity_str(sig->validity));
272                         break;
273                 case GPG_ERR_SIG_EXPIRED:
274                         g_string_append_printf(siginfo,
275                                 _("Expired signature from \"%s\"\n"),
276                                 uid);
277                         break;
278                 case GPG_ERR_BAD_SIGNATURE:
279                         g_string_append_printf(siginfo,
280                                 _("BAD signature from \"%s\"\n"),
281                                 uid);
282                         break;
283                 default:
284                         break;
285                 }
286                 if (sig->status != GPG_ERR_BAD_SIGNATURE) {
287                         gint j = 1;
288                         user = user ? user->next : NULL;
289                         while (user != NULL) {
290                                 g_string_append_printf(siginfo,
291                                         _("                aka \"%s\"\n"),
292                                         user->uid);
293                                 j++;
294                                 user = user->next;
295                         }
296                         g_string_append_printf(siginfo,
297                                 _("Primary key fingerprint: %s\n"), 
298                                 sig ? sig->fpr: "?");
299 #ifdef HAVE_GPGME_PKA_TRUST
300                         if (sig->pka_trust == 1 && sig->pka_address) {
301                                 g_string_append_printf(siginfo,
302                                    _("WARNING: Signer's address \"%s\" "
303                                       "does not match DNS entry\n"), 
304                                    sig->pka_address);
305                         }
306                         else if (sig->pka_trust == 2 && sig->pka_address) {
307                                 g_string_append_printf(siginfo,
308                                    _("Verified signer's address is \"%s\"\n"),
309                                    sig->pka_address);
310                                 /* FIXME: Compare the address to the
311                                  * From: address.  */
312                         }
313 #endif /*HAVE_GPGME_PKA_TRUST*/
314                 }
315
316                 g_string_append(siginfo, "\n");
317                 i++;
318                 sig = sig->next;
319         }
320
321         ret = siginfo->str;
322         g_string_free(siginfo, FALSE);
323         return ret;
324 }
325
326 gpgme_data_t sgpgme_data_from_mimeinfo(MimeInfo *mimeinfo)
327 {
328         gpgme_data_t data = NULL;
329         gpgme_error_t err;
330         FILE *fp = g_fopen(mimeinfo->data.filename, "rb");
331         gchar *tmp_file = NULL;
332
333         if (!fp) 
334                 return NULL;
335
336         tmp_file = get_tmp_file();
337         copy_file_part(fp, mimeinfo->offset, mimeinfo->length, tmp_file);
338         fclose(fp);
339         fp = NULL;
340         debug_print("tmp file %s\n", tmp_file);
341         
342         err = gpgme_data_new_from_file(&data, tmp_file, 1);
343         g_unlink(tmp_file);
344         g_free(tmp_file);
345
346         debug_print("data %p (%d %d)\n", (void *)&data, mimeinfo->offset, mimeinfo->length);
347         if (err) {
348                 debug_print ("gpgme_data_new_from_file failed: %s\n",
349                              gpgme_strerror (err));
350                 privacy_set_error(_("Couldn't get data from message, %s"), gpgme_strerror(err));
351                 return NULL;
352         }
353         return data;
354 }
355
356 gpgme_data_t sgpgme_decrypt_verify(gpgme_data_t cipher, gpgme_verify_result_t *status, gpgme_ctx_t ctx)
357 {
358         struct passphrase_cb_info_s info;
359         gpgme_data_t plain;
360         gpgme_error_t err;
361
362         memset (&info, 0, sizeof info);
363         
364         if ((err = gpgme_data_new(&plain)) != GPG_ERR_NO_ERROR) {
365                 gpgme_release(ctx);
366                 privacy_set_error(_("Couldn't initialize data, %s"), gpgme_strerror(err));
367                 return NULL;
368         }
369         
370         if (gpgme_get_protocol(ctx) == GPGME_PROTOCOL_OpenPGP) {
371                 if (!getenv("GPG_AGENT_INFO")) {
372                         info.c = ctx;
373                         gpgme_set_passphrase_cb (ctx, gpgmegtk_passphrase_cb, &info);
374                 }
375         } else {
376                 info.c = ctx;
377                 gpgme_set_passphrase_cb (ctx, NULL, &info);
378         }
379         
380         
381         if (gpgme_get_protocol(ctx) == GPGME_PROTOCOL_OpenPGP) {
382                 err = gpgme_op_decrypt_verify(ctx, cipher, plain);
383                 if (err != GPG_ERR_NO_ERROR) {
384                         debug_print("can't decrypt (%s)\n", gpgme_strerror(err));
385                         privacy_set_error("%s", gpgme_strerror(err));
386                         gpgmegtk_free_passphrase();
387                         gpgme_data_release(plain);
388                         return NULL;
389                 }
390
391                 err = gpgme_data_rewind(plain);
392                 if (err) {
393                         debug_print("can't seek (%d %d %s)\n", err, errno, strerror(errno));
394                 }
395
396                 debug_print("decrypted.\n");
397                 *status = gpgme_op_verify_result (ctx);
398         } else {
399                 err = gpgme_op_decrypt(ctx, cipher, plain);
400                 if (err != GPG_ERR_NO_ERROR) {
401                         debug_print("can't decrypt (%s)\n", gpgme_strerror(err));
402                         gpgmegtk_free_passphrase();
403                         gpgme_data_release(plain);
404                         return NULL;
405                 }
406
407                 err = gpgme_data_rewind(plain);
408                 if (err) {
409                         debug_print("can't seek (%d %d %s)\n", err, errno, strerror(errno));
410                 }
411
412                 debug_print("decrypted.\n");
413                 *status = gpgme_op_verify_result (ctx);
414         }
415         return plain;
416 }
417
418 gchar *sgpgme_get_encrypt_data(GSList *recp_names, gpgme_protocol_t proto)
419 {
420         SelectionResult result = KEY_SELECTION_CANCEL;
421         gpgme_key_t *keys = gpgmegtk_recipient_selection(recp_names, &result,
422                                 proto);
423         gchar *ret = NULL;
424         int i = 0;
425
426         if (!keys) {
427                 if (result == KEY_SELECTION_DONT)
428                         return g_strdup("_DONT_ENCRYPT_");
429                 else
430                         return NULL;
431         }
432         while (keys[i]) {
433                 gpgme_subkey_t skey = keys[i]->subkeys;
434                 gchar *fpr = skey->fpr;
435                 gchar *tmp = NULL;
436                 debug_print("adding %s\n", fpr);
437                 tmp = g_strconcat(ret?ret:"", fpr, " ", NULL);
438                 g_free(ret);
439                 ret = tmp;
440                 i++;
441         }
442         return ret;
443 }
444
445 gboolean sgpgme_setup_signers(gpgme_ctx_t ctx, PrefsAccount *account)
446 {
447         GPGAccountConfig *config;
448
449         gpgme_signers_clear(ctx);
450
451         config = prefs_gpg_account_get_config(account);
452
453         switch(config->sign_key) {
454         case SIGN_KEY_DEFAULT:
455                 debug_print("using default gnupg key\n");
456                 break;
457         case SIGN_KEY_BY_FROM:
458                 debug_print("using key for %s\n", account->address);
459                 break;
460         case SIGN_KEY_CUSTOM:
461                 debug_print("using key for %s\n", config->sign_key_id);
462                 break;
463         }
464
465         if (config->sign_key != SIGN_KEY_DEFAULT) {
466                 gchar *keyid;
467                 gpgme_key_t key, key2;
468                 gpgme_error_t err;
469
470                 if (config->sign_key == SIGN_KEY_BY_FROM)
471                         keyid = account->address;
472                 else if (config->sign_key == SIGN_KEY_CUSTOM)
473                         keyid = config->sign_key_id;
474                 else
475                         goto bail;
476
477                 err = gpgme_op_keylist_start(ctx, keyid, 1);
478                 if (!err)
479                         err = gpgme_op_keylist_next(ctx, &key);
480                 if (err) {
481                         g_warning("setup_signers start: %s", gpgme_strerror(err));
482                         privacy_set_error(_("Private key not found (%s)"), gpgme_strerror(err));
483                         goto bail;
484                 }
485                 
486                 err = gpgme_op_keylist_next(ctx, &key2);
487                 if (!err) {
488                         g_warning("ambiguous specification of private key '%s'\n",
489                                 keyid);
490                         privacy_set_error(_("Private key specification is ambiguous"));
491                         goto bail;
492                 }
493                 
494                 gpgme_op_keylist_end(ctx);
495                 err = gpgme_signers_add(ctx, key);
496                 gpgme_key_release(key);
497                 
498                 if (err) {
499                         g_warning("error adding secret key: %s\n", gpgme_strerror(err));
500                         privacy_set_error(_("Error setting private key: %s"), gpgme_strerror(err));
501                         goto bail;
502                 }
503         }
504
505         prefs_gpg_account_free_config(config);
506
507         return TRUE;
508 bail:
509         prefs_gpg_account_free_config(config);
510         return FALSE;
511 }
512
513 void sgpgme_init()
514 {
515         gpgme_engine_info_t engineInfo;
516         if (gpgme_check_version("1.0.0")) {
517 #ifdef LC_CTYPE
518                 gpgme_set_locale(NULL, LC_CTYPE, setlocale(LC_CTYPE, NULL));
519 #endif
520 #ifdef LC_MESSAGES
521                 gpgme_set_locale(NULL, LC_MESSAGES, setlocale(LC_MESSAGES, NULL));
522 #endif
523                 if (!gpgme_get_engine_info(&engineInfo)) {
524                         while (engineInfo) {
525                                 debug_print("GpgME Protocol: %s\n"
526                                             "Version: %s (req %s)\n"
527                                             "Executable: %s\n",
528                                         gpgme_get_protocol_name(engineInfo->protocol),
529                                         engineInfo->version ? engineInfo->version:"???",
530                                         engineInfo->req_version ? engineInfo->req_version:"???",
531                                         engineInfo->file_name ? engineInfo->file_name:"???");
532                                 if (engineInfo->protocol == GPGME_PROTOCOL_OpenPGP
533                                 &&  gpgme_engine_check_version(engineInfo->protocol) != 
534                                         GPG_ERR_NO_ERROR) {
535                                         if (engineInfo->file_name && !engineInfo->version) {
536                                                 alertpanel_error(_("Gpgme protocol '%s' is unusable: "
537                                                                    "Engine '%s' isn't installed properly."),
538                                                                    gpgme_get_protocol_name(engineInfo->protocol),
539                                                                    engineInfo->file_name);
540                                         } else if (engineInfo->file_name && engineInfo->version
541                                           && engineInfo->req_version) {
542                                                 alertpanel_error(_("Gpgme protocol '%s' is unusable: "
543                                                                    "Engine '%s' version %s is installed, "
544                                                                    "but version %s is required.\n"),
545                                                                    gpgme_get_protocol_name(engineInfo->protocol),
546                                                                    engineInfo->file_name,
547                                                                    engineInfo->version,
548                                                                    engineInfo->req_version);
549                                         } else {
550                                                 alertpanel_error(_("Gpgme protocol '%s' is unusable "
551                                                                    "(unknown problem)"),
552                                                                    gpgme_get_protocol_name(engineInfo->protocol));
553                                         }
554                                 }
555                                 engineInfo = engineInfo->next;
556                         }
557                 }
558         } else {
559                 sgpgme_disable_all();
560
561                 if (prefs_gpg_get_config()->gpg_warning) {
562                         AlertValue val;
563
564                         val = alertpanel_full
565                                 (_("Warning"),
566                                  _("GnuPG is not installed properly, or needs "
567                                  "to be upgraded.\n"
568                                  "OpenPGP support disabled."),
569                                  GTK_STOCK_CLOSE, NULL, NULL, TRUE, NULL,
570                                  ALERT_WARNING, G_ALERTDEFAULT);
571                         if (val & G_ALERTDISABLE)
572                                 prefs_gpg_get_config()->gpg_warning = FALSE;
573                 }
574         }
575 }
576
577 void sgpgme_done()
578 {
579         gpgmegtk_free_passphrase();
580 }
581
582 void sgpgme_create_secret_key(PrefsAccount *account)
583 {
584         AlertValue val = alertpanel(_("No PGP key found"),
585                         _("Sylpheed-Claws did not find a secret PGP key, "
586                           "which means that you won't be able to sign "
587                           "emails or receive encrypted emails.\n"
588                           "Do you want to create a secret key now?"),
589                           GTK_STOCK_NO, "+" GTK_STOCK_YES, NULL);
590         gchar *key_parms = NULL;
591         gchar *name = NULL;
592         gchar *email = NULL;
593         gchar *passphrase = NULL, *passphrase_second = NULL;
594         gint prev_bad = 0;
595         gchar *tmp = NULL;
596         gpgme_error_t err = 0;
597         gpgme_ctx_t ctx;
598         GtkWidget *window = NULL;
599         gpgme_genkey_result_t key;
600
601         if (account == NULL)
602                 account = account_get_default();
603
604         if (val == G_ALERTDEFAULT) {
605                 prefs_gpg_get_config()->gpg_ask_create_key = FALSE;
606                 prefs_gpg_save_config();
607                 return;
608         }
609
610         if (account->name) {
611                 name = g_strdup(account->name);
612         } else {
613                 name = g_strdup(account->address);
614         }
615         email = g_strdup(account->address);
616         tmp = g_strdup_printf("%s <%s>", account->name?account->name:account->address, account->address);
617 again:
618         passphrase = passphrase_mbox(tmp, NULL, prev_bad, 1);
619         if (passphrase == NULL) {
620                 g_free(tmp);
621                 g_free(email);
622                 g_free(name);           
623                 return;
624         }
625         passphrase_second = passphrase_mbox(tmp, NULL, 0, 2);
626         if (passphrase_second == NULL) {
627                 g_free(tmp);
628                 g_free(email);
629                 g_free(passphrase);             
630                 g_free(name);           
631                 return;
632         }
633         if (strcmp(passphrase, passphrase_second)) {
634                 g_free(passphrase);
635                 g_free(passphrase_second);
636                 prev_bad = 1;
637                 goto again;
638         }
639         
640         key_parms = g_strdup_printf("<GnupgKeyParms format=\"internal\">\n"
641                                         "Key-Type: DSA\n"
642                                         "Key-Length: 1024\n"
643                                         "Subkey-Type: ELG-E\n"
644                                         "Subkey-Length: 2048\n"
645                                         "Name-Real: %s\n"
646                                         "Name-Email: %s\n"
647                                         "Expire-Date: 0\n"
648                                         "Passphrase: %s\n"
649                                         "</GnupgKeyParms>\n",
650                                         name, email, passphrase);
651 #ifndef G_PLATFORM_WIN32
652         if (mlock(passphrase, strlen(passphrase)) == -1)
653                 debug_print("couldn't lock passphrase\n");
654         if (mlock(passphrase_second, strlen(passphrase_second)) == -1)
655                 debug_print("couldn't lock passphrase2\n");
656 #endif
657         g_free(tmp);
658         g_free(email);
659         g_free(name);
660         g_free(passphrase_second);
661         g_free(passphrase);
662         
663         err = gpgme_new (&ctx);
664         if (err) {
665                 alertpanel_error(_("Couldn't generate new key: %s"), gpgme_strerror(err));
666                 g_free(key_parms);
667                 return;
668         }
669         
670
671         window = label_window_create(_("Generating your new key... Please move the mouse "
672                               "around to help generate entropy..."));
673
674         err = gpgme_op_genkey(ctx, key_parms, NULL, NULL);
675         g_free(key_parms);
676
677         gtk_widget_destroy(window);
678
679         if (err) {
680                 alertpanel_error(_("Couldn't generate new key: %s"), gpgme_strerror(err));
681                 gpgme_release(ctx);
682                 return;
683         }
684         key = gpgme_op_genkey_result(ctx);
685         if (key == NULL) {
686                 alertpanel_error(_("Couldn't generate new key: unknown error"));
687                 gpgme_release(ctx);
688                 return;
689         } else {
690                 alertpanel_notice(_("Your secret key has been generated. "
691                                     "Its fingerprint is:\n%s"),
692                                     key->fpr ? key->fpr:"null");
693         }
694         prefs_gpg_get_config()->gpg_ask_create_key = FALSE;
695         prefs_gpg_save_config();
696         gpgme_release(ctx);
697 }
698
699 gboolean sgpgme_has_secret_key(void)
700 {
701         gpgme_error_t err = 0;
702         gpgme_ctx_t ctx;
703         gpgme_key_t key;
704
705         err = gpgme_new (&ctx);
706         if (err) {
707                 debug_print("err : %s\n", gpgme_strerror(err));
708                 return TRUE;
709         }
710         err = gpgme_op_keylist_start(ctx, NULL, TRUE);
711         if (!err)
712                 err = gpgme_op_keylist_next(ctx, &key);
713         gpgme_op_keylist_end(ctx);
714         gpgme_release(ctx);
715         if (gpg_err_code(err) == GPG_ERR_EOF)
716                 return FALSE;
717         else
718                 return TRUE;
719 }
720
721 void sgpgme_check_create_key(void)
722 {
723         if (prefs_gpg_get_config()->gpg_ask_create_key &&
724             !sgpgme_has_secret_key()) {
725                 sgpgme_create_secret_key(NULL);
726         } else {
727                 prefs_gpg_get_config()->gpg_ask_create_key = FALSE;
728                 prefs_gpg_save_config();
729         }       
730 }
731 #endif /* USE_GPGME */