Somebody claiming to be Sergio Villar Senin wrote:
> En 05/06/10 14:12, Stephen Paul Weber escribiu:
> > Is there a plugin system of any kind for modest?  I'd like to get an 
> > OpenPGP/GPG plugin working.
> >
> >   
> Yes there is, but is not intended for adding such kind of things. The
> current plugin system allows the integration of new protocol plugins.
> That's how Modest support ActiveSync and IntellySync.

After some more research, and a thread on this list about the Message UI
code, I have a very rudimentary proof of concept.

It only works for PGP/MIME (no inline PGP), only validates signatures (no
decryption, no signing or encryption), and only works if gpg is installed
and in $PATH (actually, this is how OpenPGP implementations in many popular
mail clients work).

It does not yet integrate into the UI, just does the validation and prints a
message to STDOUT.  Still, it shows what is sort of necessary to make this
work, and does in fact work for what it does.  I would appreciate feedback
on both my implementation and my style, as this is only my second time
seriously working in GNUC land.  I have tried to conform to C89+POSIX
everywhere possible, but of course some things are using glib stuff as part
of the interface with Modest.

The next step will be getting something to show up in the UI (which will be
my first foray into GTK) after which I would work on decryption and then
signing/encryption.

Keyring management, fetching from keyservers, etc, is entirely out of scope.
I may write/port a a program with some of these feature for Maemo later, but
they are certainly not the job of a mail client!

Diff against existing file and the new .h and .c files for new functionality
are attached.

-- 
Stephen Paul Weber, @singpolyma
See <http://singpolyma.net> for how I prefer to be contacted
edition right joseph
diff --git a/src/Makefile.am b/src/Makefile.am
index 542a9db..aa51571 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -68,6 +68,7 @@ modest_public_headers = \
 	modest-tny-folder.h \
 	modest-tny-local-folders-account.h \
 	modest-tny-send-queue.h \
+	modest-openpgp.h \
 	modest-utils.h
 
 libmodest_la_SOURCES=\
@@ -155,6 +156,8 @@ libmodest_la_SOURCES=\
 	modest-ui-dimming-manager.h \
 	modest-ui-dimming-rules.c \
 	modest-ui-dimming-rules.h \
+	modest-openpgp.c \
+	modest-openpgp.h \
 	modest-utils.c \
 	modest-widget-memory-priv.h \
 	modest-widget-memory.c \
diff --git a/src/widgets/modest-msg-view-window.c b/src/widgets/modest-msg-view-window.c
index 827cd10..56d7fe5 100644
--- a/src/widgets/modest-msg-view-window.c
+++ b/src/widgets/modest-msg-view-window.c
@@ -37,6 +37,7 @@
 #include "modest-marshal.h"
 #include "modest-platform.h"
 #include <modest-utils.h>
+#include "modest-openpgp.h"
 #include <modest-toolkit-utils.h>
 #include <modest-tny-msg.h>
 #include <modest-msg-view-window.h>
@@ -2343,6 +2344,17 @@ view_msg_cb (ModestMailOperation *mail_op,
 		update_window_title (MODEST_MSG_VIEW_WINDOW (self));
 		update_branding (MODEST_MSG_VIEW_WINDOW (self));
 		modest_msg_view_grab_focus (MODEST_MSG_VIEW (priv->msg_view));
+
+		struct OpenPGP_Result pgp = modest_openpgp_process(TNY_MIME_PART(msg));
+		if (pgp.signature) { // Signature not bad
+			puts("\n\n\tOPENPGP: No signature or non-bad signature. Signature, if any, from:\n");
+			puts(pgp.signature_from);
+			puts("\n");
+		} else {
+			puts("\n\n\tOPENPGP: BAD signature found from:\n");
+			puts(pgp.signature_from);
+			puts("\n");
+		}
 	}
 
 	/* Set the new message uid of the window  */
#ifndef _H_MODEST_OPENPGP
#define _H_MODEST_OPENPGP

#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <tny-mime-part.h>

/* Constants for OpenPGP_Result.signature */
#define MODEST_OPENPGP_NOT_IN_KEYRING -3
#define MODEST_OPENPGP_UNTRUSTED      -2
#define MODEST_OPENPGP_NO_SIGNATURE   -1
#define MODEST_OPENPGP_BAD_SIGNATURE   0
#define MODEST_OPENPGP_GOOD_SIGNATURE  1

struct OpenPGP_Result {
	int signature;
	/*int signature_date;*/
	char *signature_from;
	/*char *encrypted_body;*/
};

struct OpenPGP_Result modest_openpgp_process(TnyMimePart *);

#endif
#include "modest-openpgp.h"

/* PGP/MIME, RFC2015 */
struct OpenPGP_Result modest_openpgp_process(TnyMimePart *msg) {
	struct OpenPGP_Result r;
	r.signature = MODEST_OPENPGP_NO_SIGNATURE;
	r.signature_from = "";

	gchar *content_type = modest_tny_mime_part_get_content_type(msg);
	if (g_str_has_prefix(content_type, "multipart/signed")) { /* Signed message */
		modest_openpgp_process_signature(msg, &r);
	}
	g_free(content_type);

	return r;
}

void modest_openpgp_process_signature(TnyMimePart *msg, struct OpenPGP_Result *r) {
	gssize i;
	TnyList *parts, *headers;
	TnyIterator *parts_iter, *headers_iter;
	char *data_path, *sig_path, *command;
	char buf[100];
	int data_fd, sig_fd;
	FILE *command_stream;

	/* Temporary files for data and signature */
	data_path = tempnam(NULL, "mgpgi");
	if (!data_path) return;
	data_fd = open(data_path, O_WRONLY|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR);
	if (data_fd < 0) return;
	sig_path = tempnam(NULL, "mgpgi");
	if (!sig_path) return;
	sig_fd = open(sig_path, O_WRONLY|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR);
	if (sig_fd < 0) return;

	/* Set up for loop over parts */
	parts = tny_simple_list_new();
	tny_mime_part_get_parts(msg, parts);
	parts_iter = tny_list_create_iterator(parts);

	/* First part is message, second part is signature */
	for(i = 0; !tny_iterator_is_done(parts_iter); i++) {
		TnyStream *s;
		TnyMimePart *part = TNY_MIME_PART(tny_iterator_get_current(parts_iter));

		if (i == 0) { /* data file */
			s = TNY_STREAM(tny_fs_stream_new(data_fd));

			/* Write part headers to the data file */
			headers = tny_simple_list_new();
			tny_mime_part_get_header_pairs(part, headers);
			headers_iter = tny_list_create_iterator(headers);
			while(!tny_iterator_is_done(headers_iter)) {
				TnyPair *pair = TNY_PAIR(tny_iterator_get_current(headers_iter));
				char *name = tny_pair_get_name(pair);
				char *val  = tny_pair_get_value(pair);
				tny_stream_write(s, name, strlen(name));
				tny_stream_write(s, ":", 1);
				tny_stream_write(s, val, strlen(val));
				tny_stream_write(s, "\r\n", 2);

				/* Cleanup and next */
				g_object_unref(pair);
				tny_iterator_next(headers_iter);
			}
			tny_stream_write(s, "\r\n", 2);

			g_object_unref(headers_iter);
			g_object_unref(headers);
		} else { /* signature file */
			s = TNY_STREAM(tny_fs_stream_new(sig_fd));
		}

		/* Write MIME part body to file and close */
		tny_mime_part_write_to_stream(part, s, NULL);
		tny_stream_close(s);

		/* Cleanup and next */
		g_object_unref(s);
		g_object_unref(part);
		tny_iterator_next(parts_iter);
	}

	g_object_unref(parts_iter);
	g_object_unref(parts);

	command = malloc(sizeof("gpg --verify   2>&1") + strlen(data_path) + strlen(sig_path));
	*command = '\0';
	strcat(command, "gpg --verify ");
	strcat(command, sig_path);
	strcat(command, " ");
	strcat(command, data_path);
	strcat(command, " 2>&1");

	command_stream = popen(command, "r");
	while(fgets(buf, sizeof(buf)-1, command_stream)) {
		char *pos;
		if((pos = strstr(buf, "gpg: Good signature from"))) {
			r->signature = MODEST_OPENPGP_GOOD_SIGNATURE;
			r->signature_from = strdup(pos + 26); /* Should also chomp " on end */
		}
		if((pos = strstr(buf, "gpg: BAD signature from"))) {
			r->signature = MODEST_OPENPGP_BAD_SIGNATURE;
			r->signature_from = strdup(pos + 25); /* Should also chomp " on end */
		}
		if((pos = strstr(buf, "gpg: Can't check signature: public key not found"))) {
			r->signature = MODEST_OPENPGP_NOT_IN_KEYRING;
		}
		if((pos = strstr(buf, "gpg: WARNING"))) {
			r->signature = MODEST_OPENPGP_UNTRUSTED;
		}
	}
	pclose(command_stream);
}

Attachment: smime.p7s
Description: S/MIME cryptographic signature

_______________________________________________
Modest-devel mailing list
Modest-devel@garage.maemo.org
https://garage.maemo.org/mailman/listinfo/modest-devel

Reply via email to