Cosmetic: use always g_getenv instead of getenv
[claws.git] / src / plugins / pgpcore / sgpgme.c
1 /*
2  * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 1999-2015 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 #ifdef HAVE_CONFIG_H
20 #  include "config.h"
21 #include "claws-features.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 <string.h>
33 #include <stdlib.h>
34 #include <errno.h>
35 #include <sys/types.h>
36 #ifndef G_OS_WIN32
37 #  include <sys/wait.h>
38 #endif
39 #if (defined(__DragonFly__) || defined(SOLARIS) || defined (__NetBSD__) || defined (__FreeBSD__) || defined (__OpenBSD__))
40 #  include <sys/signal.h>
41 #endif
42 #ifndef G_OS_WIN32
43 #include <sys/mman.h>
44 #endif
45 #if HAVE_LOCALE_H
46 #  include <locale.h>
47 #endif
48
49 #include "sgpgme.h"
50 #include "privacy.h"
51 #include "prefs_common.h"
52 #include "utils.h"
53 #include "alertpanel.h"
54 #include "passphrase.h"
55 #include "prefs_gpg.h"
56 #include "account.h"
57 #include "select-keys.h"
58
59 static void sgpgme_disable_all(void)
60 {
61     /* FIXME: set a flag, so that we don't bother the user with failed
62      * gpgme messages */
63 }
64
65 gpgme_verify_result_t sgpgme_verify_signature(gpgme_ctx_t ctx, gpgme_data_t sig, 
66                                         gpgme_data_t plain, gpgme_data_t dummy)
67 {
68         gpgme_verify_result_t status = NULL;
69         gpgme_error_t err;
70
71         if ((err = gpgme_op_verify(ctx, sig, plain, dummy)) != GPG_ERR_NO_ERROR) {
72                 debug_print("op_verify err %s\n", gpgme_strerror(err));
73                 privacy_set_error("%s", gpgme_strerror(err));
74                 return GINT_TO_POINTER(-GPG_ERR_SYSTEM_ERROR);
75         }
76         status = gpgme_op_verify_result(ctx);
77         if (status && status->signatures == NULL) {
78                 debug_print("no signature found\n");
79                 privacy_set_error(_("No signature found"));
80                 return GINT_TO_POINTER(-GPG_ERR_SYSTEM_ERROR);
81         }
82         return status;
83 }
84
85 SignatureStatus sgpgme_sigstat_gpgme_to_privacy(gpgme_ctx_t ctx, gpgme_verify_result_t status)
86 {
87         gpgme_signature_t sig = NULL;
88         
89         if (GPOINTER_TO_INT(status) == -GPG_ERR_SYSTEM_ERROR) {
90                 debug_print("system error\n");
91                 return SIGNATURE_CHECK_FAILED;
92         }
93
94         if (status == NULL) {
95                 debug_print("status == NULL\n");
96                 return SIGNATURE_UNCHECKED;
97         }
98         sig = status->signatures;
99
100         if (sig == NULL) {
101                 debug_print("sig == NULL\n");
102                 return SIGNATURE_UNCHECKED;
103         }
104
105         debug_print("err code %d\n", gpg_err_code(sig->status));
106         switch (gpg_err_code(sig->status)) {
107         case GPG_ERR_NO_ERROR:
108                 switch (sig->validity) {
109                 case GPGME_VALIDITY_NEVER:
110                         return SIGNATURE_INVALID;
111                 case GPGME_VALIDITY_UNKNOWN:
112                 case GPGME_VALIDITY_UNDEFINED:
113                 case GPGME_VALIDITY_MARGINAL:
114                 case GPGME_VALIDITY_FULL:
115                 case GPGME_VALIDITY_ULTIMATE:
116                         return SIGNATURE_OK;
117                 default:
118                         return SIGNATURE_CHECK_FAILED;
119                 }
120         case GPG_ERR_SIG_EXPIRED:
121         case GPG_ERR_CERT_REVOKED:
122                 return SIGNATURE_WARN;
123         case GPG_ERR_KEY_EXPIRED:
124                 return SIGNATURE_KEY_EXPIRED;
125         case GPG_ERR_BAD_SIGNATURE:
126                 return SIGNATURE_INVALID;
127         case GPG_ERR_NO_PUBKEY:
128                 return SIGNATURE_CHECK_FAILED;
129         default:
130                 return SIGNATURE_CHECK_FAILED;
131         }
132         return SIGNATURE_CHECK_FAILED;
133 }
134
135 static const gchar *get_validity_str(unsigned long validity)
136 {
137         switch (gpg_err_code(validity)) {
138         case GPGME_VALIDITY_UNKNOWN:
139                 return _("Unknown");
140         case GPGME_VALIDITY_UNDEFINED:
141                 return _("Undefined");
142         case GPGME_VALIDITY_NEVER:
143                 return _("Never");
144         case GPGME_VALIDITY_MARGINAL:
145                 return _("Marginal");
146         case GPGME_VALIDITY_FULL:
147                 return _("Full");
148         case GPGME_VALIDITY_ULTIMATE:
149                 return _("Ultimate");
150         default:
151                 return _("Error");
152         }
153 }
154
155 static const gchar *get_owner_trust_str(unsigned long owner_trust)
156 {
157         switch (gpgme_err_code(owner_trust)) {
158         case GPGME_VALIDITY_NEVER:
159                 return _("Untrusted");
160         case GPGME_VALIDITY_MARGINAL:
161                 return _("Marginal");
162         case GPGME_VALIDITY_FULL:
163                 return _("Full");
164         case GPGME_VALIDITY_ULTIMATE:
165                 return _("Ultimate");
166         default:
167                 return _("Unknown");
168         }
169 }
170
171 static gchar *extract_name(const char *uid)
172 {
173         if (uid == NULL)
174                 return NULL;
175         if (!strncmp(uid, "CN=", 3)) {
176                 gchar *result = g_strdup(uid+3);
177                 if (strstr(result, ","))
178                         *(strstr(result, ",")) = '\0';
179                 return result;
180         } else if (strstr(uid, ",CN=")) {
181                 gchar *result = g_strdup(strstr(uid, ",CN=")+4);
182                 if (strstr(result, ","))
183                         *(strstr(result, ",")) = '\0';
184                 return result;
185         } else {
186                 return g_strdup(uid);
187         }
188 }
189 gchar *sgpgme_sigstat_info_short(gpgme_ctx_t ctx, gpgme_verify_result_t status)
190 {
191         gpgme_signature_t sig = NULL;
192         gchar *uname = NULL;
193         gpgme_key_t key;
194         gchar *result = NULL;
195         gpgme_error_t err = 0;
196         static gboolean warned = FALSE;
197
198         if (GPOINTER_TO_INT(status) == -GPG_ERR_SYSTEM_ERROR) {
199                 return g_strdup_printf(_("The signature can't be checked - %s"), privacy_get_error());
200         }
201
202         if (status == NULL) {
203                 return g_strdup(_("The signature has not been checked."));
204         }
205         sig = status->signatures;
206         if (sig == NULL) {
207                 return g_strdup(_("The signature has not been checked."));
208         }
209
210         err = gpgme_get_key(ctx, sig->fpr, &key, 0);
211         if (gpg_err_code(err) == GPG_ERR_NO_AGENT) {
212                 if (!warned)
213                         alertpanel_error(_("PGP Core: Can't get key - no gpg-agent running."));
214                 else
215                         g_warning("PGP Core: Can't get key - no gpg-agent running.");
216                 warned = TRUE;
217         } else if (gpg_err_code(err) != GPG_ERR_NO_ERROR && gpg_err_code(err) != GPG_ERR_EOF) {
218                 return g_strdup_printf(_("The signature can't be checked - %s"), 
219                         gpgme_strerror(err));
220         } else if (gpg_err_code(err) != GPG_ERR_NO_ERROR && gpg_err_code(err) == GPG_ERR_EOF &&
221                    key == NULL) {
222                /*
223                 * When gpg is upgraded to gpg-v21 then installer tries to migrate the old
224                 * gpg keyrings found in ~/.gnupg to the new version. If the keyrings contain
225                 * very old keys using ciphers no more supported in gpg-v21 this transition
226                 * can fail and the left-over ~/.gnupg/pubring.gpg will cause claws to crash
227                 * when the above condition is meet.
228                 */
229                return g_strdup_printf(_("The signature can't be checked - %s."),
230                         gpgme_strerror(err));
231         }
232         if (key)
233                 uname = extract_name(key->uids->uid);
234         else
235                 uname = g_strdup("<?>");
236
237         switch (gpg_err_code(sig->status)) {
238         case GPG_ERR_NO_ERROR:
239                switch (key->uids?key->uids->validity:GPGME_VALIDITY_UNKNOWN) {
240                 case GPGME_VALIDITY_ULTIMATE:
241                         result = g_strdup_printf(_("Good signature from \"%s\" [ultimate]"), uname);
242                         break;
243                 case GPGME_VALIDITY_FULL:
244                         result = g_strdup_printf(_("Good signature from \"%s\" [full]"), uname);
245                         break;
246                 case GPGME_VALIDITY_MARGINAL:
247                         result = g_strdup_printf(_("Good signature from \"%s\" [marginal]"), uname);
248                         break;
249                 case GPGME_VALIDITY_UNKNOWN:
250                 case GPGME_VALIDITY_UNDEFINED:
251                 case GPGME_VALIDITY_NEVER:
252                 default:
253                         result = g_strdup_printf(_("Good signature from \"%s\""), uname);
254                         break;
255                }
256                 break;
257         case GPG_ERR_SIG_EXPIRED:
258                 result = g_strdup_printf(_("Expired signature from \"%s\""), uname);
259                 break;
260         case GPG_ERR_KEY_EXPIRED:
261                 result = g_strdup_printf(_("Good signature from \"%s\", but the key has expired"), uname);
262                 break;
263         case GPG_ERR_CERT_REVOKED:
264                 result = g_strdup_printf(_("Good signature from \"%s\", but the key has been revoked"), uname);
265                 break;
266         case GPG_ERR_BAD_SIGNATURE:
267                 result = g_strdup_printf(_("Bad signature from \"%s\""), uname);
268                 break;
269         case GPG_ERR_NO_PUBKEY: {
270                 gchar *id = g_strdup(sig->fpr + strlen(sig->fpr)-8);
271                 result = g_strdup_printf(_("Key 0x%s not available to verify this signature"), id);
272                 g_free(id);
273                 break;
274                 }
275         default:
276                 result = g_strdup(_("The signature has not been checked"));
277                 break;
278         }
279         if (result == NULL)
280                 result = g_strdup(_("Error"));
281         g_free(uname);
282         return result;
283 }
284
285 gchar *sgpgme_sigstat_info_full(gpgme_ctx_t ctx, gpgme_verify_result_t status)
286 {
287         gint i = 0;
288         gchar *ret;
289         GString *siginfo;
290         gpgme_signature_t sig = NULL;
291
292         siginfo = g_string_sized_new(64);
293         if (status == NULL) {
294                 g_string_append_printf(siginfo,
295                         _("Error checking signature: no status\n"));
296                 goto bail;
297          }
298
299         sig = status->signatures;
300         
301         while (sig) {
302                 char buf[100];
303                 struct tm lt;
304                 gpgme_key_t key;
305                 gpgme_error_t err;
306                 const gchar *keytype, *keyid, *uid;
307                 
308                 err = gpgme_get_key(ctx, sig->fpr, &key, 0);
309
310                 if (err != GPG_ERR_NO_ERROR) {
311                         key = NULL;
312                         g_string_append_printf(siginfo, 
313                                 _("Error checking signature: %s\n"),
314                                 gpgme_strerror(err));
315                         goto bail;
316                 }
317                 if (key) {
318                         keytype = gpgme_pubkey_algo_name(
319                                         key->subkeys->pubkey_algo);
320                         keyid = key->subkeys->keyid;
321                         uid = key->uids->uid;
322                 } else {
323                         keytype = "?";
324                         keyid = "?";
325                         uid = "?";
326                 }
327
328                 memset(buf, 0, sizeof(buf));
329                 fast_strftime(buf, sizeof(buf)-1, prefs_common_get_prefs()->date_format, localtime_r(&sig->timestamp, &lt));
330                 g_string_append_printf(siginfo,
331                         _("Signature made on %s using %s key ID %s\n"),
332                         buf, keytype, keyid);
333                 
334                 switch (gpg_err_code(sig->status)) {
335                 case GPG_ERR_NO_ERROR:
336                         g_string_append_printf(siginfo,
337                                 _("Good signature from uid \"%s\" (Validity: %s)\n"),
338                                 uid, get_validity_str((key && key->uids) ? key->uids->validity:GPGME_VALIDITY_UNKNOWN));
339                         break;
340                 case GPG_ERR_KEY_EXPIRED:
341                         g_string_append_printf(siginfo,
342                                 _("Expired key uid \"%s\"\n"),
343                                 uid);
344                         break;
345                 case GPG_ERR_SIG_EXPIRED:
346                         g_string_append_printf(siginfo,
347                                 _("Expired signature from uid \"%s\" (Validity: %s)\n"),
348                                 uid, get_validity_str((key && key->uids) ? key->uids->validity:GPGME_VALIDITY_UNKNOWN));
349                         break;
350                 case GPG_ERR_CERT_REVOKED:
351                         g_string_append_printf(siginfo,
352                                 _("Revoked key uid \"%s\"\n"),
353                                 uid);
354                         break;
355                 case GPG_ERR_BAD_SIGNATURE:
356                         g_string_append_printf(siginfo,
357                                 _("BAD signature from \"%s\"\n"),
358                                 uid);
359                         break;
360                 default:
361                         break;
362                 }
363                 if (sig->status != GPG_ERR_BAD_SIGNATURE) {
364                         gint j = 1;
365                         if (key) {
366                                 key->uids = key->uids ? key->uids->next : NULL;
367                                 while (key->uids != NULL) {
368                                         g_string_append_printf(siginfo,
369                                                 g_strconcat("                    ",
370                                                             _("uid \"%s\" (Validity: %s)\n"), NULL),
371                                                 key->uids->uid,
372                                                 key->uids->revoked==TRUE?_("Revoked"):get_validity_str(key->uids->validity));
373                                         j++;
374                                         key->uids = key->uids->next;
375                                 }
376                         }
377                         g_string_append_printf(siginfo,_("Owner Trust: %s\n"),
378                                                key ? get_owner_trust_str(key->owner_trust) : _("No key!"));
379                         g_string_append(siginfo,
380                                 _("Primary key fingerprint:"));
381                         const char* primary_fpr = NULL;
382                         if (key && key->subkeys && key->subkeys->fpr)
383                                 primary_fpr = key->subkeys->fpr;
384                         else
385                                 g_string_append(siginfo, " ?");
386                         int idx; /* now pretty-print the fingerprint */
387                         for (idx=0; primary_fpr && *primary_fpr!='\0'; idx++, primary_fpr++) {
388                                 if (idx%4==0)
389                                         g_string_append_c(siginfo, ' ');
390                                 if (idx%20==0)
391                                         g_string_append_c(siginfo, ' ');
392                                 g_string_append_c(siginfo, (gchar)*primary_fpr);
393                         }
394                         g_string_append_c(siginfo, '\n');
395 #ifdef HAVE_GPGME_PKA_TRUST
396                         if (sig->pka_trust == 1 && sig->pka_address) {
397                                 g_string_append_printf(siginfo,
398                                    _("WARNING: Signer's address \"%s\" "
399                                       "does not match DNS entry\n"), 
400                                    sig->pka_address);
401                         }
402                         else if (sig->pka_trust == 2 && sig->pka_address) {
403                                 g_string_append_printf(siginfo,
404                                    _("Verified signer's address is \"%s\"\n"),
405                                    sig->pka_address);
406                                 /* FIXME: Compare the address to the
407                                  * From: address.  */
408                         }
409 #endif /*HAVE_GPGME_PKA_TRUST*/
410                 }
411
412                 g_string_append(siginfo, "\n");
413                 i++;
414                 sig = sig->next;
415         }
416 bail:
417         ret = siginfo->str;
418         g_string_free(siginfo, FALSE);
419         return ret;
420 }
421
422 gpgme_data_t sgpgme_data_from_mimeinfo(MimeInfo *mimeinfo)
423 {
424         gpgme_data_t data = NULL;
425         gpgme_error_t err;
426         FILE *fp = g_fopen(mimeinfo->data.filename, "rb");
427
428         if (!fp) 
429                 return NULL;
430
431         err = gpgme_data_new_from_filepart(&data, NULL, fp, mimeinfo->offset, mimeinfo->length);
432         fclose(fp);
433
434         debug_print("data %p (%d %d)\n", (void *)&data, mimeinfo->offset, mimeinfo->length);
435         if (err) {
436                 debug_print ("gpgme_data_new_from_file failed: %s\n",
437                              gpgme_strerror (err));
438                 privacy_set_error(_("Couldn't get data from message, %s"), gpgme_strerror(err));
439                 return NULL;
440         }
441         return data;
442 }
443
444 gpgme_data_t sgpgme_decrypt_verify(gpgme_data_t cipher, gpgme_verify_result_t *status, gpgme_ctx_t ctx)
445 {
446         struct passphrase_cb_info_s info;
447         gpgme_data_t plain;
448         gpgme_error_t err;
449
450         memset (&info, 0, sizeof info);
451         
452         if ((err = gpgme_data_new(&plain)) != GPG_ERR_NO_ERROR) {
453                 gpgme_release(ctx);
454                 privacy_set_error(_("Couldn't initialize data, %s"), gpgme_strerror(err));
455                 return NULL;
456         }
457         
458         if (gpgme_get_protocol(ctx) == GPGME_PROTOCOL_OpenPGP) {
459                 prefs_gpg_enable_agent(prefs_gpg_get_config()->use_gpg_agent);
460                 if (!g_getenv("GPG_AGENT_INFO") || !prefs_gpg_get_config()->use_gpg_agent) {
461                         info.c = ctx;
462                         gpgme_set_passphrase_cb (ctx, gpgmegtk_passphrase_cb, &info);
463                 }
464         } else {
465                 prefs_gpg_enable_agent(TRUE);
466                 info.c = ctx;
467                 gpgme_set_passphrase_cb (ctx, NULL, &info);
468         }
469         
470         
471         if (gpgme_get_protocol(ctx) == GPGME_PROTOCOL_OpenPGP) {
472                 err = gpgme_op_decrypt_verify(ctx, cipher, plain);
473                 if (err != GPG_ERR_NO_ERROR) {
474                         debug_print("can't decrypt (%s)\n", gpgme_strerror(err));
475                         privacy_set_error("%s", gpgme_strerror(err));
476                         gpgmegtk_free_passphrase();
477                         gpgme_data_release(plain);
478                         return NULL;
479                 }
480
481                 err = cm_gpgme_data_rewind(plain);
482                 if (err) {
483                         debug_print("can't seek (%d %d %s)\n", err, errno, g_strerror(errno));
484                 }
485
486                 debug_print("decrypted.\n");
487                 *status = gpgme_op_verify_result (ctx);
488         } else {
489                 err = gpgme_op_decrypt(ctx, cipher, plain);
490                 if (err != GPG_ERR_NO_ERROR) {
491                         debug_print("can't decrypt (%s)\n", gpgme_strerror(err));
492                         privacy_set_error("%s", gpgme_strerror(err));
493                         gpgmegtk_free_passphrase();
494                         gpgme_data_release(plain);
495                         return NULL;
496                 }
497
498                 err = cm_gpgme_data_rewind(plain);
499                 if (err) {
500                         debug_print("can't seek (%d %d %s)\n", err, errno, g_strerror(errno));
501                 }
502
503                 debug_print("decrypted.\n");
504                 *status = gpgme_op_verify_result (ctx);
505         }
506         return plain;
507 }
508
509 gchar *sgpgme_get_encrypt_data(GSList *recp_names, gpgme_protocol_t proto)
510 {
511         SelectionResult result = KEY_SELECTION_CANCEL;
512         gpgme_key_t *keys = gpgmegtk_recipient_selection(recp_names, &result,
513                                 proto);
514         gchar *ret = NULL;
515         int i = 0;
516
517         if (!keys) {
518                 if (result == KEY_SELECTION_DONT)
519                         return g_strdup("_DONT_ENCRYPT_");
520                 else
521                         return NULL;
522         }
523         while (keys[i]) {
524                 gpgme_subkey_t skey = keys[i]->subkeys;
525                 gchar *fpr = skey->fpr;
526                 gchar *tmp = NULL;
527                 debug_print("adding %s\n", fpr);
528                 tmp = g_strconcat(ret?ret:"", fpr, " ", NULL);
529                 g_free(ret);
530                 ret = tmp;
531                 i++;
532         }
533         return ret;
534 }
535
536 gboolean sgpgme_setup_signers(gpgme_ctx_t ctx, PrefsAccount *account,
537                               const gchar *from_addr)
538 {
539         GPGAccountConfig *config;
540         const gchar *signer_addr = account->address;
541
542         gpgme_signers_clear(ctx);
543
544         if (from_addr)
545                 signer_addr = from_addr;
546         config = prefs_gpg_account_get_config(account);
547
548         switch(config->sign_key) {
549         case SIGN_KEY_DEFAULT:
550                 debug_print("using default gnupg key\n");
551                 break;
552         case SIGN_KEY_BY_FROM:
553                 debug_print("using key for %s\n", signer_addr);
554                 break;
555         case SIGN_KEY_CUSTOM:
556                 debug_print("using key for %s\n", config->sign_key_id);
557                 break;
558         }
559
560         if (config->sign_key != SIGN_KEY_DEFAULT) {
561                 const gchar *keyid;
562                 gpgme_key_t key, found_key;
563                 gpgme_error_t err;
564
565                 if (config->sign_key == SIGN_KEY_BY_FROM)
566                         keyid = signer_addr;
567                 else if (config->sign_key == SIGN_KEY_CUSTOM)
568                         keyid = config->sign_key_id;
569                 else
570                         goto bail;
571
572                 found_key = NULL;
573                 /* Look for any key, not just private ones, or GPGMe doesn't
574                  * correctly set the revoked flag. */
575                 err = gpgme_op_keylist_start(ctx, keyid, 0);
576                 while ((err = gpgme_op_keylist_next(ctx, &key)) == 0) {
577                         if (key == NULL)
578                                 continue;
579
580                         if (!key->can_sign)
581                                 continue;
582
583                         if (key->protocol != gpgme_get_protocol(ctx)) {
584                                 debug_print("skipping a key (wrong protocol %d)\n", key->protocol);
585                                 gpgme_key_release(key);
586                                 continue;
587                         }
588
589                         if (key->expired) {
590                                 debug_print("skipping a key, expired");
591                                 gpgme_key_release(key);
592                                 continue;
593                         }
594                         if (key->revoked) {
595                                 debug_print("skipping a key, revoked");
596                                 gpgme_key_release(key);
597                                 continue;
598                         }
599                         if (key->disabled) {
600                                 debug_print("skipping a key, disabled");
601                                 gpgme_key_release(key);
602                                 continue;
603                         }
604
605                         if (found_key != NULL) {
606                                 gpgme_key_release(key);
607                                 gpgme_op_keylist_end(ctx);
608                                 g_warning("ambiguous specification of secret key '%s'", keyid);
609                                 privacy_set_error(_("Secret key specification is ambiguous"));
610                                 goto bail;
611                         }
612
613                         found_key = key;
614                 }
615                 gpgme_op_keylist_end(ctx);
616
617                 if (found_key == NULL) {
618                         g_warning("setup_signers start: %s", gpgme_strerror(err));
619                         privacy_set_error(_("Secret key not found (%s)"), gpgme_strerror(err));
620                         goto bail;
621                 }
622
623                 err = gpgme_signers_add(ctx, found_key);
624                 debug_print("got key (proto %d (pgp %d, smime %d).\n",
625                             found_key->protocol, GPGME_PROTOCOL_OpenPGP,
626                             GPGME_PROTOCOL_CMS);
627                 gpgme_key_release(found_key);
628
629                 if (err) {
630                         g_warning("error adding secret key: %s",
631                                   gpgme_strerror(err));
632                         privacy_set_error(_("Error setting secret key: %s"),
633                                           gpgme_strerror(err));
634                         goto bail;
635                 }
636         }
637
638         prefs_gpg_account_free_config(config);
639
640         return TRUE;
641 bail:
642         prefs_gpg_account_free_config(config);
643         return FALSE;
644 }
645
646 void sgpgme_init()
647 {
648         gchar *ctype_locale = NULL, *messages_locale = NULL;
649         gchar *ctype_utf8_locale = NULL, *messages_utf8_locale = NULL;
650
651         gpgme_engine_info_t engineInfo;
652
653         if (strcmp(prefs_gpg_get_config()->gpg_path, "") != 0 &&
654             access(prefs_gpg_get_config()->gpg_path, X_OK) != -1)
655                 gpgme_set_engine_info(GPGME_PROTOCOL_OpenPGP,prefs_gpg_get_config()->gpg_path, NULL);
656
657         if (gpgme_check_version("1.0.0")) {
658 #ifdef LC_CTYPE
659                 debug_print("setting gpgme CTYPE locale\n");
660 #ifdef G_OS_WIN32
661                 ctype_locale = g_win32_getlocale();
662 #else
663                 ctype_locale = g_strdup(setlocale(LC_CTYPE, NULL));
664 #endif
665                 if (ctype_locale) {
666                         debug_print("setting gpgme CTYPE locale to: %s\n", ctype_locale);
667                         if (strchr(ctype_locale, '.'))
668                                 *(strchr(ctype_locale, '.')) = '\0';
669                         else if (strchr(ctype_locale, '@'))
670                                 *(strchr(ctype_locale, '@')) = '\0';
671                         ctype_utf8_locale = g_strconcat(ctype_locale, ".UTF-8", NULL);
672
673                         debug_print("setting gpgme locale to UTF8: %s\n", ctype_utf8_locale ? ctype_utf8_locale : "NULL");
674                         gpgme_set_locale(NULL, LC_CTYPE, ctype_utf8_locale);
675
676                         debug_print("done\n");
677                         g_free(ctype_utf8_locale);
678                         g_free(ctype_locale);
679                 } else {
680                         debug_print("couldn't set gpgme CTYPE locale\n");
681                 }
682 #endif
683 #ifdef LC_MESSAGES
684                 debug_print("setting gpgme MESSAGES locale\n");
685 #ifdef G_OS_WIN32
686                 messages_locale = g_win32_getlocale();
687 #else
688                 messages_locale = g_strdup(setlocale(LC_MESSAGES, NULL));
689 #endif
690                 if (messages_locale) {
691                         debug_print("setting gpgme MESSAGES locale to: %s\n", messages_locale);
692                         if (strchr(messages_locale, '.'))
693                                 *(strchr(messages_locale, '.')) = '\0';
694                         else if (strchr(messages_locale, '@'))
695                                 *(strchr(messages_locale, '@')) = '\0';
696                         messages_utf8_locale = g_strconcat(messages_locale, ".UTF-8", NULL);
697                         debug_print("setting gpgme locale to UTF8: %s\n", messages_utf8_locale ? messages_utf8_locale : "NULL");
698
699                         gpgme_set_locale(NULL, LC_MESSAGES, messages_utf8_locale);
700
701                         debug_print("done\n");
702                         g_free(messages_utf8_locale);
703                         g_free(messages_locale);
704                 } else {
705                         debug_print("couldn't set gpgme MESSAGES locale\n");
706                 }
707 #endif
708                 if (!gpgme_get_engine_info(&engineInfo)) {
709                         while (engineInfo) {
710                                 debug_print("GpgME Protocol: %s\n"
711                                             "Version: %s (req %s)\n"
712                                             "Executable: %s\n",
713                                         gpgme_get_protocol_name(engineInfo->protocol) ? gpgme_get_protocol_name(engineInfo->protocol):"???",
714                                         engineInfo->version ? engineInfo->version:"???",
715                                         engineInfo->req_version ? engineInfo->req_version:"???",
716                                         engineInfo->file_name ? engineInfo->file_name:"???");
717                                 if (engineInfo->protocol == GPGME_PROTOCOL_OpenPGP
718                                 &&  gpgme_engine_check_version(engineInfo->protocol) != 
719                                         GPG_ERR_NO_ERROR) {
720                                         if (engineInfo->file_name && !engineInfo->version) {
721                                                 alertpanel_error(_("Gpgme protocol '%s' is unusable: "
722                                                                    "Engine '%s' isn't installed properly."),
723                                                                    gpgme_get_protocol_name(engineInfo->protocol),
724                                                                    engineInfo->file_name);
725                                         } else if (engineInfo->file_name && engineInfo->version
726                                           && engineInfo->req_version) {
727                                                 alertpanel_error(_("Gpgme protocol '%s' is unusable: "
728                                                                    "Engine '%s' version %s is installed, "
729                                                                    "but version %s is required.\n"),
730                                                                    gpgme_get_protocol_name(engineInfo->protocol),
731                                                                    engineInfo->file_name,
732                                                                    engineInfo->version,
733                                                                    engineInfo->req_version);
734                                         } else {
735                                                 alertpanel_error(_("Gpgme protocol '%s' is unusable "
736                                                                    "(unknown problem)"),
737                                                                    gpgme_get_protocol_name(engineInfo->protocol));
738                                         }
739                                 }
740                                 engineInfo = engineInfo->next;
741                         }
742                 }
743         } else {
744                 sgpgme_disable_all();
745
746                 if (prefs_gpg_get_config()->gpg_warning) {
747                         AlertValue val;
748
749                         val = alertpanel_full
750                                 (_("Warning"),
751                                  _("GnuPG is not installed properly, or needs "
752                                  "to be upgraded.\n"
753                                  "OpenPGP support disabled."),
754                                  GTK_STOCK_CLOSE, NULL, NULL, TRUE, NULL,
755                                  ALERT_WARNING, G_ALERTDEFAULT);
756                         if (val & G_ALERTDISABLE)
757                                 prefs_gpg_get_config()->gpg_warning = FALSE;
758                 }
759         }
760 }
761
762 void sgpgme_done()
763 {
764         gpgmegtk_free_passphrase();
765 }
766
767 void sgpgme_create_secret_key(PrefsAccount *account, gboolean ask_create)
768 {
769         AlertValue val = G_ALERTDEFAULT;
770         gchar *key_parms = NULL;
771         gchar *name = NULL;
772         gchar *email = NULL;
773         gchar *passphrase = NULL, *passphrase_second = NULL;
774         gint prev_bad = 0;
775         gchar *tmp = NULL;
776         gpgme_error_t err = 0;
777         gpgme_ctx_t ctx;
778         GtkWidget *window = NULL;
779         gpgme_genkey_result_t key;
780
781         if (account == NULL)
782                 account = account_get_default();
783
784         if (account->address == NULL) {
785                 alertpanel_error(_("You have to save the account's information with \"OK\" "
786                                    "before being able to generate a key pair.\n"));
787                 return;
788         }
789         if (ask_create) {
790                 val = alertpanel(_("No PGP key found"),
791                                 _("Claws Mail did not find a secret PGP key, "
792                                   "which means that you won't be able to sign "
793                                   "emails or receive encrypted emails.\n"
794                                   "Do you want to create a new key pair now?"),
795                                   GTK_STOCK_NO, "+" GTK_STOCK_YES, NULL);
796                 if (val == G_ALERTDEFAULT) {
797                         prefs_gpg_get_config()->gpg_ask_create_key = FALSE;
798                         prefs_gpg_save_config();
799                         return;
800                 }
801         }
802
803         if (account->name) {
804                 name = g_strdup(account->name);
805         } else {
806                 name = g_strdup(account->address);
807         }
808         email = g_strdup(account->address);
809         tmp = g_strdup_printf("%s <%s>", account->name?account->name:account->address, account->address);
810 again:
811         passphrase = passphrase_mbox(tmp, NULL, prev_bad, 1);
812         if (passphrase == NULL) {
813                 g_free(tmp);
814                 g_free(email);
815                 g_free(name);           
816                 return;
817         }
818         passphrase_second = passphrase_mbox(tmp, NULL, 0, 2);
819         if (passphrase_second == NULL) {
820                 g_free(tmp);
821                 g_free(email);
822                 g_free(passphrase);             
823                 g_free(name);           
824                 return;
825         }
826         if (strcmp(passphrase, passphrase_second)) {
827                 g_free(passphrase);
828                 g_free(passphrase_second);
829                 prev_bad = 1;
830                 goto again;
831         }
832         
833         key_parms = g_strdup_printf("<GnupgKeyParms format=\"internal\">\n"
834                                         "Key-Type: RSA\n"
835                                         "Key-Length: 2048\n"
836                                         "Subkey-Type: RSA\n"
837                                         "Subkey-Length: 2048\n"
838                                         "Name-Real: %s\n"
839                                         "Name-Email: %s\n"
840                                         "Expire-Date: 0\n"
841                                         "%s%s%s"
842                                         "</GnupgKeyParms>\n",
843                                         name, email, 
844                                         strlen(passphrase)?"Passphrase: ":"",
845                                         passphrase,
846                                         strlen(passphrase)?"\n":"");
847 #ifndef G_PLATFORM_WIN32
848         if (mlock(passphrase, strlen(passphrase)) == -1)
849                 debug_print("couldn't lock passphrase\n");
850         if (mlock(passphrase_second, strlen(passphrase_second)) == -1)
851                 debug_print("couldn't lock passphrase2\n");
852 #endif
853         g_free(tmp);
854         g_free(email);
855         g_free(name);
856         g_free(passphrase_second);
857         g_free(passphrase);
858         
859         err = gpgme_new (&ctx);
860         if (err) {
861                 alertpanel_error(_("Couldn't generate a new key pair: %s"),
862                                  gpgme_strerror(err));
863                 g_free(key_parms);
864                 return;
865         }
866         
867
868         window = label_window_create(_("Generating your new key pair... Please move the mouse "
869                               "around to help generate entropy..."));
870
871         err = gpgme_op_genkey(ctx, key_parms, NULL, NULL);
872         g_free(key_parms);
873
874         label_window_destroy(window);
875
876         if (err) {
877                 alertpanel_error(_("Couldn't generate a new key pair: %s"), gpgme_strerror(err));
878                 gpgme_release(ctx);
879                 return;
880         }
881         key = gpgme_op_genkey_result(ctx);
882         if (key == NULL) {
883                 alertpanel_error(_("Couldn't generate a new key pair: unknown error"));
884                 gpgme_release(ctx);
885                 return;
886         } else {
887                 gchar *buf = g_strdup_printf(_("Your new key pair has been generated. "
888                                     "Its fingerprint is:\n%s\n\nDo you want to export it "
889                                     "to a keyserver?"),
890                                     key->fpr ? key->fpr:"null");
891                 AlertValue val = alertpanel(_("Key generated"), buf,
892                                   GTK_STOCK_NO, "+" GTK_STOCK_YES, NULL);
893                 g_free(buf);
894                 if (val == G_ALERTALTERNATE) {
895 #ifndef G_OS_WIN32
896                         gchar *cmd = g_strdup_printf("gpg --no-tty --send-keys %s", key->fpr);
897                         int res = 0;
898                         pid_t pid = 0;
899                         pid = fork();
900                         if (pid == -1) {
901                                 res = -1;
902                         } else if (pid == 0) {
903                                 /* son */
904                                 res = system(cmd);
905                                 res = WEXITSTATUS(res);
906                                 _exit(res);
907                         } else {
908                                 int status = 0;
909                                 time_t start_wait = time(NULL);
910                                 res = -1;
911                                 do {
912                                         if (waitpid(pid, &status, WNOHANG) == 0 || !WIFEXITED(status)) {
913                                                 usleep(200000);
914                                         } else {
915                                                 res = WEXITSTATUS(status);
916                                                 break;
917                                         }
918                                         if (time(NULL) - start_wait > 5) {
919                                                 debug_print("SIGTERM'ing gpg\n");
920                                                 kill(pid, SIGTERM);
921                                         }
922                                         if (time(NULL) - start_wait > 6) {
923                                                 debug_print("SIGKILL'ing gpg\n");
924                                                 kill(pid, SIGKILL);
925                                                 break;
926                                         }
927                                 } while(1);
928                         }
929                         if (res == 0) {
930                                 alertpanel_notice(_("Key exported."));
931                         } else {
932                                 alertpanel_error(_("Couldn't export key."));
933                         }
934                         g_free(cmd);
935 #else
936                         alertpanel_error(_("Key export isn't implemented in Windows."));
937 #endif
938                 }
939         }
940         prefs_gpg_get_config()->gpg_ask_create_key = FALSE;
941         prefs_gpg_save_config();
942         gpgme_release(ctx);
943 }
944
945 gboolean sgpgme_has_secret_key(void)
946 {
947         gpgme_error_t err = 0;
948         gpgme_ctx_t ctx;
949         gpgme_key_t key;
950
951         err = gpgme_new (&ctx);
952         if (err) {
953                 debug_print("err : %s\n", gpgme_strerror(err));
954                 return TRUE;
955         }
956 check_again:
957         err = gpgme_op_keylist_start(ctx, NULL, TRUE);
958         if (!err)
959                 err = gpgme_op_keylist_next(ctx, &key);
960         gpgme_op_keylist_end(ctx);
961         if (gpg_err_code(err) == GPG_ERR_EOF) {
962                 if (gpgme_get_protocol(ctx) != GPGME_PROTOCOL_CMS) {
963                         gpgme_set_protocol(ctx, GPGME_PROTOCOL_CMS);
964                         goto check_again;
965                 }
966                 gpgme_release(ctx);
967                 return FALSE;
968         } else {
969                 gpgme_release(ctx);
970                 return TRUE;
971         }
972 }
973
974 void sgpgme_check_create_key(void)
975 {
976         if (prefs_gpg_get_config()->gpg_ask_create_key &&
977             !sgpgme_has_secret_key()) {
978                 sgpgme_create_secret_key(NULL, TRUE);
979         } else {
980                 prefs_gpg_get_config()->gpg_ask_create_key = FALSE;
981                 prefs_gpg_save_config();
982         }       
983 }
984
985 void *sgpgme_data_release_and_get_mem(gpgme_data_t data, size_t *len)
986 {
987         char buf[BUFSIZ];
988         void *result = NULL;
989         ssize_t r = 0;
990         size_t w = 0;
991         
992         if (data == NULL)
993                 return NULL;
994         if (len == NULL)
995                 return NULL;
996
997         /* I know it's deprecated, but we don't compile with _LARGEFILE */
998         cm_gpgme_data_rewind(data);
999         while ((r = gpgme_data_read(data, buf, BUFSIZ)) > 0) {
1000                 void *rresult = realloc(result, r + w);
1001                 if (rresult == NULL) {
1002                         g_warning("can't allocate memory");
1003                         if (result != NULL)
1004                                 free(result);
1005                         return NULL;
1006                 }
1007                 result = rresult;
1008                 memcpy(result+w, buf, r);
1009                 w += r;
1010         }
1011         
1012         *len = w;
1013
1014         gpgme_data_release(data);
1015         if (r < 0) {
1016                 free(result);
1017                 *len = 0;
1018                 return NULL;
1019         }
1020         return result;
1021 }
1022
1023 gpgme_error_t cm_gpgme_data_rewind(gpgme_data_t dh)
1024 {
1025 #if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64
1026         if (gpgme_data_seek(dh, (off_t)0, SEEK_SET) == -1)
1027                 return gpg_error_from_errno(errno);
1028         else
1029                 return 0;
1030 #else
1031         return gpgme_data_rewind(dh);
1032 #endif
1033 }
1034
1035 #endif /* USE_GPGME */