aboutsummaryrefslogtreecommitdiffstats
path: root/camel/camel-gpg-context.c
diff options
context:
space:
mode:
Diffstat (limited to 'camel/camel-gpg-context.c')
-rw-r--r--camel/camel-gpg-context.c343
1 files changed, 186 insertions, 157 deletions
diff --git a/camel/camel-gpg-context.c b/camel/camel-gpg-context.c
index 79c14d9b71..6f79cdb4ff 100644
--- a/camel/camel-gpg-context.c
+++ b/camel/camel-gpg-context.c
@@ -49,89 +49,13 @@
#include "camel-stream-mem.h"
#include "camel-stream-fs.h"
#include "camel-operation.h"
+#include "camel-mime-part.h"
+#include "camel-mime-filter-canon.h"
#define d(x)
-static void camel_gpg_context_class_init (CamelGpgContextClass *klass);
-static void camel_gpg_context_init (CamelGpgContext *obj);
-static void camel_gpg_context_finalise (CamelObject *obj);
-
-static const char *gpg_hash_to_id (CamelCipherContext *context, CamelCipherHash hash);
-static CamelCipherHash gpg_id_to_hash (CamelCipherContext *context, const char *id);
-
-static int gpg_sign (CamelCipherContext *ctx, const char *userid, CamelCipherHash hash,
- CamelStream *istream, CamelStream *ostream, CamelException *ex);
-static CamelCipherValidity *gpg_verify (CamelCipherContext *context, CamelCipherHash hash,
- CamelStream *istream, CamelStream *sigstream,
- CamelException *ex);
-static int gpg_encrypt (CamelCipherContext *context, gboolean sign, const char *userid,
- GPtrArray *recipients, CamelStream *istream, CamelStream *ostream,
- CamelException *ex);
-static int gpg_decrypt (CamelCipherContext *context, CamelStream *istream,
- CamelStream *ostream, CamelException *ex);
-static int gpg_import_keys (CamelCipherContext *context, CamelStream *istream,
- CamelException *ex);
-static int gpg_export_keys (CamelCipherContext *context, GPtrArray *keys,
- CamelStream *ostream, CamelException *ex);
-
static CamelCipherContextClass *parent_class = NULL;
-
-CamelType
-camel_gpg_context_get_type (void)
-{
- static CamelType type = CAMEL_INVALID_TYPE;
-
- if (type == CAMEL_INVALID_TYPE) {
- type = camel_type_register (camel_cipher_context_get_type (),
- "CamelGpgContext",
- sizeof (CamelGpgContext),
- sizeof (CamelGpgContextClass),
- (CamelObjectClassInitFunc) camel_gpg_context_class_init,
- NULL,
- (CamelObjectInitFunc) camel_gpg_context_init,
- (CamelObjectFinalizeFunc) camel_gpg_context_finalise);
- }
-
- return type;
-}
-
-static void
-camel_gpg_context_class_init (CamelGpgContextClass *klass)
-{
- CamelCipherContextClass *cipher_class = CAMEL_CIPHER_CONTEXT_CLASS (klass);
-
- parent_class = CAMEL_CIPHER_CONTEXT_CLASS (camel_type_get_global_classfuncs (camel_cipher_context_get_type ()));
-
- 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->verify = gpg_verify;
- cipher_class->encrypt = gpg_encrypt;
- cipher_class->decrypt = gpg_decrypt;
- cipher_class->import_keys = gpg_import_keys;
- cipher_class->export_keys = gpg_export_keys;
-}
-
-static void
-camel_gpg_context_init (CamelGpgContext *context)
-{
- CamelCipherContext *cipher = (CamelCipherContext *) context;
-
- context->always_trust = FALSE;
-
- cipher->sign_protocol = "application/pgp-signature";
- cipher->encrypt_protocol = "application/pgp-encrypted";
- cipher->key_protocol = "application/pgp-keys";
-}
-
-static void
-camel_gpg_context_finalise (CamelObject *object)
-{
- ;
-}
-
-
/**
* camel_gpg_context_new:
* @session: session
@@ -1271,10 +1195,14 @@ gpg_ctx_op_wait (struct _GpgCtx *gpg)
static int
gpg_sign (CamelCipherContext *context, const char *userid, CamelCipherHash hash,
- CamelStream *istream, CamelStream *ostream, CamelException *ex)
+ CamelStream *istream, CamelMimePart *sigpart, CamelException *ex)
{
struct _GpgCtx *gpg;
-
+ CamelStream *ostream = camel_stream_mem_new();
+ CamelDataWrapper *dw;
+ CamelContentType *ct;
+ int res = -1;
+
gpg = gpg_ctx_new (context->session);
gpg_ctx_set_mode (gpg, GPG_CTX_MODE_SIGN);
gpg_ctx_set_hash (gpg, hash);
@@ -1286,9 +1214,7 @@ gpg_sign (CamelCipherContext *context, const char *userid, CamelCipherHash hash,
if (gpg_ctx_op_start (gpg) == -1) {
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
_("Failed to execute gpg: %s"), g_strerror (errno));
- gpg_ctx_free (gpg);
-
- return -1;
+ goto fail;
}
while (!gpg_ctx_op_complete (gpg)) {
@@ -1296,16 +1222,12 @@ gpg_sign (CamelCipherContext *context, const char *userid, CamelCipherHash hash,
camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL,
_("Cancelled."));
gpg_ctx_op_cancel (gpg);
- gpg_ctx_free (gpg);
-
- return -1;
+ goto fail;
}
if (gpg_ctx_op_step (gpg, ex) == -1) {
gpg_ctx_op_cancel (gpg);
- gpg_ctx_free (gpg);
-
- return -1;
+ goto fail;
}
}
@@ -1316,20 +1238,34 @@ gpg_sign (CamelCipherContext *context, const char *userid, CamelCipherHash hash,
camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
diagnostics && *diagnostics ? diagnostics :
_("Failed to execute gpg."));
-
- gpg_ctx_free (gpg);
-
- return -1;
+ goto fail;
}
-
+
+ res = 0;
+
+ dw = camel_data_wrapper_new();
+ camel_stream_reset(ostream);
+ camel_data_wrapper_construct_from_stream(dw, ostream);
+
+ ct = camel_content_type_new("application", "pgp-signature");
+ camel_content_type_set_param(ct, "name", "signature.asc");
+ camel_data_wrapper_set_mime_type_field(dw, ct);
+ camel_content_type_unref(ct);
+
+ camel_medium_set_content_object((CamelMedium *)sigpart, dw);
+ camel_object_unref(dw);
+ camel_mime_part_set_description(sigpart, _("This is a digitally signed message part"));
+
+fail:
+ camel_object_unref(ostream);
gpg_ctx_free (gpg);
- return 0;
+ return res;
}
static char *
-swrite (CamelStream *istream)
+swrite (CamelMimePart *sigpart)
{
CamelStream *ostream;
char *template;
@@ -1341,17 +1277,19 @@ swrite (CamelStream *istream)
g_free (template);
return NULL;
}
-
+
+ /* TODO: This should probably just write the decoded message content out, not the part + headers */
+
ostream = camel_stream_fs_new_with_fd (fd);
- ret = camel_stream_write_to_stream (istream, ostream);
+ ret = camel_data_wrapper_write_to_stream((CamelDataWrapper *)sigpart, ostream);
if (ret != -1) {
ret = camel_stream_flush (ostream);
if (ret != -1)
ret = camel_stream_close (ostream);
}
-
- camel_object_unref (ostream);
-
+
+ camel_object_unref(ostream);
+
if (ret == -1) {
unlink (template);
g_free (template);
@@ -1363,7 +1301,7 @@ swrite (CamelStream *istream)
static CamelCipherValidity *
gpg_verify (CamelCipherContext *context, CamelCipherHash hash,
- CamelStream *istream, CamelStream *sigstream,
+ CamelStream *istream, CamelMimePart *sigpart,
CamelException *ex)
{
CamelCipherValidity *validity;
@@ -1372,10 +1310,10 @@ gpg_verify (CamelCipherContext *context, CamelCipherHash hash,
char *sigfile = NULL;
gboolean valid;
- if (sigstream != NULL) {
+ if (sigpart != NULL) {
/* We are going to verify a detached signature so save
the signature to a temp file. */
- sigfile = swrite (sigstream);
+ sigfile = swrite (sigpart);
if (sigfile == NULL) {
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
_("Cannot verify message signature: "
@@ -1438,51 +1376,62 @@ gpg_verify (CamelCipherContext *context, CamelCipherHash hash,
return NULL;
}
-
static int
-gpg_encrypt (CamelCipherContext *context, gboolean sign, const char *userid,
- GPtrArray *recipients, CamelStream *istream, CamelStream *ostream,
- CamelException *ex)
+gpg_encrypt (CamelCipherContext *context, const char *userid, GPtrArray *recipients, struct _CamelMimePart *ipart, struct _CamelMimePart *opart, CamelException *ex)
{
CamelGpgContext *ctx = (CamelGpgContext *) context;
struct _GpgCtx *gpg;
- int i;
+ int i, res = -1;
+ CamelStream *istream, *filtered_stream, *ostream;
+ CamelMimeFilter *filter;
+ CamelDataWrapper *dw;
+ CamelContentType *ct;
+
+ ostream = camel_stream_mem_new();
+
+ /* TODO: Should this just return a mimepart with an embedded multipart-encrypted? */
+
+ /* Canonicalise the input */
+ /* FIXME: Move this to a common routine */
+ istream = camel_stream_mem_new();
+ filtered_stream = (CamelStream *)camel_stream_filter_new_with_stream(istream);
+ filter = camel_mime_filter_canon_new(CAMEL_MIME_FILTER_CANON_CRLF);
+ camel_stream_filter_add((CamelStreamFilter *)filtered_stream, filter);
+ camel_object_unref(filter);
+ camel_data_wrapper_write_to_stream((CamelDataWrapper *)ipart, filtered_stream);
+ camel_stream_flush(filtered_stream);
+ camel_object_unref(filtered_stream);
+ camel_stream_reset(istream);
gpg = gpg_ctx_new (context->session);
gpg_ctx_set_mode (gpg, GPG_CTX_MODE_ENCRYPT);
gpg_ctx_set_armor (gpg, TRUE);
gpg_ctx_set_userid (gpg, userid);
gpg_ctx_set_istream (gpg, istream);
+ camel_object_unref(istream);
gpg_ctx_set_ostream (gpg, ostream);
gpg_ctx_set_always_trust (gpg, ctx->always_trust);
-
+
for (i = 0; i < recipients->len; i++) {
gpg_ctx_add_recipient (gpg, recipients->pdata[i]);
}
if (gpg_ctx_op_start (gpg) == -1) {
- camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Failed to execute gpg."));
- gpg_ctx_free (gpg);
-
- return -1;
+ camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Failed to execute gpg."));
+ 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);
- gpg_ctx_free (gpg);
-
- return -1;
+
+ /* FIXME: move tihs to a common routine */
+ 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);
- gpg_ctx_free (gpg);
-
- return -1;
+ goto fail;
}
}
@@ -1491,26 +1440,46 @@ gpg_encrypt (CamelCipherContext *context, gboolean sign, const char *userid,
diagnostics = gpg_ctx_get_diagnostics (gpg);
camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
- diagnostics && *diagnostics ? diagnostics :
- _("Failed to execute gpg."));
-
- gpg_ctx_free (gpg);
-
- return -1;
+ diagnostics && *diagnostics ? diagnostics : _("Failed to execute gpg."));
+ goto fail;
}
-
- gpg_ctx_free (gpg);
-
- return 0;
-}
+ res = 0;
-static int
-gpg_decrypt (CamelCipherContext *context, CamelStream *istream,
- CamelStream *ostream, CamelException *ex)
+ dw = camel_data_wrapper_new();
+ ct = camel_content_type_new("application", "octet-stream");
+ camel_content_type_set_param(ct, "name", "encrypted.asc");
+ camel_data_wrapper_set_mime_type_field(dw, ct);
+ camel_content_type_unref(ct);
+ camel_data_wrapper_construct_from_stream(dw, ostream);
+ camel_medium_set_content_object((CamelMedium *)opart, dw);
+ camel_object_unref(dw);
+
+fail:
+ camel_object_unref(ostream);
+ gpg_ctx_free(gpg);
+
+ return res;
+}
+
+static CamelMimePart *
+gpg_decrypt (CamelCipherContext *context, CamelMimePart *ipart, CamelException *ex)
{
struct _GpgCtx *gpg;
-
+ CamelMimePart *opart = NULL;
+ CamelStream *ostream, *istream;
+
+ istream = camel_stream_mem_new();
+ camel_data_wrapper_write_to_stream(camel_medium_get_content_object((CamelMedium *)ipart), istream);
+ /* TODO: de-canonicalise end of lines? */
+ /*stream = camel_stream_mem_new ();
+ filtered_stream = (CamelStream *) camel_stream_filter_new_with_stream (stream);
+ crlf_filter = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_DECODE,
+ CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY);
+ camel_stream_filter_add (CAMEL_STREAM_FILTER (filtered_stream), crlf_filter);
+ camel_object_unref (crlf_filter);*/
+ ostream = camel_stream_mem_new();
+
gpg = gpg_ctx_new (context->session);
gpg_ctx_set_mode (gpg, GPG_CTX_MODE_DECRYPT);
gpg_ctx_set_istream (gpg, istream);
@@ -1519,9 +1488,7 @@ gpg_decrypt (CamelCipherContext *context, CamelStream *istream,
if (gpg_ctx_op_start (gpg) == -1) {
camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
_("Failed to execute gpg."));
- gpg_ctx_free (gpg);
-
- return -1;
+ goto fail;
}
while (!gpg_ctx_op_complete (gpg)) {
@@ -1529,16 +1496,12 @@ gpg_decrypt (CamelCipherContext *context, CamelStream *istream,
camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL,
_("Cancelled."));
gpg_ctx_op_cancel (gpg);
- gpg_ctx_free (gpg);
-
- return -1;
+ goto fail;
}
if (gpg_ctx_op_step (gpg, ex) == -1) {
gpg_ctx_op_cancel (gpg);
- gpg_ctx_free (gpg);
-
- return -1;
+ goto fail;
}
}
@@ -1549,15 +1512,23 @@ gpg_decrypt (CamelCipherContext *context, CamelStream *istream,
camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
diagnostics && *diagnostics ? diagnostics :
_("Failed to execute gpg."));
-
- gpg_ctx_free (gpg);
-
- return -1;
+ goto fail;
}
-
+
+ opart = camel_mime_part_new();
+ camel_stream_reset(ostream);
+ if (camel_data_wrapper_construct_from_stream((CamelDataWrapper *)opart, ostream) == -1) {
+ camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
+ _("Unable to parse message content"));
+ camel_object_unref(opart);
+ opart = NULL;
+ }
+fail:
+ camel_object_unref(ostream);
+ camel_object_unref(istream);
gpg_ctx_free (gpg);
- return 0;
+ return opart;
}
static int
@@ -1655,3 +1626,61 @@ gpg_export_keys (CamelCipherContext *context, GPtrArray *keys, CamelStream *ostr
return 0;
}
+
+/* ********************************************************************** */
+
+static void
+camel_gpg_context_class_init (CamelGpgContextClass *klass)
+{
+ CamelCipherContextClass *cipher_class = CAMEL_CIPHER_CONTEXT_CLASS (klass);
+
+ parent_class = CAMEL_CIPHER_CONTEXT_CLASS (camel_type_get_global_classfuncs (camel_cipher_context_get_type ()));
+
+ 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->verify = gpg_verify;
+ cipher_class->encrypt = gpg_encrypt;
+ cipher_class->decrypt = gpg_decrypt;
+ cipher_class->import_keys = gpg_import_keys;
+ cipher_class->export_keys = gpg_export_keys;
+}
+
+static void
+camel_gpg_context_init (CamelGpgContext *context)
+{
+ CamelCipherContext *cipher = (CamelCipherContext *) context;
+
+ context->always_trust = FALSE;
+
+ cipher->sign_protocol = "application/pgp-signature";
+ cipher->encrypt_protocol = "application/pgp-encrypted";
+ cipher->key_protocol = "application/pgp-keys";
+}
+
+static void
+camel_gpg_context_finalise (CamelObject *object)
+{
+ ;
+}
+
+CamelType
+camel_gpg_context_get_type (void)
+{
+ static CamelType type = CAMEL_INVALID_TYPE;
+
+ if (type == CAMEL_INVALID_TYPE) {
+ type = camel_type_register (camel_cipher_context_get_type (),
+ "CamelGpgContext",
+ sizeof (CamelGpgContext),
+ sizeof (CamelGpgContextClass),
+ (CamelObjectClassInitFunc) camel_gpg_context_class_init,
+ NULL,
+ (CamelObjectInitFunc) camel_gpg_context_init,
+ (CamelObjectFinalizeFunc) camel_gpg_context_finalise);
+ }
+
+ return type;
+}
+
+