#include <glib/gi18n.h>
#include <stdio.h>
#include <errno.h>
+#ifndef G_OS_WIN32
+#include <sys/mman.h>
+#endif
#if HAVE_LOCALE_H
# include <locale.h>
#endif
#include "alertpanel.h"
#include "passphrase.h"
#include "prefs_gpg.h"
+#include "account.h"
#include "select-keys.h"
static void sgpgme_disable_all(void)
if ((err = gpgme_op_verify(ctx, sig, plain, dummy)) != GPG_ERR_NO_ERROR) {
debug_print("op_verify err %s\n", gpgme_strerror(err));
+ privacy_set_error(gpgme_strerror(err));
return GINT_TO_POINTER(-GPG_ERR_SYSTEM_ERROR);
}
static gboolean warned = FALSE;
if (GPOINTER_TO_INT(status) == -GPG_ERR_SYSTEM_ERROR) {
- return g_strdup(_("The signature can't be checked - GPG error."));
+ return g_strdup_printf(_("The signature can't be checked - %s"), privacy_get_error());
}
if (status == NULL) {
tmp_file = get_tmp_file();
copy_file_part(fp, mimeinfo->offset, mimeinfo->length, tmp_file);
fclose(fp);
- fp = g_fopen(tmp_file, "rb");
+ fp = NULL;
debug_print("tmp file %s\n", tmp_file);
- if (!fp)
- return NULL;
err = gpgme_data_new_from_file(&data, tmp_file, 1);
g_unlink(tmp_file);
if (err) {
debug_print ("gpgme_data_new_from_file failed: %s\n",
gpgme_strerror (err));
+ privacy_set_error(_("Couldn't get data from message, %s"), gpgme_strerror(err));
return NULL;
}
return data;
memset (&info, 0, sizeof info);
- if (gpgme_data_new(&plain) != GPG_ERR_NO_ERROR) {
+ if ((err = gpgme_data_new(&plain)) != GPG_ERR_NO_ERROR) {
gpgme_release(ctx);
+ privacy_set_error(_("Couldn't initialize data, %s"), gpgme_strerror(err));
return NULL;
}
err = gpgme_op_decrypt_verify(ctx, cipher, plain);
if (err != GPG_ERR_NO_ERROR) {
debug_print("can't decrypt (%s)\n", gpgme_strerror(err));
+ privacy_set_error("%s", gpgme_strerror(err));
gpgmegtk_free_passphrase();
gpgme_data_release(plain);
return NULL;
config = prefs_gpg_account_get_config(account);
+ switch(config->sign_key) {
+ case SIGN_KEY_DEFAULT:
+ debug_print("using default gnupg key\n");
+ break;
+ case SIGN_KEY_BY_FROM:
+ debug_print("using key for %s\n", account->address);
+ break;
+ case SIGN_KEY_CUSTOM:
+ debug_print("using key for %s\n", config->sign_key_id);
+ break;
+ }
+
if (config->sign_key != SIGN_KEY_DEFAULT) {
gchar *keyid;
- gpgme_key_t key;
+ gpgme_key_t key, key2;
gpgme_error_t err;
if (config->sign_key == SIGN_KEY_BY_FROM)
else if (config->sign_key == SIGN_KEY_CUSTOM)
keyid = config->sign_key_id;
else
- return FALSE;
+ goto bail;
err = gpgme_op_keylist_start(ctx, keyid, 1);
+ if (!err)
+ err = gpgme_op_keylist_next(ctx, &key);
if (err) {
- g_warning("setup_signers start: %s",
- gpg_strerror(err));
- return FALSE;
+ g_warning("setup_signers start: %s", gpgme_strerror(err));
+ privacy_set_error(_("Private key not found (%s)"), gpgme_strerror(err));
+ goto bail;
}
- while (!(err = gpgme_op_keylist_next(ctx, &key))) {
- gpgme_signers_add(ctx, key);
- gpgme_key_release(key);
- }
- if (err && gpg_err_code(err) != GPG_ERR_EOF) {
- g_warning("setup_signers next: %s",
- gpg_strerror(err));
- return FALSE;
+
+ err = gpgme_op_keylist_next(ctx, &key2);
+ if (!err) {
+ g_warning("ambiguous specification of private key '%s'\n",
+ keyid);
+ privacy_set_error(_("Private key specification is ambiguous"));
+ goto bail;
}
- err = gpgme_op_keylist_end(ctx);
+
+ gpgme_op_keylist_end(ctx);
+ err = gpgme_signers_add(ctx, key);
+ gpgme_key_release(key);
+
if (err) {
- g_warning("setup_signers end: %s",
- gpg_strerror(err));
- return FALSE;
+ g_warning("error adding secret key: %s\n", gpgme_strerror(err));
+ privacy_set_error(_("Error setting private key: %s"), gpgme_strerror(err));
+ goto bail;
}
}
prefs_gpg_account_free_config(config);
return TRUE;
+bail:
+ prefs_gpg_account_free_config(config);
+ return FALSE;
}
void sgpgme_init()
#endif
if (!gpgme_get_engine_info(&engineInfo)) {
while (engineInfo) {
- debug_print("GpgME Protocol: %s\n Version: %s\n",
+ debug_print("GpgME Protocol: %s\n"
+ "Version: %s (req %s)\n"
+ "Executable: %s\n",
gpgme_get_protocol_name(engineInfo->protocol),
- engineInfo->version);
+ engineInfo->version ? engineInfo->version:"???",
+ engineInfo->req_version ? engineInfo->req_version:"???",
+ engineInfo->file_name ? engineInfo->file_name:"???");
+ if (engineInfo->protocol == GPGME_PROTOCOL_OpenPGP
+ && gpgme_engine_check_version(engineInfo->protocol) !=
+ GPG_ERR_NO_ERROR) {
+ if (engineInfo->file_name && !engineInfo->version) {
+ alertpanel_error(_("Gpgme protocol '%s' is unusable: "
+ "Engine '%s' isn't installed properly."),
+ gpgme_get_protocol_name(engineInfo->protocol),
+ engineInfo->file_name);
+ } else if (engineInfo->file_name && engineInfo->version
+ && engineInfo->req_version) {
+ alertpanel_error(_("Gpgme protocol '%s' is unusable: "
+ "Engine '%s' version %s is installed, "
+ "but version %s is required.\n"),
+ gpgme_get_protocol_name(engineInfo->protocol),
+ engineInfo->file_name,
+ engineInfo->version,
+ engineInfo->req_version);
+ } else {
+ alertpanel_error(_("Gpgme protocol '%s' is unusable "
+ "(unknown problem)"),
+ gpgme_get_protocol_name(engineInfo->protocol));
+ }
+ }
engineInfo = engineInfo->next;
}
}
gpgmegtk_free_passphrase();
}
+void sgpgme_create_secret_key(PrefsAccount *account)
+{
+ AlertValue val = alertpanel(_("No PGP key found"),
+ _("Sylpheed-Claws did not find a secret PGP key, "
+ "which means that you won't be able to sign "
+ "emails or receive encrypted emails.\n"
+ "Do you want to create a secret key now?"),
+ GTK_STOCK_NO, "+" GTK_STOCK_YES, NULL);
+ gchar *key_parms = NULL;
+ gchar *name = NULL;
+ gchar *email = NULL;
+ gchar *passphrase = NULL, *passphrase_second = NULL;
+ gint prev_bad = 0;
+ gchar *tmp = NULL;
+ gpgme_error_t err = 0;
+ gpgme_ctx_t ctx;
+ GtkWidget *window = NULL;
+ gpgme_genkey_result_t key;
+
+ if (account == NULL)
+ account = account_get_default();
+
+ if (val == G_ALERTDEFAULT) {
+ prefs_gpg_get_config()->gpg_ask_create_key = FALSE;
+ prefs_gpg_save_config();
+ return;
+ }
+
+ if (account->name) {
+ name = g_strdup(account->name);
+ } else {
+ name = g_strdup(account->address);
+ }
+ email = g_strdup(account->address);
+ tmp = g_strdup_printf("%s <%s>", account->name?account->name:account->address, account->address);
+again:
+ passphrase = passphrase_mbox(tmp, NULL, prev_bad, 1);
+ if (passphrase == NULL) {
+ g_free(tmp);
+ g_free(email);
+ g_free(name);
+ return;
+ }
+ passphrase_second = passphrase_mbox(tmp, NULL, 0, 2);
+ if (passphrase_second == NULL) {
+ g_free(tmp);
+ g_free(email);
+ g_free(passphrase);
+ g_free(name);
+ return;
+ }
+ if (strcmp(passphrase, passphrase_second)) {
+ g_free(passphrase);
+ g_free(passphrase_second);
+ prev_bad = 1;
+ goto again;
+ }
+
+ key_parms = g_strdup_printf("<GnupgKeyParms format=\"internal\">\n"
+ "Key-Type: DSA\n"
+ "Key-Length: 1024\n"
+ "Subkey-Type: ELG-E\n"
+ "Subkey-Length: 2048\n"
+ "Name-Real: %s\n"
+ "Name-Email: %s\n"
+ "Expire-Date: 0\n"
+ "%s%s%s"
+ "</GnupgKeyParms>\n",
+ name, email,
+ strlen(passphrase)?"Passphrase: ":"",
+ passphrase,
+ strlen(passphrase)?"\n":"");
+#ifndef G_PLATFORM_WIN32
+ if (mlock(passphrase, strlen(passphrase)) == -1)
+ debug_print("couldn't lock passphrase\n");
+ if (mlock(passphrase_second, strlen(passphrase_second)) == -1)
+ debug_print("couldn't lock passphrase2\n");
+#endif
+ g_free(tmp);
+ g_free(email);
+ g_free(name);
+ g_free(passphrase_second);
+ g_free(passphrase);
+
+ err = gpgme_new (&ctx);
+ if (err) {
+ alertpanel_error(_("Couldn't generate new key: %s"), gpgme_strerror(err));
+ g_free(key_parms);
+ return;
+ }
+
+
+ window = label_window_create(_("Generating your new key... Please move the mouse "
+ "around to help generate entropy..."));
+
+ err = gpgme_op_genkey(ctx, key_parms, NULL, NULL);
+ g_free(key_parms);
+
+ gtk_widget_destroy(window);
+
+ if (err) {
+ alertpanel_error(_("Couldn't generate new key: %s"), gpgme_strerror(err));
+ gpgme_release(ctx);
+ return;
+ }
+ key = gpgme_op_genkey_result(ctx);
+ if (key == NULL) {
+ alertpanel_error(_("Couldn't generate new key: unknown error"));
+ gpgme_release(ctx);
+ return;
+ } else {
+ alertpanel_notice(_("Your secret key has been generated. "
+ "Its fingerprint is:\n%s"),
+ key->fpr ? key->fpr:"null");
+ }
+ prefs_gpg_get_config()->gpg_ask_create_key = FALSE;
+ prefs_gpg_save_config();
+ gpgme_release(ctx);
+}
+
+gboolean sgpgme_has_secret_key(void)
+{
+ gpgme_error_t err = 0;
+ gpgme_ctx_t ctx;
+ gpgme_key_t key;
+
+ err = gpgme_new (&ctx);
+ if (err) {
+ debug_print("err : %s\n", gpgme_strerror(err));
+ return TRUE;
+ }
+ err = gpgme_op_keylist_start(ctx, NULL, TRUE);
+ if (!err)
+ err = gpgme_op_keylist_next(ctx, &key);
+ gpgme_op_keylist_end(ctx);
+ gpgme_release(ctx);
+ if (gpg_err_code(err) == GPG_ERR_EOF)
+ return FALSE;
+ else
+ return TRUE;
+}
+
+void sgpgme_check_create_key(void)
+{
+ if (prefs_gpg_get_config()->gpg_ask_create_key &&
+ !sgpgme_has_secret_key()) {
+ sgpgme_create_secret_key(NULL);
+ } else {
+ prefs_gpg_get_config()->gpg_ask_create_key = FALSE;
+ prefs_gpg_save_config();
+ }
+}
#endif /* USE_GPGME */