예제 #1
0
파일: prefs_gpg.c 프로젝트: Mortal/claws
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();
}
예제 #2
0
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();
	}	
}
예제 #3
0
파일: prefs_gpg.c 프로젝트: Mortal/claws
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();
}
예제 #4
0
파일: prefs_gpg.c 프로젝트: Mortal/claws
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();
}
예제 #5
0
파일: prefs_gpg.c 프로젝트: Mortal/claws
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;
}
예제 #6
0
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;
}
예제 #7
0
파일: prefs_gpg.c 프로젝트: Mortal/claws
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);
}
예제 #8
0
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);
}
예제 #9
0
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;
		}
	}
}
예제 #10
0
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;
}
예제 #11
0
파일: pgpinline.c 프로젝트: buzz/claws
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;
}
예제 #12
0
파일: prefs_gpg.c 프로젝트: Mortal/claws
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;
}
예제 #13
0
파일: prefs_gpg.c 프로젝트: Mortal/claws
gboolean prefs_gpg_auto_check_signatures(void)
{
	return prefs_gpg_get_config()->auto_check_signatures;
}
예제 #14
0
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;
}