Re: [evolution-patches] Mailer bug #127521: Inline PGP support for evolution (part A: only sending)
- From: Bohumir Jelinek <bj48 ra msstate edu>
- To: bj48 ra msstate edu
- Cc: evolution-patches ximian com
- Subject: Re: [evolution-patches] Mailer bug #127521: Inline PGP support for evolution (part A: only sending)
- Date: Tue, 6 Jan 2004 06:48:46 -0600 (CST)
This is unencoded version of the patch.
-Bohumir
Index: camel/ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution/camel/ChangeLog,v
retrieving revision 1.1922
diff -u -r1.1922 ChangeLog
--- camel/ChangeLog 26 Nov 2003 19:32:15 -0000 1.1922
+++ camel/ChangeLog 6 Jan 2004 12:07:05 -0000
@@ -1,3 +1,12 @@
+2004-01-06 Bohumir Jelinek <bj48 msstate edu>
+
+ * camel-cipher-context.c (cipher_clearsign): signs plain text
+ (camel_cipher_dw_to_canon_stream): filters plain text
+ * camel-cipher-context.h: added prototypes for above
+ * camel-gpg-context.c: added GPG_CTX_MODE_CLEARSIGN enumeration
+ (gpg_clearsign): signs plain text
+ * e-msg-composer.c (build_message): modified to offer clearsign
+
2003-11-26 JP Rosevear <jpr ximian com>
* Makefile.am: make sure we always dist the smime stuff
Index: camel/camel-cipher-context.c
===================================================================
RCS file: /cvs/gnome/evolution/camel/camel-cipher-context.c,v
retrieving revision 1.16
diff -u -r1.16 camel-cipher-context.c
--- camel/camel-cipher-context.c 24 Nov 2003 22:38:12 -0000 1.16
+++ camel/camel-cipher-context.c 6 Jan 2004 12:07:05 -0000
@@ -102,6 +102,15 @@
return -1;
}
+static int
+cipher_clearsign (CamelCipherContext *ctx, const char *userid, CamelCipherHash hash,
+ struct _CamelDataWrapper *plain, struct _CamelDataWrapper *current, CamelException *ex)
+{
+ camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
+ _("Inline signing is not supported by this cipher"));
+ return -1;
+}
+
/**
* camel_cipher_sign:
* @context: Cipher Context
@@ -133,6 +142,35 @@
return retval;
}
+/**
+ * camel_cipher_clearsign:
+ * @context: Cipher Context
+ * @userid: private key to use to sign the stream
+ * @hash: preferred Message-Integrity-Check hash algorithm
+ * @iopart: Input/output part.
+ * @ex: exception
+ *
+ * Appends signature at the end of plain text part @iopart.
+ *
+ * Return value: 0 for success or -1 for failure.
+ **/
+int
+camel_cipher_clearsign (CamelCipherContext *context, const char *userid, CamelCipherHash hash,
+ struct _CamelDataWrapper *plain, struct _CamelDataWrapper *current, CamelException *ex)
+{
+ int retval;
+
+ g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), -1);
+
+ CIPHER_LOCK(context);
+
+ retval = CCC_CLASS (context)->clearsign (context, userid, hash, plain, current, ex);
+
+ CIPHER_UNLOCK(context);
+
+ return retval;
+}
+
static CamelCipherValidity *
cipher_verify (CamelCipherContext *context, struct _CamelMimePart *sigpart, CamelException *ex)
{
@@ -490,6 +528,7 @@
camel_cipher_context_class->hash_to_id = cipher_hash_to_id;
camel_cipher_context_class->id_to_hash = cipher_id_to_hash;
camel_cipher_context_class->sign = cipher_sign;
+ camel_cipher_context_class->clearsign = cipher_clearsign;
camel_cipher_context_class->verify = cipher_verify;
camel_cipher_context_class->encrypt = cipher_encrypt;
camel_cipher_context_class->decrypt = cipher_decrypt;
@@ -583,3 +622,37 @@
return res;
}
+
+/**
+ * camel_cipher_dw_to_canon_stream:
+ * @dw: data wrapper to write.
+ * @flags: flags for the canonicalisation filter (CamelMimeFilterCanon)
+ * @ostream: stream to write canonicalised output to.
+ *
+ * Writes a dw to a stream in a canonicalised format, suitable for signing/encrypting.
+ *
+ * Return value: -1 on error;
+ **/
+int
+camel_cipher_dw_to_canon_stream(CamelDataWrapper *dw, guint32 flags, CamelStream *ostream)
+{
+ CamelStreamFilter *filter;
+ CamelMimeFilter *canon;
+ int res = -1;
+
+ filter = camel_stream_filter_new_with_stream(ostream);
+
+ canon = camel_mime_filter_canon_new(flags);
+ camel_stream_filter_add(filter, canon);
+ camel_object_unref(canon);
+
+ if (camel_data_wrapper_write_to_stream(dw, (CamelStream *)filter) != -1
+ && camel_stream_flush((CamelStream *)filter) != -1)
+ res = 0;
+
+ camel_object_unref(filter);
+
+ camel_stream_reset(ostream);
+
+ return res;
+}
Index: camel/camel-cipher-context.h
===================================================================
RCS file: /cvs/gnome/evolution/camel/camel-cipher-context.h,v
retrieving revision 1.14
diff -u -r1.14 camel-cipher-context.h
--- camel/camel-cipher-context.h 24 Nov 2003 22:38:12 -0000 1.14
+++ camel/camel-cipher-context.h 6 Jan 2004 12:07:06 -0000
@@ -105,6 +105,9 @@
int (*sign) (CamelCipherContext *context, const char *userid, CamelCipherHash hash,
struct _CamelMimePart *ipart, struct _CamelMimePart *opart, CamelException *ex);
+ int (*clearsign) (CamelCipherContext *context, const char *userid, CamelCipherHash hash,
+ struct _CamelDataWrapper *plain, struct _CamelDataWrapper *current, CamelException *ex);
+
CamelCipherValidity * (*verify) (CamelCipherContext *context, struct _CamelMimePart *ipart, CamelException *ex);
int (*encrypt) (CamelCipherContext *context, const char *userid,
@@ -139,6 +142,8 @@
/* cipher routines */
int camel_cipher_sign (CamelCipherContext *context, const char *userid, CamelCipherHash hash,
struct _CamelMimePart *ipart, struct _CamelMimePart *opart, CamelException *ex);
+int camel_cipher_clearsign (CamelCipherContext *context, const char *userid, CamelCipherHash hash,
+ struct _CamelDataWrapper *plain, struct _CamelDataWrapper *current, CamelException *ex);
CamelCipherValidity *camel_cipher_verify (CamelCipherContext *context, struct _CamelMimePart *ipart, CamelException *ex);
int camel_cipher_encrypt (CamelCipherContext *context, const char *userid,
GPtrArray *recipients, struct _CamelMimePart *ipart, struct _CamelMimePart *opart,
@@ -166,6 +171,7 @@
/* utility functions */
int camel_cipher_canonical_to_stream(CamelMimePart *part, guint32 flags, CamelStream *ostream);
+int camel_cipher_dw_to_canon_stream(CamelDataWrapper *dw, guint32 flags, CamelStream *ostream);
#ifdef __cplusplus
}
Index: camel/camel-gpg-context.c
===================================================================
RCS file: /cvs/gnome/evolution/camel/camel-gpg-context.c,v
retrieving revision 1.40
diff -u -r1.40 camel-gpg-context.c
--- camel/camel-gpg-context.c 13 Nov 2003 23:17:30 -0000 1.40
+++ camel/camel-gpg-context.c 6 Jan 2004 12:07:06 -0000
@@ -148,6 +148,7 @@
enum _GpgCtxMode {
GPG_CTX_MODE_SIGN,
+ GPG_CTX_MODE_CLEARSIGN,
GPG_CTX_MODE_VERIFY,
GPG_CTX_MODE_ENCRYPT,
GPG_CTX_MODE_DECRYPT,
@@ -294,7 +295,7 @@
gpg_ctx_set_mode (struct _GpgCtx *gpg, enum _GpgCtxMode mode)
{
gpg->mode = mode;
- gpg->need_passwd = ((gpg->mode == GPG_CTX_MODE_SIGN) || (gpg->mode == GPG_CTX_MODE_DECRYPT));
+ gpg->need_passwd = ((gpg->mode == GPG_CTX_MODE_SIGN) || (gpg->mode == GPG_CTX_MODE_DECRYPT) || (gpg->mode == GPG_CTX_MODE_CLEARSIGN));
}
static void
@@ -494,6 +495,18 @@
g_ptr_array_add (argv, "--output");
g_ptr_array_add (argv, "-");
break;
+ case GPG_CTX_MODE_CLEARSIGN:
+ g_ptr_array_add (argv, "--clearsign");
+ hash_str = gpg_hash_str (gpg->hash);
+ if (hash_str)
+ g_ptr_array_add (argv, (char *) hash_str);
+ if (gpg->userid) {
+ g_ptr_array_add (argv, "-u");
+ g_ptr_array_add (argv, (char *) gpg->userid);
+ }
+ g_ptr_array_add (argv, "--output");
+ g_ptr_array_add (argv, "-");
+ break;
case GPG_CTX_MODE_VERIFY:
if (!camel_session_is_online (gpg->session)) {
/* this is a deprecated flag to gpg since 1.0.7 */
@@ -806,6 +819,11 @@
/* FIXME: save this state? */
}
break;
+ case GPG_CTX_MODE_CLEARSIGN:
+ if (!strncmp (status, "SIG_CREATED ", 12)) {
+ /* FIXME: save this state? */
+ }
+ break;
case GPG_CTX_MODE_VERIFY:
if (!strncmp (status, "TRUST_", 6)) {
status += 6;
@@ -1087,6 +1105,9 @@
case GPG_CTX_MODE_SIGN:
mode = "sign";
break;
+ case GPG_CTX_MODE_CLEARSIGN:
+ mode = "clearsign";
+ break;
case GPG_CTX_MODE_VERIFY:
mode = "verify";
break;
@@ -1310,6 +1331,81 @@
}
+static int
+gpg_clearsign (CamelCipherContext *context, const char *userid, CamelCipherHash hash, CamelDataWrapper *plain, CamelDataWrapper *current, CamelException *ex)
+{
+ struct _GpgCtx *gpg;
+ CamelStream *ostream = camel_stream_mem_new(), *istream;
+ CamelContentType *ct;
+ int res = -1;
+
+ /* Note: see rfc2015 or rfc3156, section 5 */
+
+ /* FIXME: stream this, we stream output at least */
+ istream = camel_stream_mem_new();
+ if (camel_cipher_dw_to_canon_stream(plain, CAMEL_MIME_FILTER_CANON_STRIP|CAMEL_MIME_FILTER_CANON_CRLF|CAMEL_MIME_FILTER_CANON_FROM,
+ istream) == -1) {
+ camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
+ _("Could not generate signing data: %s"), g_strerror(errno));
+ goto fail;
+ }
+
+ gpg = gpg_ctx_new (context->session);
+ gpg_ctx_set_mode (gpg, GPG_CTX_MODE_CLEARSIGN);
+ gpg_ctx_set_hash (gpg, hash);
+ gpg_ctx_set_userid (gpg, userid);
+ gpg_ctx_set_istream (gpg, istream);
+ gpg_ctx_set_ostream (gpg, ostream);
+
+ if (gpg_ctx_op_start (gpg) == -1) {
+ camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
+ _("Failed to execute gpg: %s"), g_strerror (errno));
+ goto fail;
+ }
+
+ while (!gpg_ctx_op_complete (gpg)) {
+ if (camel_operation_cancel_check (NULL)) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL,
+ _("Cancelled."));
+ gpg_ctx_op_cancel (gpg);
+ goto fail;
+ }
+
+ if (gpg_ctx_op_step (gpg, ex) == -1) {
+ gpg_ctx_op_cancel (gpg);
+ goto fail;
+ }
+ }
+
+ if (gpg_ctx_op_wait (gpg) != 0) {
+ const char *diagnostics;
+
+ diagnostics = gpg_ctx_get_diagnostics (gpg);
+ camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
+ diagnostics && *diagnostics ? diagnostics :
+ _("Failed to execute gpg."));
+ goto fail;
+ }
+
+ res = 0;
+
+ camel_stream_reset(ostream);
+ camel_data_wrapper_construct_from_stream(current, ostream);
+
+ ct = camel_content_type_new("application", "pgp");
+ camel_content_type_set_param(ct, "x-action", "sign");
+ camel_content_type_set_param(ct, "format", "text");
+ camel_data_wrapper_set_mime_type_field(current, ct);
+ camel_content_type_unref(ct);
+
+fail:
+ camel_object_unref(ostream);
+ gpg_ctx_free (gpg);
+
+ return res;
+}
+
+
static char *
swrite (CamelMimePart *sigpart)
{
@@ -1740,6 +1836,7 @@
cipher_class->hash_to_id = gpg_hash_to_id;
cipher_class->id_to_hash = gpg_id_to_hash;
cipher_class->sign = gpg_sign;
+ cipher_class->clearsign = gpg_clearsign;
cipher_class->verify = gpg_verify;
cipher_class->encrypt = gpg_encrypt;
cipher_class->decrypt = gpg_decrypt;
Index: composer/e-msg-composer.c
===================================================================
RCS file: /cvs/gnome/evolution/composer/e-msg-composer.c,v
retrieving revision 1.424
diff -u -r1.424 e-msg-composer.c
--- composer/e-msg-composer.c 26 Nov 2003 21:51:40 -0000 1.424
+++ composer/e-msg-composer.c 6 Jan 2004 12:07:06 -0000
@@ -370,6 +370,7 @@
CamelException ex;
GByteArray *data;
int i;
+ gboolean clearsign = FALSE;
if (composer->persist_stream_interface == CORBA_OBJECT_NIL)
return NULL;
@@ -575,11 +576,8 @@
CamelInternetAddress *from = NULL;
CamelCipherContext *cipher;
- part = camel_mime_part_new ();
- camel_medium_set_content_object (CAMEL_MEDIUM (part), current);
if (current == plain)
camel_mime_part_set_encoding (part, plain_encoding);
- camel_object_unref (current);
if (hdrs->account && hdrs->account->pgp_key && *hdrs->account->pgp_key) {
pgp_userid = hdrs->account->pgp_key;
@@ -589,19 +587,44 @@
}
if (composer->pgp_sign) {
- CamelMimePart *npart = camel_mime_part_new();
+
+ if (current == plain) {
+ /*
+ * For plain text message, ask user if he wants to use "clearsign"
+ */
+ clearsign = em_utils_prompt_user ((GtkWindow *) composer, GTK_RESPONSE_YES, NULL,
+ _("PGP signature of plain text message can be inlined.\nInline?"));
+ }
cipher = mail_crypto_get_pgp_cipher_context(hdrs->account);
- camel_cipher_sign(cipher, pgp_userid, CAMEL_CIPHER_HASH_SHA1, part, npart, &ex);
- camel_object_unref(cipher);
-
- if (camel_exception_is_set(&ex)) {
- camel_object_unref(npart);
- goto exception;
+ if (!clearsign) {
+ part = camel_mime_part_new ();
+ camel_medium_set_content_object (CAMEL_MEDIUM (part), current);
+ camel_object_unref (current);
+ CamelMimePart *npart = camel_mime_part_new();
+
+ camel_cipher_sign(cipher, pgp_userid, CAMEL_CIPHER_HASH_SHA1, part, npart, &ex);
+
+ if (camel_exception_is_set(&ex)) {
+ camel_object_unref(npart);
+ goto exception;
+ }
+
+ camel_object_unref(part);
+ part = npart;
}
+ else {
+ current = camel_data_wrapper_new ();
+ camel_cipher_clearsign(cipher, pgp_userid, CAMEL_CIPHER_HASH_SHA1, plain, current, &ex);
+
+ if (camel_exception_is_set(&ex)) {
+ camel_object_unref(current);
+ goto exception;
+ }
- camel_object_unref(part);
- part = npart;
+ }
+ camel_object_unref(cipher);
+
}
if (composer->pgp_encrypt) {
@@ -630,9 +653,11 @@
if (from)
camel_object_unref (from);
- current = camel_medium_get_content_object (CAMEL_MEDIUM (part));
- camel_object_ref (current);
- camel_object_unref (part);
+ if (!clearsign) {
+ current = camel_medium_get_content_object (CAMEL_MEDIUM (part));
+ camel_object_ref (current);
+ camel_object_unref (part);
+ }
}
#if defined (HAVE_NSS) && defined (SMIME_SUPPORTED)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]