2 * Claws Mail -- a GTK based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2022 the Claws Mail team
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.
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.
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/>.
21 #include "claws-features.h"
30 #include <glib/gi18n.h>
35 #include <sys/types.h>
37 # include <sys/wait.h>
42 #if (defined(__DragonFly__) || defined(SOLARIS) || defined (__NetBSD__) || defined (__FreeBSD__) || defined (__OpenBSD__))
43 # include <sys/signal.h>
54 #include "prefs_common.h"
56 #include "alertpanel.h"
57 #include "passphrase.h"
58 #include "prefs_gpg.h"
60 #include "select-keys.h"
62 #include "file-utils.h"
64 static void sgpgme_disable_all(void)
66 /* FIXME: set a flag, so that we don't bother the user with failed
70 void cm_free_detached_sig_task_data(gpointer data
)
72 DetachedSigTaskData
*task_data
= (DetachedSigTaskData
*)data
;
74 g_free(task_data
->boundary
);
75 g_free(task_data
->text_filename
);
76 g_free(task_data
->sig_filename
);
80 void cm_check_detached_sig(GTask
*task
,
81 gpointer source_object
,
83 GCancellable
*cancellable
)
85 DetachedSigTaskData
*task_data
= (DetachedSigTaskData
*)_task_data
;
90 gpgme_data_t textdata
= NULL
;
91 gpgme_data_t sigdata
= NULL
;
92 gpgme_verify_result_t gpgme_res
;
94 gboolean return_err
= TRUE
;
95 gboolean cancelled
= FALSE
;
96 SigCheckTaskResult
*task_result
= NULL
;
97 char err_str
[GPGERR_BUFSIZE
] = "";
99 domain
= g_quark_from_static_string("claws_pgpcore");
101 err
= gpgme_new(&ctx
);
102 if (err
!= GPG_ERR_NO_ERROR
) {
103 gpgme_strerror_r(err
, err_str
, GPGERR_BUFSIZE
);
104 g_warning("couldn't initialize GPG context: %s", err_str
);
108 err
= gpgme_set_protocol(ctx
, task_data
->protocol
);
109 if (err
!= GPG_ERR_NO_ERROR
) {
110 gpgme_strerror_r(err
, err_str
, GPGERR_BUFSIZE
);
111 g_warning("couldn't set GPG protocol: %s", err_str
);
115 fp
= claws_fopen(task_data
->text_filename
, "rb");
117 err
= GPG_ERR_GENERAL
;
118 g_snprintf(err_str
, GPGERR_BUFSIZE
, "claws_fopen failed");
122 textstr
= task_data
->get_canonical_content(fp
, task_data
->boundary
);
125 err
= gpgme_data_new_from_mem(&textdata
, textstr
, textstr
?strlen(textstr
):0, 0);
126 if (err
!= GPG_ERR_NO_ERROR
) {
127 gpgme_strerror_r(err
, err_str
, GPGERR_BUFSIZE
);
128 g_warning("gpgme_data_new_from_mem failed: %s", err_str
);
132 fp
= claws_fopen(task_data
->sig_filename
, "rb");
134 err
= GPG_ERR_GENERAL
;
135 g_snprintf(err_str
, GPGERR_BUFSIZE
, "claws_fopen failed");
139 err
= gpgme_data_new_from_filepart(&sigdata
, NULL
, fp
, task_data
->sig_offset
, task_data
->sig_length
);
141 if (err
!= GPG_ERR_NO_ERROR
) {
142 gpgme_strerror_r(err
, err_str
, GPGERR_BUFSIZE
);
143 g_warning("gpgme_data_new_from_filepart failed: %s", err_str
);
147 if (task_data
->sig_encoding
== ENC_BASE64
) {
148 err
= gpgme_data_set_encoding(sigdata
, GPGME_DATA_ENCODING_BASE64
);
149 if (err
!= GPG_ERR_NO_ERROR
) {
150 gpgme_strerror_r(err
, err_str
, GPGERR_BUFSIZE
);
151 g_warning("gpgme_data_set_encoding failed: %s\n", err_str
);
156 if (g_task_return_error_if_cancelled(task
)) {
157 debug_print("task was cancelled, aborting task:%p\n", task
);
162 err
= gpgme_op_verify(ctx
, sigdata
, textdata
, NULL
);
163 if (err
!= GPG_ERR_NO_ERROR
) {
164 gpgme_strerror_r(err
, err_str
, GPGERR_BUFSIZE
);
165 g_warning("gpgme_op_verify failed: %s\n", err_str
);
169 if (g_task_return_error_if_cancelled(task
)) {
170 debug_print("task was cancelled, aborting task:%p\n", task
);
175 gpgme_res
= gpgme_op_verify_result(ctx
);
176 if (gpgme_res
&& gpgme_res
->signatures
== NULL
) {
177 err
= GPG_ERR_SYSTEM_ERROR
;
178 g_warning("no signature found");
179 g_snprintf(err_str
, GPGERR_BUFSIZE
, "No signature found");
183 task_result
= g_new0(SigCheckTaskResult
, 1);
184 task_result
->sig_data
= g_new0(SignatureData
, 1);
186 task_result
->sig_data
->status
= sgpgme_sigstat_gpgme_to_privacy(ctx
, gpgme_res
);
187 task_result
->sig_data
->info_short
= sgpgme_sigstat_info_short(ctx
, gpgme_res
);
188 task_result
->sig_data
->info_full
= sgpgme_sigstat_info_full(ctx
, gpgme_res
);
193 gpgme_data_release(sigdata
);
195 gpgme_data_release(textdata
);
205 g_task_return_new_error(task
, domain
, err
, "%s", err_str
);
207 g_task_return_pointer(task
, task_result
, privacy_free_sig_check_task_result
);
210 gint
cm_check_detached_sig_async(MimeInfo
*mimeinfo
,
211 GCancellable
*cancellable
,
212 GAsyncReadyCallback callback
,
214 gpgme_protocol_t protocol
,
215 gchar
*(*get_canonical_content
)(FILE *, const gchar
*))
218 DetachedSigTaskData
*task_data
;
223 parent
= procmime_mimeinfo_parent(mimeinfo
);
225 boundary
= g_hash_table_lookup(parent
->typeparameters
, "boundary");
226 if (boundary
== NULL
) {
227 debug_print("failed to lookup boundary string\n");
231 signature
= (MimeInfo
*) mimeinfo
->node
->next
->data
;
233 task_data
= g_new0(DetachedSigTaskData
, 1);
235 task_data
->protocol
= protocol
;
236 task_data
->boundary
= g_strdup(boundary
);
237 task_data
->text_filename
= g_strdup(parent
->data
.filename
);
238 task_data
->sig_filename
= g_strdup(signature
->data
.filename
);
239 task_data
->sig_offset
= signature
->offset
;
240 task_data
->sig_length
= signature
->length
;
241 task_data
->sig_encoding
= signature
->encoding_type
;
242 task_data
->get_canonical_content
= get_canonical_content
;
244 task
= g_task_new(NULL
, cancellable
, callback
, user_data
);
245 mimeinfo
->last_sig_check_task
= task
;
247 g_task_set_task_data(task
, task_data
, cm_free_detached_sig_task_data
);
248 debug_print("creating check sig async task:%p task_data:%p\n", task
, task_data
);
249 g_task_set_return_on_cancel(task
, TRUE
);
250 g_task_run_in_thread(task
, cm_check_detached_sig
);
251 g_object_unref(task
);
256 gpgme_verify_result_t
sgpgme_verify_signature(gpgme_ctx_t ctx
, gpgme_data_t sig
,
257 gpgme_data_t plain
, gpgme_data_t dummy
)
259 gpgme_verify_result_t status
= NULL
;
262 if ((err
= gpgme_op_verify(ctx
, sig
, plain
, dummy
)) != GPG_ERR_NO_ERROR
) {
263 debug_print("op_verify err %s\n", gpgme_strerror(err
));
264 privacy_set_error("%s", gpgme_strerror(err
));
265 return GINT_TO_POINTER(-GPG_ERR_SYSTEM_ERROR
);
267 status
= gpgme_op_verify_result(ctx
);
268 if (status
&& status
->signatures
== NULL
) {
269 debug_print("no signature found\n");
270 privacy_set_error(_("No signature found"));
271 return GINT_TO_POINTER(-GPG_ERR_SYSTEM_ERROR
);
276 SignatureStatus
sgpgme_sigstat_gpgme_to_privacy(gpgme_ctx_t ctx
, gpgme_verify_result_t status
)
278 gpgme_signature_t sig
= NULL
;
280 if (GPOINTER_TO_INT(status
) == -GPG_ERR_SYSTEM_ERROR
) {
281 debug_print("system error\n");
282 return SIGNATURE_CHECK_FAILED
;
285 if (status
== NULL
) {
286 debug_print("status == NULL\n");
287 return SIGNATURE_UNCHECKED
;
289 sig
= status
->signatures
;
292 debug_print("sig == NULL\n");
293 return SIGNATURE_UNCHECKED
;
296 debug_print("err code %d\n", gpg_err_code(sig
->status
));
297 switch (gpg_err_code(sig
->status
)) {
298 case GPG_ERR_NO_ERROR
:
299 switch (sig
->validity
) {
300 case GPGME_VALIDITY_NEVER
:
301 return SIGNATURE_INVALID
;
302 case GPGME_VALIDITY_UNKNOWN
:
303 case GPGME_VALIDITY_UNDEFINED
:
304 case GPGME_VALIDITY_MARGINAL
:
305 case GPGME_VALIDITY_FULL
:
306 case GPGME_VALIDITY_ULTIMATE
:
309 return SIGNATURE_CHECK_FAILED
;
311 case GPG_ERR_SIG_EXPIRED
:
312 case GPG_ERR_CERT_REVOKED
:
313 return SIGNATURE_WARN
;
314 case GPG_ERR_KEY_EXPIRED
:
315 return SIGNATURE_KEY_EXPIRED
;
316 case GPG_ERR_BAD_SIGNATURE
:
317 return SIGNATURE_INVALID
;
318 case GPG_ERR_NO_PUBKEY
:
319 return SIGNATURE_CHECK_FAILED
;
321 return SIGNATURE_CHECK_FAILED
;
323 return SIGNATURE_CHECK_FAILED
;
326 static const gchar
*get_validity_str(unsigned long validity
)
328 switch (gpg_err_code(validity
)) {
329 case GPGME_VALIDITY_UNKNOWN
:
331 case GPGME_VALIDITY_UNDEFINED
:
332 return _("Undefined");
333 case GPGME_VALIDITY_NEVER
:
335 case GPGME_VALIDITY_MARGINAL
:
336 return _("Marginal");
337 case GPGME_VALIDITY_FULL
:
339 case GPGME_VALIDITY_ULTIMATE
:
340 return _("Ultimate");
346 static const gchar
*get_owner_trust_str(unsigned long owner_trust
)
348 switch (gpgme_err_code(owner_trust
)) {
349 case GPGME_VALIDITY_NEVER
:
350 return _("Untrusted");
351 case GPGME_VALIDITY_MARGINAL
:
352 return _("Marginal");
353 case GPGME_VALIDITY_FULL
:
355 case GPGME_VALIDITY_ULTIMATE
:
356 return _("Ultimate");
362 gchar
*get_gpg_executable_name()
364 gpgme_engine_info_t e
;
366 if (!gpgme_get_engine_info(&e
)) {
368 if (e
->protocol
== GPGME_PROTOCOL_OpenPGP
369 && e
->file_name
!= NULL
) {
370 debug_print("Found gpg executable: '%s'\n", e
->file_name
);
379 static gchar
*get_gpg_version_string()
381 gpgme_engine_info_t e
;
383 if (!gpgme_get_engine_info(&e
)) {
385 if (e
->protocol
== GPGME_PROTOCOL_OpenPGP
386 && e
->version
!= NULL
) {
387 debug_print("Got OpenPGP version: '%s'\n", e
->version
);
396 static gchar
*extract_name(const char *uid
)
400 if (!strncmp(uid
, "CN=", 3)) {
401 gchar
*result
= g_strdup(uid
+3);
402 if (strstr(result
, ","))
403 *(strstr(result
, ",")) = '\0';
405 } else if (strstr(uid
, ",CN=")) {
406 gchar
*result
= g_strdup(strstr(uid
, ",CN=")+4);
407 if (strstr(result
, ","))
408 *(strstr(result
, ",")) = '\0';
411 return g_strdup(uid
);
414 gchar
*sgpgme_sigstat_info_short(gpgme_ctx_t ctx
, gpgme_verify_result_t status
)
416 gpgme_signature_t sig
= NULL
;
419 gchar
*result
= NULL
;
420 gpgme_error_t err
= 0;
421 static gboolean warned
= FALSE
;
423 if (GPOINTER_TO_INT(status
) == -GPG_ERR_SYSTEM_ERROR
) {
424 return g_strdup_printf(_("The signature can't be checked - %s"), privacy_get_error());
427 if (status
== NULL
) {
428 return g_strdup(_("The signature has not been checked."));
430 sig
= status
->signatures
;
432 return g_strdup(_("The signature has not been checked."));
435 err
= gpgme_get_key(ctx
, sig
->fpr
, &key
, 0);
436 if (gpg_err_code(err
) == GPG_ERR_NO_AGENT
) {
438 alertpanel_error(_("PGP Core: Can't get key - no gpg-agent running."));
440 g_warning("PGP Core: can't get key - no gpg-agent running");
442 } else if (gpg_err_code(err
) != GPG_ERR_NO_ERROR
&& gpg_err_code(err
) != GPG_ERR_EOF
) {
443 return g_strdup_printf(_("The signature can't be checked - %s"),
444 gpgme_strerror(err
));
448 uname
= extract_name(key
->uids
->uid
);
450 uname
= g_strdup("<?>");
452 switch (gpg_err_code(sig
->status
)) {
453 case GPG_ERR_NO_ERROR
:
454 switch ((key
&& key
->uids
) ? key
->uids
->validity
: GPGME_VALIDITY_UNKNOWN
) {
455 case GPGME_VALIDITY_ULTIMATE
:
456 result
= g_strdup_printf(_("Good signature from \"%s\" [ultimate]"), uname
);
458 case GPGME_VALIDITY_FULL
:
459 result
= g_strdup_printf(_("Good signature from \"%s\" [full]"), uname
);
461 case GPGME_VALIDITY_MARGINAL
:
462 result
= g_strdup_printf(_("Good signature from \"%s\" [marginal]"), uname
);
464 case GPGME_VALIDITY_UNKNOWN
:
465 case GPGME_VALIDITY_UNDEFINED
:
466 case GPGME_VALIDITY_NEVER
:
469 result
= g_strdup_printf(_("Good signature from \"%s\""), uname
);
471 result
= g_strdup_printf(_("Key 0x%s not available to verify this signature"), sig
->fpr
);
476 case GPG_ERR_SIG_EXPIRED
:
477 result
= g_strdup_printf(_("Expired signature from \"%s\""), uname
);
479 case GPG_ERR_KEY_EXPIRED
:
480 result
= g_strdup_printf(_("Good signature from \"%s\", but the key has expired"), uname
);
482 case GPG_ERR_CERT_REVOKED
:
483 result
= g_strdup_printf(_("Good signature from \"%s\", but the key has been revoked"), uname
);
485 case GPG_ERR_BAD_SIGNATURE
:
486 result
= g_strdup_printf(_("Bad signature from \"%s\""), uname
);
488 case GPG_ERR_NO_PUBKEY
: {
489 result
= g_strdup_printf(_("Key 0x%s not available to verify this signature"), sig
->fpr
);
493 result
= g_strdup(_("The signature has not been checked"));
497 result
= g_strdup(_("Error"));
501 gpgme_key_unref(key
);
506 gchar
*sgpgme_sigstat_info_full(gpgme_ctx_t ctx
, gpgme_verify_result_t status
)
511 gpgme_signature_t sig
= NULL
;
513 siginfo
= g_string_sized_new(64);
514 if (status
== NULL
) {
515 g_string_append_printf(siginfo
,
516 _("Error checking signature: no status\n"));
520 sig
= status
->signatures
;
528 const gchar
*keytype
, *keyid
, *uid
;
530 err
= gpgme_get_key(ctx
, sig
->fpr
, &key
, 0);
532 if (err
!= GPG_ERR_NO_ERROR
) {
534 g_string_append_printf(siginfo
,
535 _("Error checking signature: %s\n"),
536 gpgme_strerror(err
));
540 keytype
= gpgme_pubkey_algo_name(
541 key
->subkeys
->pubkey_algo
);
542 keyid
= key
->subkeys
->keyid
;
543 uid
= key
->uids
->uid
;
550 memset(buf
, 0, sizeof(buf
));
551 fast_strftime(buf
, sizeof(buf
)-1, prefs_common_get_prefs()->date_format
, localtime_r((time_t *)&sig
->timestamp
, <
));
552 g_string_append_printf(siginfo
,
553 _("Signature made on %s using %s key ID %s\n"),
554 buf
, keytype
, keyid
);
556 switch (gpg_err_code(sig
->status
)) {
557 case GPG_ERR_NO_ERROR
:
558 g_string_append_printf(siginfo
,
559 _("Good signature from uid \"%s\" (Validity: %s)\n"),
560 uid
, get_validity_str((key
&& key
->uids
) ? key
->uids
->validity
:GPGME_VALIDITY_UNKNOWN
));
562 case GPG_ERR_KEY_EXPIRED
:
563 g_string_append_printf(siginfo
,
564 _("Expired key uid \"%s\"\n"),
567 case GPG_ERR_SIG_EXPIRED
:
568 g_string_append_printf(siginfo
,
569 _("Expired signature from uid \"%s\" (Validity: %s)\n"),
570 uid
, get_validity_str((key
&& key
->uids
) ? key
->uids
->validity
:GPGME_VALIDITY_UNKNOWN
));
572 case GPG_ERR_CERT_REVOKED
:
573 g_string_append_printf(siginfo
,
574 _("Revoked key uid \"%s\"\n"),
577 case GPG_ERR_BAD_SIGNATURE
:
578 g_string_append_printf(siginfo
,
579 _("BAD signature from \"%s\"\n"),
585 if (sig
->status
!= GPG_ERR_BAD_SIGNATURE
) {
588 tmp
= key
->uids
? key
->uids
->next
: NULL
;
589 while (tmp
!= NULL
) {
590 g_string_append_printf(siginfo
,
591 _(" uid \"%s\" (Validity: %s)\n"),
593 tmp
->revoked
==TRUE
?_("Revoked"):get_validity_str(tmp
->validity
));
598 g_string_append_printf(siginfo
,_("Owner Trust: %s\n"),
599 key
? get_owner_trust_str(key
->owner_trust
) : _("No key!"));
600 g_string_append(siginfo
,
601 _("Primary key fingerprint:"));
602 const char* primary_fpr
= NULL
;
603 if (key
&& key
->subkeys
&& key
->subkeys
->fpr
)
604 primary_fpr
= key
->subkeys
->fpr
;
606 g_string_append(siginfo
, " ?");
607 int idx
; /* now pretty-print the fingerprint */
608 for (idx
=0; primary_fpr
&& *primary_fpr
!='\0'; idx
++, primary_fpr
++) {
610 g_string_append_c(siginfo
, ' ');
612 g_string_append_c(siginfo
, ' ');
613 g_string_append_c(siginfo
, (gchar
)*primary_fpr
);
615 g_string_append_c(siginfo
, '\n');
617 if (sig
->pka_trust
== 1 && sig
->pka_address
) {
618 g_string_append_printf(siginfo
,
619 _("WARNING: Signer's address \"%s\" "
620 "does not match DNS entry\n"),
623 else if (sig
->pka_trust
== 2 && sig
->pka_address
) {
624 g_string_append_printf(siginfo
,
625 _("Verified signer's address is \"%s\"\n"),
627 /* FIXME: Compare the address to the
632 g_string_append(siginfo
, "\n");
635 gpgme_key_unref(key
);
639 g_string_free(siginfo
, FALSE
);
643 gpgme_data_t
sgpgme_data_from_mimeinfo(MimeInfo
*mimeinfo
)
645 gpgme_data_t data
= NULL
;
647 FILE *fp
= claws_fopen(mimeinfo
->data
.filename
, "rb");
652 err
= gpgme_data_new_from_filepart(&data
, NULL
, fp
, mimeinfo
->offset
, mimeinfo
->length
);
655 debug_print("data %p (%d %d)\n", (void *)&data
, mimeinfo
->offset
, mimeinfo
->length
);
657 debug_print ("gpgme_data_new_from_file failed: %s\n",
658 gpgme_strerror (err
));
659 privacy_set_error(_("Couldn't get data from message, %s"), gpgme_strerror(err
));
665 gpgme_data_t
sgpgme_decrypt_verify(gpgme_data_t cipher
, gpgme_verify_result_t
*status
, gpgme_ctx_t ctx
)
667 struct passphrase_cb_info_s info
;
671 memset (&info
, 0, sizeof info
);
673 if ((err
= gpgme_data_new(&plain
)) != GPG_ERR_NO_ERROR
) {
675 privacy_set_error(_("Couldn't initialize data, %s"), gpgme_strerror(err
));
679 if (gpgme_get_protocol(ctx
) == GPGME_PROTOCOL_OpenPGP
) {
680 prefs_gpg_enable_agent(prefs_gpg_get_config()->use_gpg_agent
);
681 if (!g_getenv("GPG_AGENT_INFO") || !prefs_gpg_get_config()->use_gpg_agent
) {
683 gpgme_set_passphrase_cb (ctx
, gpgmegtk_passphrase_cb
, &info
);
686 prefs_gpg_enable_agent(TRUE
);
688 gpgme_set_passphrase_cb (ctx
, NULL
, &info
);
692 if (gpgme_get_protocol(ctx
) == GPGME_PROTOCOL_OpenPGP
) {
693 err
= gpgme_op_decrypt_verify(ctx
, cipher
, plain
);
694 if (err
!= GPG_ERR_NO_ERROR
) {
695 debug_print("can't decrypt (%s)\n", gpgme_strerror(err
));
696 privacy_set_error("%s", gpgme_strerror(err
));
697 gpgmegtk_free_passphrase();
698 gpgme_data_release(plain
);
702 err
= cm_gpgme_data_rewind(plain
);
704 debug_print("can't seek (%d %d %s)\n", err
, errno
, g_strerror(errno
));
707 debug_print("decrypted.\n");
708 *status
= gpgme_op_verify_result (ctx
);
710 err
= gpgme_op_decrypt(ctx
, cipher
, plain
);
711 if (err
!= GPG_ERR_NO_ERROR
) {
712 debug_print("can't decrypt (%s)\n", gpgme_strerror(err
));
713 privacy_set_error("%s", gpgme_strerror(err
));
714 gpgmegtk_free_passphrase();
715 gpgme_data_release(plain
);
719 err
= cm_gpgme_data_rewind(plain
);
721 debug_print("can't seek (%d %d %s)\n", err
, errno
, g_strerror(errno
));
724 debug_print("decrypted.\n");
725 *status
= gpgme_op_verify_result (ctx
);
730 gchar
*sgpgme_get_encrypt_data(GSList
*recp_names
, gpgme_protocol_t proto
)
732 SelectionResult result
= KEY_SELECTION_CANCEL
;
733 gpgme_key_t
*keys
= gpgmegtk_recipient_selection(recp_names
, &result
,
739 if (result
== KEY_SELECTION_DONT
)
740 return g_strdup("_DONT_ENCRYPT_");
745 gpgme_subkey_t skey
= keys
[i
]->subkeys
;
746 gchar
*fpr
= skey
->fpr
;
748 debug_print("adding %s\n", fpr
);
749 tmp
= g_strconcat(ret
? ret
: "", fpr
, " ", NULL
);
759 gboolean
sgpgme_setup_signers(gpgme_ctx_t ctx
, PrefsAccount
*account
,
760 const gchar
*from_addr
)
762 GPGAccountConfig
*config
;
763 const gchar
*signer_addr
= account
->address
;
766 gboolean smime
= FALSE
;
768 gpgme_signers_clear(ctx
);
770 if (gpgme_get_protocol(ctx
) == GPGME_PROTOCOL_CMS
)
774 signer_addr
= from_addr
;
775 config
= prefs_gpg_account_get_config(account
);
778 debug_print("sgpgme_setup_signers: S/MIME protocol\n");
779 sk
= config
->smime_sign_key
;
780 skid
= config
->smime_sign_key_id
;
782 debug_print("sgpgme_setup_signers: OpenPGP protocol\n");
783 sk
= config
->sign_key
;
784 skid
= config
->sign_key_id
;
788 case SIGN_KEY_DEFAULT
:
789 debug_print("using default gnupg key\n");
791 case SIGN_KEY_BY_FROM
:
792 debug_print("using key for %s\n", signer_addr
);
794 case SIGN_KEY_CUSTOM
:
795 debug_print("using key for %s\n", skid
);
799 if (sk
!= SIGN_KEY_DEFAULT
) {
801 gpgme_key_t key
, found_key
;
804 if (sk
== SIGN_KEY_BY_FROM
)
806 else if (sk
== SIGN_KEY_CUSTOM
)
812 /* Look for any key, not just private ones, or GPGMe doesn't
813 * correctly set the revoked flag. */
814 err
= gpgme_op_keylist_start(ctx
, keyid
, 0);
816 if ((err
= gpgme_op_keylist_next(ctx
, &key
)) != 0)
822 if (!key
->can_sign
) {
823 debug_print("skipping a key, can not be used for signing\n");
824 gpgme_key_unref(key
);
828 if (key
->protocol
!= gpgme_get_protocol(ctx
)) {
829 debug_print("skipping a key (wrong protocol %d)\n", key
->protocol
);
830 gpgme_key_unref(key
);
835 debug_print("skipping a key, expired\n");
836 gpgme_key_unref(key
);
840 debug_print("skipping a key, revoked\n");
841 gpgme_key_unref(key
);
845 debug_print("skipping a key, disabled\n");
846 gpgme_key_unref(key
);
850 if (found_key
!= NULL
) {
851 gpgme_key_unref(key
);
852 gpgme_op_keylist_end(ctx
);
853 g_warning("ambiguous specification of secret key '%s'", keyid
);
854 privacy_set_error(_("Secret key specification is ambiguous"));
860 gpgme_op_keylist_end(ctx
);
862 if (found_key
== NULL
) {
863 g_warning("setup_signers start: %s", gpgme_strerror(err
));
864 privacy_set_error(_("Secret key not found (%s)"), gpgme_strerror(err
));
868 err
= gpgme_signers_add(ctx
, found_key
);
869 debug_print("got key (proto %d (pgp %d, smime %d).\n",
870 found_key
->protocol
, GPGME_PROTOCOL_OpenPGP
,
872 gpgme_key_unref(found_key
);
875 g_warning("error adding secret key: %s",
876 gpgme_strerror(err
));
877 privacy_set_error(_("Error setting secret key: %s"),
878 gpgme_strerror(err
));
883 prefs_gpg_account_free_config(config
);
887 prefs_gpg_account_free_config(config
);
893 gchar
*ctype_locale
= NULL
, *messages_locale
= NULL
;
894 gchar
*ctype_utf8_locale
= NULL
, *messages_utf8_locale
= NULL
;
895 gpgme_error_t err
= 0;
897 gpgme_engine_info_t engineInfo
;
899 if (strcmp(prefs_gpg_get_config()->gpg_path
, "") != 0
900 && access(prefs_gpg_get_config()->gpg_path
, X_OK
) != -1) {
901 err
= gpgme_set_engine_info(GPGME_PROTOCOL_OpenPGP
, prefs_gpg_get_config()->gpg_path
, NULL
);
902 if (err
!= GPG_ERR_NO_ERROR
)
903 g_warning("failed to set crypto engine configuration: %s", gpgme_strerror(err
));
906 if (gpgme_check_version("1.0.0")) {
908 debug_print("setting gpgme CTYPE locale\n");
910 ctype_locale
= g_win32_getlocale();
912 ctype_locale
= g_strdup(setlocale(LC_CTYPE
, NULL
));
915 debug_print("setting gpgme CTYPE locale to: %s\n", ctype_locale
);
916 if (strchr(ctype_locale
, '.'))
917 *(strchr(ctype_locale
, '.')) = '\0';
918 else if (strchr(ctype_locale
, '@'))
919 *(strchr(ctype_locale
, '@')) = '\0';
920 ctype_utf8_locale
= g_strconcat(ctype_locale
, ".UTF-8", NULL
);
922 debug_print("setting gpgme locale to UTF8: %s\n", ctype_utf8_locale
? ctype_utf8_locale
: "NULL");
923 gpgme_set_locale(NULL
, LC_CTYPE
, ctype_utf8_locale
);
925 debug_print("done\n");
926 g_free(ctype_utf8_locale
);
927 g_free(ctype_locale
);
929 debug_print("couldn't set gpgme CTYPE locale\n");
933 debug_print("setting gpgme MESSAGES locale\n");
935 messages_locale
= g_win32_getlocale();
937 messages_locale
= g_strdup(setlocale(LC_MESSAGES
, NULL
));
939 if (messages_locale
) {
940 debug_print("setting gpgme MESSAGES locale to: %s\n", messages_locale
);
941 if (strchr(messages_locale
, '.'))
942 *(strchr(messages_locale
, '.')) = '\0';
943 else if (strchr(messages_locale
, '@'))
944 *(strchr(messages_locale
, '@')) = '\0';
945 messages_utf8_locale
= g_strconcat(messages_locale
, ".UTF-8", NULL
);
946 debug_print("setting gpgme locale to UTF8: %s\n", messages_utf8_locale
? messages_utf8_locale
: "NULL");
948 gpgme_set_locale(NULL
, LC_MESSAGES
, messages_utf8_locale
);
950 debug_print("done\n");
951 g_free(messages_utf8_locale
);
952 g_free(messages_locale
);
954 debug_print("couldn't set gpgme MESSAGES locale\n");
957 if (!gpgme_get_engine_info(&engineInfo
)) {
959 debug_print("GpgME Protocol: %s\n"
960 "Version: %s (req %s)\n"
962 gpgme_get_protocol_name(engineInfo
->protocol
) ? gpgme_get_protocol_name(engineInfo
->protocol
):"???",
963 engineInfo
->version
? engineInfo
->version
:"???",
964 engineInfo
->req_version
? engineInfo
->req_version
:"???",
965 engineInfo
->file_name
? engineInfo
->file_name
:"???");
966 if (engineInfo
->protocol
== GPGME_PROTOCOL_OpenPGP
967 && gpgme_engine_check_version(engineInfo
->protocol
) !=
969 if (engineInfo
->file_name
&& !engineInfo
->version
) {
970 alertpanel_error(_("Gpgme protocol '%s' is unusable: "
971 "Engine '%s' isn't installed properly."),
972 gpgme_get_protocol_name(engineInfo
->protocol
),
973 engineInfo
->file_name
);
974 } else if (engineInfo
->file_name
&& engineInfo
->version
975 && engineInfo
->req_version
) {
976 alertpanel_error(_("Gpgme protocol '%s' is unusable: "
977 "Engine '%s' version %s is installed, "
978 "but version %s is required.\n"),
979 gpgme_get_protocol_name(engineInfo
->protocol
),
980 engineInfo
->file_name
,
982 engineInfo
->req_version
);
984 alertpanel_error(_("Gpgme protocol '%s' is unusable "
985 "(unknown problem)"),
986 gpgme_get_protocol_name(engineInfo
->protocol
));
989 engineInfo
= engineInfo
->next
;
993 sgpgme_disable_all();
995 if (prefs_gpg_get_config()->gpg_warning
) {
998 val
= alertpanel_full
1000 _("GnuPG is not installed properly, or needs "
1002 "OpenPGP support disabled."),
1003 "window-close", _("_Close"), NULL
, NULL
, NULL
, NULL
,
1004 ALERTFOCUS_FIRST
, TRUE
, NULL
, ALERT_WARNING
);
1005 if (val
& G_ALERTDISABLE
)
1006 prefs_gpg_get_config()->gpg_warning
= FALSE
;
1013 gpgmegtk_free_passphrase();
1023 static void *_export_threaded(void *arg
)
1025 struct _ExportCtx
*ctx
= (struct _ExportCtx
*)arg
;
1028 PROCESS_INFORMATION pi
= {0};
1029 STARTUPINFO si
= {0};
1031 result
= CreateProcess(NULL
, ctx
->cmd
, NULL
, NULL
, FALSE
,
1032 NORMAL_PRIORITY_CLASS
| CREATE_NO_WINDOW
,
1033 NULL
, NULL
, &si
, &pi
);
1036 debug_print("Couldn't execute '%s'\n", ctx
->cmd
);
1038 WaitForSingleObject(pi
.hProcess
, 10000);
1039 result
= GetExitCodeProcess(pi
.hProcess
, &ctx
->exitcode
);
1040 if (ctx
->exitcode
== STILL_ACTIVE
) {
1041 debug_print("Process still running, terminating it.\n");
1042 TerminateProcess(pi
.hProcess
, 255);
1045 CloseHandle(pi
.hProcess
);
1046 CloseHandle(pi
.hThread
);
1049 debug_print("Process executed, but we couldn't get its exit code (huh?)\n");
1058 void sgpgme_create_secret_key(PrefsAccount
*account
, gboolean ask_create
)
1060 AlertValue val
= G_ALERTDEFAULT
;
1061 gchar
*key_parms
= NULL
;
1063 gchar
*email
= NULL
;
1064 gchar
*passphrase
= NULL
, *passphrase_second
= NULL
;
1066 gchar
*tmp
= NULL
, *gpgver
;
1067 gpgme_error_t err
= 0;
1069 GtkWidget
*window
= NULL
;
1070 gpgme_genkey_result_t key
;
1071 gboolean exported
= FALSE
;
1073 if (account
== NULL
)
1074 account
= account_get_default();
1076 if (account
->address
== NULL
) {
1077 alertpanel_error(_("You have to save the account's information with \"OK\" "
1078 "before being able to generate a key pair.\n"));
1082 val
= alertpanel(_("No PGP key found"),
1083 _("Claws Mail did not find a secret PGP key, "
1084 "which means that you won't be able to sign "
1085 "emails or receive encrypted emails.\n"
1086 "Do you want to create a new key pair now?"),
1087 NULL
, _("_No"), NULL
, _("_Yes"), NULL
, NULL
,
1089 if (val
== G_ALERTDEFAULT
) {
1094 if (account
->name
) {
1095 name
= g_strdup(account
->name
);
1097 name
= g_strdup(account
->address
);
1099 email
= g_strdup(account
->address
);
1100 tmp
= g_strdup_printf("%s <%s>", account
->name
?account
->name
:account
->address
, account
->address
);
1101 gpgver
= get_gpg_version_string();
1102 if (gpgver
== NULL
|| !strncmp(gpgver
, "1.", 2)) {
1103 debug_print("Using gpg 1.x, using builtin passphrase dialog.\n");
1105 passphrase
= passphrase_mbox(tmp
, NULL
, prev_bad
, 1);
1106 if (passphrase
== NULL
) {
1112 passphrase_second
= passphrase_mbox(tmp
, NULL
, 0, 2);
1113 if (passphrase_second
== NULL
) {
1116 if (passphrase
!= NULL
) {
1117 memset(passphrase
, 0, strlen(passphrase
));
1123 if (strcmp(passphrase
, passphrase_second
)) {
1124 if (passphrase
!= NULL
) {
1125 memset(passphrase
, 0, strlen(passphrase
));
1128 if (passphrase_second
!= NULL
) {
1129 memset(passphrase_second
, 0, strlen(passphrase_second
));
1130 g_free(passphrase_second
);
1137 key_parms
= g_strdup_printf("<GnupgKeyParms format=\"internal\">\n"
1139 "Key-Length: 2048\n"
1140 "Subkey-Type: RSA\n"
1141 "Subkey-Length: 2048\n"
1146 "</GnupgKeyParms>\n",
1148 passphrase
?"Passphrase: ":"",
1149 passphrase
?passphrase
:"",
1150 passphrase
?"\n":"");
1151 #ifndef G_PLATFORM_WIN32
1153 mlock(passphrase
, strlen(passphrase
)) == -1)
1154 debug_print("couldn't lock passphrase\n");
1155 if (passphrase_second
&&
1156 mlock(passphrase_second
, strlen(passphrase_second
)) == -1)
1157 debug_print("couldn't lock passphrase2\n");
1162 if (passphrase_second
!= NULL
) {
1163 memset(passphrase_second
, 0, strlen(passphrase_second
));
1164 g_free(passphrase_second
);
1166 if (passphrase
!= NULL
) {
1167 memset(passphrase
, 0, strlen(passphrase
));
1171 err
= gpgme_new (&ctx
);
1173 alertpanel_error(_("Couldn't generate a new key pair: %s"),
1174 gpgme_strerror(err
));
1175 if (key_parms
!= NULL
) {
1176 memset(key_parms
, 0, strlen(key_parms
));
1183 window
= label_window_create(_("Generating your new key pair... Please move the mouse "
1184 "around to help generate entropy..."));
1186 err
= gpgme_op_genkey(ctx
, key_parms
, NULL
, NULL
);
1187 if (key_parms
!= NULL
) {
1188 memset(key_parms
, 0, strlen(key_parms
));
1192 label_window_destroy(window
);
1195 alertpanel_error(_("Couldn't generate a new key pair: %s"), gpgme_strerror(err
));
1199 key
= gpgme_op_genkey_result(ctx
);
1201 alertpanel_error(_("Couldn't generate a new key pair: unknown error"));
1205 gchar
*buf
= g_strdup_printf(_("Your new key pair has been generated. "
1206 "Its fingerprint is:\n%s\n\nDo you want to export it "
1208 key
->fpr
? key
->fpr
:"null");
1209 AlertValue val
= alertpanel(_("Key generated"), buf
,
1210 NULL
, _("_No"), NULL
, _("_Yes"), NULL
, NULL
, ALERTFOCUS_SECOND
);
1212 if (val
== G_ALERTALTERNATE
) {
1213 gchar
*gpgbin
= get_gpg_executable_name();
1214 gchar
*cmd
= g_strdup_printf("\"%s\" --batch --no-tty --send-keys %s",
1215 (gpgbin
? gpgbin
: "gpg"), key
->fpr
);
1216 debug_print("Executing command: %s\n", cmd
);
1224 } else if (pid
== 0) {
1227 res
= WEXITSTATUS(res
);
1231 time_t start_wait
= time(NULL
);
1234 if (waitpid(pid
, &status
, WNOHANG
) == 0 || !WIFEXITED(status
)) {
1237 res
= WEXITSTATUS(status
);
1240 if (time(NULL
) - start_wait
> 5) {
1241 debug_print("SIGTERM'ing gpg\n");
1244 if (time(NULL
) - start_wait
> 6) {
1245 debug_print("SIGKILL'ing gpg\n");
1255 /* We need to call gpg in a separate thread, so that waiting for
1256 * it to finish does not block the UI. */
1258 struct _ExportCtx
*ectx
= malloc(sizeof(struct _ExportCtx
));
1261 ectx
->exitcode
= STILL_ACTIVE
;
1264 if (pthread_create(&pt
, NULL
,
1265 _export_threaded
, (void *)ectx
) != 0) {
1266 debug_print("Couldn't create thread, continuing unthreaded.\n");
1267 _export_threaded(ctx
);
1269 debug_print("Thread created, waiting for it to finish...\n");
1274 debug_print("Thread finished.\n");
1275 pthread_join(pt
, NULL
);
1277 if (ectx
->exitcode
== 0)
1285 alertpanel_notice(_("Key exported."));
1287 alertpanel_error(_("Couldn't export key."));
1294 gboolean
sgpgme_has_secret_key(void)
1296 gpgme_error_t err
= 0;
1300 err
= gpgme_new (&ctx
);
1302 debug_print("err : %s\n", gpgme_strerror(err
));
1306 err
= gpgme_op_keylist_start(ctx
, NULL
, TRUE
);
1308 err
= gpgme_op_keylist_next(ctx
, &key
);
1309 gpgme_key_unref(key
); /* We're not interested in the key itself. */
1311 gpgme_op_keylist_end(ctx
);
1312 if (gpg_err_code(err
) == GPG_ERR_EOF
) {
1313 if (gpgme_get_protocol(ctx
) != GPGME_PROTOCOL_CMS
) {
1314 gpgme_set_protocol(ctx
, GPGME_PROTOCOL_CMS
);
1325 void sgpgme_check_create_key(void)
1327 if (prefs_gpg_get_config()->gpg_ask_create_key
&&
1328 !sgpgme_has_secret_key()) {
1329 sgpgme_create_secret_key(NULL
, TRUE
);
1332 prefs_gpg_get_config()->gpg_ask_create_key
= FALSE
;
1333 prefs_gpg_save_config();
1336 void *sgpgme_data_release_and_get_mem(gpgme_data_t data
, size_t *len
)
1339 void *result
= NULL
;
1343 cm_return_val_if_fail(data
!= NULL
, NULL
);
1344 cm_return_val_if_fail(len
!= NULL
, NULL
);
1346 /* I know it's deprecated, but we don't compile with _LARGEFILE */
1347 cm_gpgme_data_rewind(data
);
1348 while ((r
= gpgme_data_read(data
, buf
, BUFSIZ
)) > 0) {
1349 void *rresult
= realloc(result
, r
+ w
);
1350 if (rresult
== NULL
) {
1351 g_warning("can't allocate memory");
1357 memcpy(result
+w
, buf
, r
);
1363 gpgme_data_release(data
);
1365 g_warning("gpgme_data_read() returned an error: %d", (int)r
);
1373 gpgme_error_t
cm_gpgme_data_rewind(gpgme_data_t dh
)
1375 #if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64
1376 if (gpgme_data_seek(dh
, (off_t
)0, SEEK_SET
) == -1)
1377 return gpg_error_from_errno(errno
);
1381 return gpgme_data_rewind(dh
);
1385 #endif /* USE_GPGME */