void prefs_gpg_remove_skip_encryption_warning(const gchar *systemid) { gchar **systems = NULL; int i = 0; if (prefs_gpg_get_config()->skip_encryption_warning == NULL) return; if (prefs_gpg_should_skip_encryption_warning(systemid)) { systems = g_strsplit(prefs_gpg_get_config()->skip_encryption_warning, ",", -1); g_free(prefs_gpg_get_config()->skip_encryption_warning); prefs_gpg_get_config()->skip_encryption_warning = NULL; while (systems && systems[i]) { if (!strcmp(systems[i],systemid)) { i++; continue; } prefs_gpg_add_skip_encryption_warning(systems[i]); i++; } g_strfreev(systems); } prefs_gpg_save_config(); }
void sgpgme_check_create_key(void) { if (prefs_gpg_get_config()->gpg_ask_create_key && !sgpgme_has_secret_key()) { sgpgme_create_secret_key(NULL, TRUE); } else { prefs_gpg_get_config()->gpg_ask_create_key = FALSE; prefs_gpg_save_config(); } }
void prefs_gpg_add_skip_encryption_warning(const gchar *systemid) { gchar *tmp = NULL; if (prefs_gpg_get_config()->skip_encryption_warning == NULL) prefs_gpg_get_config()->skip_encryption_warning = g_strdup_printf("%s,", systemid); else if (!prefs_gpg_should_skip_encryption_warning(systemid)) { tmp = g_strdup_printf("%s%s,", prefs_gpg_get_config()->skip_encryption_warning, systemid); g_free(prefs_gpg_get_config()->skip_encryption_warning); prefs_gpg_get_config()->skip_encryption_warning = tmp; } prefs_gpg_save_config(); }
static void prefs_gpg_save_func(PrefsPage *_page) { struct GPGPage *page = (struct GPGPage *) _page; GPGConfig *config = prefs_gpg_get_config(); config->auto_check_signatures = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->checkbtn_auto_check_signatures)); config->autocompletion = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->checkbtn_autocompletion)); config->use_gpg_agent = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->checkbtn_use_gpg_agent)); config->store_passphrase = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->checkbtn_store_passphrase)); config->store_passphrase_timeout = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(page->spinbtn_store_passphrase)); config->passphrase_grab = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->checkbtn_passphrase_grab)); config->gpg_warning = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->checkbtn_gpg_warning)); g_free(config->gpg_path); config->gpg_path = g_strdup(gtk_entry_get_text(GTK_ENTRY(page->gpg_path))); if (strcmp(config->gpg_path, "") != 0 && access(config->gpg_path, X_OK) != -1) gpgme_set_engine_info(GPGME_PROTOCOL_OpenPGP, config->gpg_path, NULL); prefs_gpg_enable_agent(config->use_gpg_agent); prefs_gpg_save_config(); }
gboolean prefs_gpg_should_skip_encryption_warning(const gchar *systemid) { gchar **systems = NULL; int i = 0; if (prefs_gpg_get_config()->skip_encryption_warning == NULL) return FALSE; systems = g_strsplit(prefs_gpg_get_config()->skip_encryption_warning, ",", -1); while (systems && systems[i]) { debug_print(" cmp %s %s\n", systems[i], systemid); if (!strcmp(systems[i],systemid)) { g_strfreev(systems); return TRUE; } i++; } g_strfreev(systems); return FALSE; }
const char* gpgmegtk_passphrase_cb (void *opaque, const char *desc, void **r_hd) { struct passphrase_cb_info_s *info = opaque; GpgmeCtx ctx = info ? info->c : NULL; const char *pass; if (!desc) { /* FIXME: cleanup by looking at *r_hd */ return NULL; } if (prefs_gpg_get_config()->store_passphrase && last_pass != NULL && strncmp(desc, "TRY_AGAIN", 9) != 0) return g_strdup(last_pass); gpgmegtk_set_passphrase_grab (prefs_gpg_get_config()->passphrase_grab); debug_print ("%% requesting passphrase for `%s': ", desc); pass = passphrase_mbox (desc); gpgmegtk_free_passphrase(); if (!pass) { debug_print ("%% cancel passphrase entry"); gpgme_cancel (ctx); } else { if (prefs_gpg_get_config()->store_passphrase) { last_pass = g_strdup(pass); if (mlock(last_pass, strlen(last_pass)) == -1) debug_print("%% locking passphrase failed"); if (prefs_gpg_get_config()->store_passphrase_timeout > 0) { gtk_timeout_add(prefs_gpg_get_config()->store_passphrase_timeout*60*1000, free_passphrase, NULL); } } debug_print ("%% sending passphrase"); } return pass; }
void prefs_gpg_init() { static gchar *path[3]; gchar *rcpath; const gchar *tmp = NULL; prefs_set_default(param); rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, COMMON_RC, NULL); prefs_read_config(param, "GPG", rcpath, NULL); g_free(rcpath); path[0] = _("Plugins"); path[1] = _("GPG"); path[2] = NULL; gpg_page.page.path = path; gpg_page.page.create_widget = prefs_gpg_create_widget_func; gpg_page.page.destroy_widget = prefs_gpg_destroy_widget_func; gpg_page.page.save_page = prefs_gpg_save_func; gpg_page.page.weight = 30.0; prefs_gtk_register_page((PrefsPage *) &gpg_page); gpg_account_page.page.path = path; gpg_account_page.page.create_widget = prefs_gpg_account_create_widget_func; gpg_account_page.page.destroy_widget = prefs_gpg_account_destroy_widget_func; gpg_account_page.page.save_page = prefs_gpg_account_save_func; gpg_account_page.page.weight = 30.0; prefs_account_register_page((PrefsPage *) &gpg_account_page); tmp = g_getenv("GPG_AGENT_INFO"); if (tmp) saved_gpg_agent_info = g_strdup(tmp); prefs_gpg_enable_agent(prefs_gpg_get_config()->use_gpg_agent); }
void sgpgme_create_secret_key(PrefsAccount *account, gboolean ask_create) { AlertValue val = G_ALERTDEFAULT; 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 (account->address == NULL) { alertpanel_error(_("You have to save the account's information with \"OK\" " "before being able to generate a key pair.\n")); return; } if (ask_create) { val = alertpanel(_("No PGP key found"), _("Claws Mail 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 new key pair now?"), GTK_STOCK_NO, "+" GTK_STOCK_YES, NULL); 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: RSA\n" "Key-Length: 2048\n" "Subkey-Type: RSA\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 a new key pair: %s"), gpgme_strerror(err)); g_free(key_parms); return; } window = label_window_create(_("Generating your new key pair... Please move the mouse " "around to help generate entropy...")); err = gpgme_op_genkey(ctx, key_parms, NULL, NULL); g_free(key_parms); label_window_destroy(window); if (err) { alertpanel_error(_("Couldn't generate a new key pair: %s"), gpgme_strerror(err)); gpgme_release(ctx); return; } key = gpgme_op_genkey_result(ctx); if (key == NULL) { alertpanel_error(_("Couldn't generate a new key pair: unknown error")); gpgme_release(ctx); return; } else { gchar *buf = g_strdup_printf(_("Your new key pair has been generated. " "Its fingerprint is:\n%s\n\nDo you want to export it " "to a keyserver?"), key->fpr ? key->fpr:"null"); AlertValue val = alertpanel(_("Key generated"), buf, GTK_STOCK_NO, "+" GTK_STOCK_YES, NULL); g_free(buf); if (val == G_ALERTALTERNATE) { #ifndef G_OS_WIN32 gchar *cmd = g_strdup_printf("gpg --no-tty --send-keys %s", key->fpr); int res = 0; pid_t pid = 0; pid = fork(); if (pid == -1) { res = -1; } else if (pid == 0) { /* son */ res = system(cmd); res = WEXITSTATUS(res); _exit(res); } else { int status = 0; time_t start_wait = time(NULL); res = -1; do { if (waitpid(pid, &status, WNOHANG) == 0 || !WIFEXITED(status)) { usleep(200000); } else { res = WEXITSTATUS(status); break; } if (time(NULL) - start_wait > 5) { debug_print("SIGTERM'ing gpg\n"); kill(pid, SIGTERM); } if (time(NULL) - start_wait > 6) { debug_print("SIGKILL'ing gpg\n"); kill(pid, SIGKILL); break; } } while(1); } if (res == 0) { alertpanel_notice(_("Key exported.")); } else { alertpanel_error(_("Couldn't export key.")); } g_free(cmd); #else alertpanel_error(_("Key export isn't implemented in Windows.")); #endif } } prefs_gpg_get_config()->gpg_ask_create_key = FALSE; prefs_gpg_save_config(); gpgme_release(ctx); }
void sgpgme_init() { gchar *ctype_locale = NULL, *messages_locale = NULL; gchar *ctype_utf8_locale = NULL, *messages_utf8_locale = NULL; gpgme_engine_info_t engineInfo; if (gpgme_check_version("1.0.0")) { #ifdef LC_CTYPE debug_print("setting gpgme CTYPE locale\n"); #ifdef G_OS_WIN32 ctype_locale = g_win32_getlocale(); #else ctype_locale = g_strdup(setlocale(LC_CTYPE, NULL)); #endif if (ctype_locale) { debug_print("setting gpgme CTYPE locale to: %s\n", ctype_locale); if (strchr(ctype_locale, '.')) *(strchr(ctype_locale, '.')) = '\0'; else if (strchr(ctype_locale, '@')) *(strchr(ctype_locale, '@')) = '\0'; ctype_utf8_locale = g_strconcat(ctype_locale, ".UTF-8", NULL); debug_print("setting gpgme locale to UTF8: %s\n", ctype_utf8_locale ? ctype_utf8_locale : "NULL"); gpgme_set_locale(NULL, LC_CTYPE, ctype_utf8_locale); debug_print("done\n"); g_free(ctype_utf8_locale); g_free(ctype_locale); } else { debug_print("couldn't set gpgme CTYPE locale\n"); } #endif #ifdef LC_MESSAGES debug_print("setting gpgme MESSAGES locale\n"); #ifdef G_OS_WIN32 messages_locale = g_win32_getlocale(); #else messages_locale = g_strdup(setlocale(LC_MESSAGES, NULL)); #endif if (messages_locale) { debug_print("setting gpgme MESSAGES locale to: %s\n", messages_locale); if (strchr(messages_locale, '.')) *(strchr(messages_locale, '.')) = '\0'; else if (strchr(messages_locale, '@')) *(strchr(messages_locale, '@')) = '\0'; messages_utf8_locale = g_strconcat(messages_locale, ".UTF-8", NULL); debug_print("setting gpgme locale to UTF8: %s\n", messages_utf8_locale ? messages_utf8_locale : "NULL"); gpgme_set_locale(NULL, LC_MESSAGES, messages_utf8_locale); debug_print("done\n"); g_free(messages_utf8_locale); g_free(messages_locale); } else { debug_print("couldn't set gpgme MESSAGES locale\n"); } #endif if (!gpgme_get_engine_info(&engineInfo)) { while (engineInfo) { debug_print("GpgME Protocol: %s\n" "Version: %s (req %s)\n" "Executable: %s\n", gpgme_get_protocol_name(engineInfo->protocol) ? gpgme_get_protocol_name(engineInfo->protocol):"???", 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; } } } else { sgpgme_disable_all(); if (prefs_gpg_get_config()->gpg_warning) { AlertValue val; val = alertpanel_full (_("Warning"), _("GnuPG is not installed properly, or needs " "to be upgraded.\n" "OpenPGP support disabled."), GTK_STOCK_CLOSE, NULL, NULL, TRUE, NULL, ALERT_WARNING, G_ALERTDEFAULT); if (val & G_ALERTDISABLE) prefs_gpg_get_config()->gpg_warning = FALSE; } } }
gpgme_data_t sgpgme_decrypt_verify(gpgme_data_t cipher, gpgme_verify_result_t *status, gpgme_ctx_t ctx) { struct passphrase_cb_info_s info; gpgme_data_t plain; gpgme_error_t err; memset (&info, 0, sizeof info); 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; } if (gpgme_get_protocol(ctx) == GPGME_PROTOCOL_OpenPGP) { prefs_gpg_enable_agent(prefs_gpg_get_config()->use_gpg_agent); if (!getenv("GPG_AGENT_INFO") || !prefs_gpg_get_config()->use_gpg_agent) { info.c = ctx; gpgme_set_passphrase_cb (ctx, gpgmegtk_passphrase_cb, &info); } } else { prefs_gpg_enable_agent(TRUE); info.c = ctx; gpgme_set_passphrase_cb (ctx, NULL, &info); } if (gpgme_get_protocol(ctx) == GPGME_PROTOCOL_OpenPGP) { 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; } err = cm_gpgme_data_rewind(plain); if (err) { debug_print("can't seek (%d %d %s)\n", err, errno, strerror(errno)); } debug_print("decrypted.\n"); *status = gpgme_op_verify_result (ctx); } else { err = gpgme_op_decrypt(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; } err = cm_gpgme_data_rewind(plain); if (err) { debug_print("can't seek (%d %d %s)\n", err, errno, strerror(errno)); } debug_print("decrypted.\n"); *status = gpgme_op_verify_result (ctx); } return plain; }
static gboolean pgpinline_sign(MimeInfo *mimeinfo, PrefsAccount *account, const gchar *from_addr) { MimeInfo *msgcontent; gchar *textstr, *tmp; FILE *fp; gchar *sigcontent; gpgme_ctx_t ctx; gpgme_data_t gpgtext, gpgsig; size_t len; gpgme_error_t err; struct passphrase_cb_info_s info; gpgme_sign_result_t result = NULL; memset (&info, 0, sizeof info); /* get content node from message */ msgcontent = (MimeInfo *) mimeinfo->node->children->data; if (msgcontent->type == MIMETYPE_MULTIPART) { if (!msgcontent->node->children) { debug_print("msgcontent->node->children NULL, bailing\n"); privacy_set_error(_("Malformed message")); return FALSE; } msgcontent = (MimeInfo *) msgcontent->node->children->data; } /* get rid of quoted-printable or anything */ procmime_decode_content(msgcontent); fp = my_tmpfile(); if (fp == NULL) { perror("my_tmpfile"); privacy_set_error(_("Couldn't create temporary file.")); return FALSE; } procmime_write_mimeinfo(msgcontent, fp); rewind(fp); /* read temporary file into memory */ textstr = fp_read_noconv(fp); fclose(fp); gpgme_data_new_from_mem(&gpgtext, textstr, (size_t)strlen(textstr), 0); gpgme_data_new(&gpgsig); if ((err = gpgme_new(&ctx)) != GPG_ERR_NO_ERROR) { debug_print(("Couldn't initialize GPG context, %s"), gpgme_strerror(err)); privacy_set_error(_("Couldn't initialize GPG context, %s"), gpgme_strerror(err)); return FALSE; } gpgme_set_textmode(ctx, 1); gpgme_set_armor(ctx, 1); if (!sgpgme_setup_signers(ctx, account, from_addr)) { gpgme_release(ctx); return FALSE; } prefs_gpg_enable_agent(prefs_gpg_get_config()->use_gpg_agent); if (!getenv("GPG_AGENT_INFO") || !prefs_gpg_get_config()->use_gpg_agent) { info.c = ctx; gpgme_set_passphrase_cb (ctx, gpgmegtk_passphrase_cb, &info); } err = gpgme_op_sign(ctx, gpgtext, gpgsig, GPGME_SIG_MODE_CLEAR); if (err != GPG_ERR_NO_ERROR) { if (err == GPG_ERR_CANCELED) { /* ignore cancelled signing */ privacy_reset_error(); debug_print("gpgme_op_sign cancelled\n"); } else { privacy_set_error(_("Data signing failed, %s"), gpgme_strerror(err)); debug_print("gpgme_op_sign error : %x\n", err); } gpgme_release(ctx); return FALSE; } result = gpgme_op_sign_result(ctx); if (result && result->signatures) { gpgme_new_signature_t sig = result->signatures; while (sig) { debug_print("valid signature: %s\n", sig->fpr); sig = sig->next; } } else if (result && result->invalid_signers) { gpgme_invalid_key_t invalid = result->invalid_signers; while (invalid) { g_warning("invalid signer: %s (%s)", invalid->fpr, gpgme_strerror(invalid->reason)); privacy_set_error(_("Data signing failed due to invalid signer: %s"), gpgme_strerror(invalid->reason)); invalid = invalid->next; } gpgme_release(ctx); return FALSE; } else { /* can't get result (maybe no signing key?) */ debug_print("gpgme_op_sign_result error\n"); privacy_set_error(_("Data signing failed, no results.")); gpgme_release(ctx); return FALSE; } sigcontent = sgpgme_data_release_and_get_mem(gpgsig, &len); if (sigcontent == NULL || len <= 0) { g_warning("sgpgme_data_release_and_get_mem failed"); privacy_set_error(_("Data signing failed, no contents.")); gpgme_data_release(gpgtext); g_free(textstr); g_free(sigcontent); gpgme_release(ctx); return FALSE; } tmp = g_malloc(len+1); g_memmove(tmp, sigcontent, len+1); tmp[len] = '\0'; gpgme_data_release(gpgtext); g_free(textstr); g_free(sigcontent); if (msgcontent->content == MIMECONTENT_FILE && msgcontent->data.filename != NULL) { if (msgcontent->tmp == TRUE) claws_unlink(msgcontent->data.filename); g_free(msgcontent->data.filename); } msgcontent->data.mem = g_strdup(tmp); msgcontent->content = MIMECONTENT_MEM; g_free(tmp); /* avoid all sorts of clear-signing problems with non ascii * chars */ procmime_encode_content(msgcontent, ENC_BASE64); gpgme_release(ctx); return TRUE; }
static void prefs_gpg_create_widget_func(PrefsPage *_page, GtkWindow *window, gpointer data) { struct GPGPage *page = (struct GPGPage *) _page; struct GPGConfig *config; GtkWidget *checkbtn_use_gpg_agent; GtkWidget *checkbtn_passphrase_grab; GtkWidget *checkbtn_store_passphrase; GtkWidget *checkbtn_auto_check_signatures; GtkWidget *checkbtn_autocompletion; GtkWidget *checkbtn_gpg_warning; GtkWidget *hbox1, *hbox2; GtkWidget *vbox1, *vbox2; GtkWidget *label_gpg_path; GtkWidget *label_expire1; GtkAdjustment *spinbtn_store_passphrase_adj; GtkWidget *spinbtn_store_passphrase; GtkWidget *label_expire2; GtkWidget *frame_passphrase; GtkWidget *gpg_path, *gpg_path_btn; vbox1 = gtk_vbox_new (FALSE, VSPACING); gtk_widget_show (vbox1); gtk_container_set_border_width (GTK_CONTAINER (vbox1), VBOX_BORDER); vbox2 = gtk_vbox_new (FALSE, 0); gtk_widget_show (vbox2); gtk_box_pack_start (GTK_BOX (vbox1), vbox2, FALSE, FALSE, 0); PACK_CHECK_BUTTON (vbox2, checkbtn_auto_check_signatures, _("Automatically check signatures")); PACK_CHECK_BUTTON (vbox2, checkbtn_autocompletion, _("Use keyring for address autocompletion")); vbox2 = gtkut_get_options_frame(vbox1, &frame_passphrase, _("Passphrase")); PACK_CHECK_BUTTON (vbox2, checkbtn_use_gpg_agent, _("Use gpg-agent to manage passwords")); if (saved_gpg_agent_info == NULL) gtk_widget_set_sensitive(checkbtn_use_gpg_agent, FALSE); PACK_CHECK_BUTTON (vbox2, checkbtn_store_passphrase, _("Store passphrase in memory")); SET_TOGGLE_SENSITIVITY_REVERSE(checkbtn_use_gpg_agent, checkbtn_store_passphrase); hbox1 = gtk_hbox_new (FALSE, 8); gtk_widget_show (hbox1); gtk_box_pack_start (GTK_BOX (vbox2), hbox1, FALSE, FALSE, 0); SET_TOGGLE_SENSITIVITY_REVERSE(checkbtn_use_gpg_agent, hbox1); label_expire1 = gtk_label_new(_("Expire after")); gtk_widget_show (label_expire1); gtk_box_pack_start (GTK_BOX (hbox1), label_expire1, FALSE, FALSE, 0); spinbtn_store_passphrase_adj = GTK_ADJUSTMENT(gtk_adjustment_new(1, 0, 1440, 1, 10, 0)); spinbtn_store_passphrase = gtk_spin_button_new(GTK_ADJUSTMENT (spinbtn_store_passphrase_adj), 1, 0); gtk_widget_show(spinbtn_store_passphrase); gtk_box_pack_start(GTK_BOX(hbox1), spinbtn_store_passphrase, FALSE, FALSE, 0); gtk_widget_set_size_request(spinbtn_store_passphrase, 64, -1); CLAWS_SET_TIP(spinbtn_store_passphrase, _("Setting to '0' will store the passphrase for the whole session")); gtk_spin_button_set_numeric(GTK_SPIN_BUTTON (spinbtn_store_passphrase), TRUE); label_expire2 = gtk_label_new(_("minute(s)")); gtk_widget_show(label_expire2); gtk_box_pack_start(GTK_BOX(hbox1), label_expire2, FALSE, FALSE, 0); gtk_misc_set_alignment(GTK_MISC(label_expire2), 0.0, 0.5); SET_TOGGLE_SENSITIVITY (checkbtn_store_passphrase, label_expire1); SET_TOGGLE_SENSITIVITY (checkbtn_store_passphrase, spinbtn_store_passphrase); SET_TOGGLE_SENSITIVITY (checkbtn_store_passphrase, label_expire2); PACK_CHECK_BUTTON (vbox2, checkbtn_passphrase_grab, _("Grab input while entering a passphrase")); vbox2 = gtk_vbox_new (FALSE, 0); gtk_widget_show (vbox2); gtk_box_pack_start (GTK_BOX (vbox1), vbox2, FALSE, FALSE, 0); PACK_CHECK_BUTTON (vbox2, checkbtn_gpg_warning, _("Display warning on start-up if GnuPG doesn't work")); hbox2 = gtk_hbox_new(FALSE, 6); label_gpg_path = gtk_label_new(_("Path to GnuPG executable")); gtk_box_pack_start(GTK_BOX(hbox2), label_gpg_path, FALSE, FALSE, 0); gpg_path = gtk_entry_new(); gtk_box_pack_start(GTK_BOX(hbox2), gpg_path, TRUE, TRUE, 0); CLAWS_SET_TIP(gpg_path, _("If left blank the location of the GnuPG executable will be automatically determined.")); gpg_path_btn = gtkut_get_browse_file_btn(_("Bro_wse")); gtk_box_pack_start(GTK_BOX(hbox2), gpg_path_btn, FALSE, FALSE, 0); g_signal_connect(G_OBJECT(gpg_path_btn), "clicked", G_CALLBACK(gpg_path_browse_cb), gpg_path); pref_set_entry_from_pref(GTK_ENTRY(gpg_path), prefs_gpg.gpg_path); gtk_box_pack_start(GTK_BOX(vbox2), hbox2, FALSE, FALSE, 0); gtk_widget_show_all(vbox1); config = prefs_gpg_get_config(); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbtn_auto_check_signatures), config->auto_check_signatures); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbtn_autocompletion), config->autocompletion); if (!g_getenv("GPG_AGENT_INFO")) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbtn_use_gpg_agent), FALSE); else gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbtn_use_gpg_agent), config->use_gpg_agent); if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkbtn_use_gpg_agent))) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbtn_store_passphrase), config->store_passphrase); gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinbtn_store_passphrase), (float) config->store_passphrase_timeout); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbtn_passphrase_grab), config->passphrase_grab); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbtn_gpg_warning), config->gpg_warning); gtk_entry_set_text(GTK_ENTRY(gpg_path), config->gpg_path); page->checkbtn_auto_check_signatures = checkbtn_auto_check_signatures; page->checkbtn_autocompletion = checkbtn_autocompletion; page->checkbtn_store_passphrase = checkbtn_store_passphrase; page->spinbtn_store_passphrase = spinbtn_store_passphrase; page->checkbtn_passphrase_grab = checkbtn_passphrase_grab; page->checkbtn_gpg_warning = checkbtn_gpg_warning; page->checkbtn_use_gpg_agent = checkbtn_use_gpg_agent; page->gpg_path = gpg_path; page->page.widget = vbox1; }
gboolean prefs_gpg_auto_check_signatures(void) { return prefs_gpg_get_config()->auto_check_signatures; }
gboolean pgpmime_sign(MimeInfo *mimeinfo, PrefsAccount *account, const gchar *from_addr) { MimeInfo *msgcontent, *sigmultipart, *newinfo; gchar *textstr, *micalg = NULL; FILE *fp; gchar *boundary = NULL; gchar *sigcontent; gpgme_ctx_t ctx; gpgme_data_t gpgtext, gpgsig; gpgme_error_t err; size_t len; struct passphrase_cb_info_s info; gpgme_sign_result_t result = NULL; gchar *test_msg; fp = my_tmpfile(); if (fp == NULL) { perror("my_tmpfile"); privacy_set_error(_("Couldn't create temporary file: %s"), g_strerror(errno)); return FALSE; } procmime_write_mimeinfo(mimeinfo, fp); rewind(fp); /* read temporary file into memory */ test_msg = file_read_stream_to_str(fp); claws_fclose(fp); memset (&info, 0, sizeof info); /* remove content node from message */ msgcontent = (MimeInfo *) mimeinfo->node->children->data; g_node_unlink(msgcontent->node); /* create temporary multipart for content */ sigmultipart = procmime_mimeinfo_new(); sigmultipart->type = MIMETYPE_MULTIPART; sigmultipart->subtype = g_strdup("signed"); do { g_free(boundary); boundary = generate_mime_boundary("Sig"); } while (strstr(test_msg, boundary) != NULL); g_free(test_msg); g_hash_table_insert(sigmultipart->typeparameters, g_strdup("boundary"), g_strdup(boundary)); g_hash_table_insert(sigmultipart->typeparameters, g_strdup("protocol"), g_strdup("application/pgp-signature")); g_node_append(sigmultipart->node, msgcontent->node); g_node_append(mimeinfo->node, sigmultipart->node); /* write message content to temporary file */ fp = my_tmpfile(); if (fp == NULL) { perror("my_tmpfile"); privacy_set_error(_("Couldn't create temporary file: %s"), g_strerror(errno)); return FALSE; } procmime_write_mimeinfo(sigmultipart, fp); rewind(fp); /* read temporary file into memory */ textstr = get_canonical_content(fp, boundary); g_free(boundary); claws_fclose(fp); gpgme_data_new_from_mem(&gpgtext, textstr, (size_t)strlen(textstr), 0); gpgme_data_new(&gpgsig); if ((err = gpgme_new(&ctx)) != GPG_ERR_NO_ERROR) { debug_print(("Couldn't initialize GPG context, %s\n"), gpgme_strerror(err)); privacy_set_error(_("Couldn't initialize GPG context, %s"), gpgme_strerror(err)); return FALSE; } gpgme_set_textmode(ctx, 1); gpgme_set_armor(ctx, 1); gpgme_signers_clear (ctx); if (!sgpgme_setup_signers(ctx, account, from_addr)) { gpgme_release(ctx); return FALSE; } prefs_gpg_enable_agent(prefs_gpg_get_config()->use_gpg_agent); if (g_getenv("GPG_AGENT_INFO") && prefs_gpg_get_config()->use_gpg_agent) { debug_print("GPG_AGENT_INFO environment defined, running without passphrase callback\n"); } else { info.c = ctx; gpgme_set_passphrase_cb (ctx, gpgmegtk_passphrase_cb, &info); } err = gpgme_op_sign(ctx, gpgtext, gpgsig, GPGME_SIG_MODE_DETACH); if (err != GPG_ERR_NO_ERROR) { if (err == GPG_ERR_CANCELED) { /* ignore cancelled signing */ privacy_reset_error(); debug_print("gpgme_op_sign cancelled\n"); } else { privacy_set_error(_("Data signing failed, %s"), gpgme_strerror(err)); debug_print("gpgme_op_sign error : %x\n", err); } gpgme_release(ctx); return FALSE; } result = gpgme_op_sign_result(ctx); if (result && result->signatures) { gpgme_new_signature_t sig = result->signatures; if (gpgme_get_protocol(ctx) == GPGME_PROTOCOL_OpenPGP) { gchar *down_algo = g_ascii_strdown(gpgme_hash_algo_name( result->signatures->hash_algo), -1); micalg = g_strdup_printf("pgp-%s", down_algo); g_free(down_algo); } else { micalg = g_strdup(gpgme_hash_algo_name( result->signatures->hash_algo)); } while (sig) { debug_print("valid signature: %s\n", sig->fpr); sig = sig->next; } } else if (result && result->invalid_signers) { gpgme_invalid_key_t invalid = result->invalid_signers; while (invalid) { g_warning("invalid signer: %s (%s)", invalid->fpr, gpgme_strerror(invalid->reason)); privacy_set_error(_("Data signing failed due to invalid signer: %s"), gpgme_strerror(invalid->reason)); invalid = invalid->next; } gpgme_release(ctx); return FALSE; } else { /* can't get result (maybe no signing key?) */ debug_print("gpgme_op_sign_result error\n"); privacy_set_error(_("Data signing failed, no results.")); gpgme_release(ctx); return FALSE; } sigcontent = sgpgme_data_release_and_get_mem(gpgsig, &len); gpgme_data_release(gpgtext); g_free(textstr); if (sigcontent == NULL || len <= 0) { g_warning("sgpgme_data_release_and_get_mem failed"); privacy_set_error(_("Data signing failed, no contents.")); g_free(micalg); g_free(sigcontent); return FALSE; } /* add signature */ g_hash_table_insert(sigmultipart->typeparameters, g_strdup("micalg"), micalg); newinfo = procmime_mimeinfo_new(); newinfo->type = MIMETYPE_APPLICATION; newinfo->subtype = g_strdup("pgp-signature"); newinfo->description = g_strdup(_("OpenPGP digital signature")); newinfo->content = MIMECONTENT_MEM; newinfo->data.mem = g_malloc(len + 1); g_memmove(newinfo->data.mem, sigcontent, len); newinfo->data.mem[len] = '\0'; g_node_append(sigmultipart->node, newinfo->node); g_free(sigcontent); gpgme_release(ctx); return TRUE; }