aboutsummaryrefslogtreecommitdiffstats
path: root/camel/camel-multipart-signed.c
diff options
context:
space:
mode:
Diffstat (limited to 'camel/camel-multipart-signed.c')
-rw-r--r--camel/camel-multipart-signed.c195
1 files changed, 193 insertions, 2 deletions
diff --git a/camel/camel-multipart-signed.c b/camel/camel-multipart-signed.c
index ebd5d275e4..26d3b04993 100644
--- a/camel/camel-multipart-signed.c
+++ b/camel/camel-multipart-signed.c
@@ -43,13 +43,12 @@
#include "camel-multipart-signed.h"
#include "camel-mime-part.h"
#include "camel-exception.h"
-#include "libedataserver/md5-utils.h"
+#include "md5-utils.h"
#include "camel-stream-filter.h"
#include "camel-seekable-substream.h"
#include "camel-mime-filter-crlf.h"
#include "camel-mime-filter-canon.h"
-#include "camel-i18n.h"
#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))
#include <stdio.h>;*/
@@ -541,6 +540,124 @@ write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream)
return total;
}
+/* See rfc3156, section 2 and others */
+/* We do this simply: Anything not base64 must be qp
+ This is so that we can safely translate any occurance of "From "
+ into the quoted-printable escaped version safely. */
+static void
+prepare_sign(CamelMimePart *mime_part)
+{
+ CamelDataWrapper *wrapper;
+ CamelTransferEncoding encoding;
+ int parts, i;
+
+ wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part));
+ if (!wrapper)
+ return;
+
+ if (CAMEL_IS_MULTIPART (wrapper)) {
+ parts = camel_multipart_get_number((CamelMultipart *)wrapper);
+ for (i = 0; i < parts; i++)
+ prepare_sign(camel_multipart_get_part((CamelMultipart *)wrapper, i));
+ } else if (CAMEL_IS_MIME_MESSAGE (wrapper)) {
+ prepare_sign((CamelMimePart *)wrapper);
+ } else {
+ encoding = camel_mime_part_get_encoding(mime_part);
+
+ if (encoding != CAMEL_TRANSFER_ENCODING_BASE64
+ && encoding != CAMEL_TRANSFER_ENCODING_QUOTEDPRINTABLE) {
+ camel_mime_part_set_encoding(mime_part, CAMEL_TRANSFER_ENCODING_QUOTEDPRINTABLE);
+ }
+ }
+}
+
+/**
+ * camel_multipart_signed_sign:
+ * @mps:
+ * @context: The CipherContext to use for signing.
+ * @content: CamelMimePart content you wish to sign/transport.
+ * @userid: The id of the signing key to use.
+ * @hash: The algorithm to use.
+ * @ex:
+ *
+ * Sign the part @content, and attach it as the first part
+ * (CAMEL_MULTIPART_SIGNED_CONTENT) of the multipart @mps. A
+ * signature object will be created and setup as the second part
+ * (CAMEL_MULTIPART_SIGNED_SIGNATURE) of the object. Once a part has
+ * been successfully signed the mutlipart is ready for transmission.
+ *
+ * This method should be used to create multipart/signed objects
+ * which are properly canoncalised before signing, etc.
+ *
+ * Return value: -1 on error, setting @ex appropriately. On error
+ * neither the content or signature parts will be setup.
+ **/
+int
+camel_multipart_signed_sign(CamelMultipartSigned *mps, CamelCipherContext *context, CamelMimePart *content, const char *userid, CamelCipherHash hash, CamelException *ex)
+{
+ abort();
+#if 0
+ CamelMimeFilter *canon_filter;
+ CamelStream *mem;
+ CamelStreamFilter *filter;
+ CamelContentType *mime_type;
+ CamelMimePart *sigpart;
+
+ /* this needs to be set */
+ g_return_val_if_fail(context->sign_protocol != NULL, -1);
+
+ prepare_sign(content);
+
+ mem = camel_stream_mem_new();
+ filter = camel_stream_filter_new_with_stream(mem);
+
+ /* Note: see rfc2015 or rfc3156, section 5 */
+ canon_filter = camel_mime_filter_canon_new(CAMEL_MIME_FILTER_CANON_STRIP|CAMEL_MIME_FILTER_CANON_CRLF|CAMEL_MIME_FILTER_CANON_FROM);
+ camel_stream_filter_add(filter, (CamelMimeFilter *)canon_filter);
+ camel_object_unref((CamelObject *)canon_filter);
+
+ camel_data_wrapper_write_to_stream((CamelDataWrapper *)content, (CamelStream *)filter);
+ camel_stream_flush((CamelStream *)filter);
+ camel_object_unref((CamelObject *)filter);
+ camel_stream_reset(mem);
+
+#if 0
+ printf("-- Signing:\n");
+ fwrite(((CamelStreamMem *)mem)->buffer->data, ((CamelStreamMem *)mem)->buffer->len, 1, stdout);
+ printf("-- end\n");
+#endif
+
+ sigpart = camel_mime_part_new();
+
+ if (camel_cipher_sign(context, userid, hash, mem, sigpart, ex) == -1) {
+ camel_object_unref(mem);
+ camel_object_unref(sigpart);
+ return -1;
+ }
+
+ /* setup our mime type and boundary */
+ mime_type = camel_content_type_new("multipart", "signed");
+ camel_content_type_set_param(mime_type, "micalg", camel_cipher_hash_to_id(context, hash));
+ camel_content_type_set_param(mime_type, "protocol", context->sign_protocol);
+ camel_data_wrapper_set_mime_type_field(CAMEL_DATA_WRAPPER (mps), mime_type);
+ camel_content_type_unref(mime_type);
+ camel_multipart_set_boundary((CamelMultipart *)mps, NULL);
+
+ /* just keep the whole raw content. We dont *really* need to do this because
+ we know how we just proccessed it, but, well, better to be safe than sorry */
+ mps->signature = sigpart;
+ mps->contentraw = mem;
+ camel_stream_reset(mem);
+
+ /* clear the data-wrapper stream - tells write_to_stream to use the right object */
+ if (((CamelDataWrapper *)mps)->stream) {
+ camel_object_unref((CamelObject *) ((CamelDataWrapper *)mps)->stream);
+ ((CamelDataWrapper *)mps)->stream = NULL;
+ }
+#endif
+ return 0;
+}
+
CamelStream *
camel_multipart_signed_get_content_stream(CamelMultipartSigned *mps, CamelException *ex)
{
@@ -573,3 +690,77 @@ camel_multipart_signed_get_content_stream(CamelMultipartSigned *mps, CamelExcept
return constream;
}
+
+/**
+ * camel_multipart_signed_verify:
+ * @mps:
+ * @context:
+ * @ex:
+ *
+ * Verify a signed object. This may be used to verify newly signed
+ * objects as well as those created from external streams or parsers.
+ *
+ * Return value: A validity value, or NULL on error, setting @ex
+ * appropriately.
+ **/
+CamelCipherValidity *
+camel_multipart_signed_verify(CamelMultipartSigned *mps, CamelCipherContext *context, CamelException *ex)
+{
+ abort();
+
+ return NULL;
+#if 0
+ CamelCipherValidity *valid;
+ CamelMimePart *sigpart;
+ CamelStream *constream;
+
+ /* we need to be able to verify stuff we just signed as well as stuff we loaded from a stream/parser */
+
+ if (mps->contentraw) {
+ constream = mps->contentraw;
+ camel_object_ref((CamelObject *)constream);
+ } else {
+ CamelStream *sub;
+ CamelMimeFilter *canon_filter;
+
+ if (mps->start1 == -1 && parse_content(mps) == -1) {
+ camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("parse error"));
+ return NULL;
+ }
+
+ /* first, prepare our parts */
+ sub = camel_seekable_substream_new((CamelSeekableStream *)((CamelDataWrapper *)mps)->stream, mps->start1, mps->end1);
+ constream = (CamelStream *)camel_stream_filter_new_with_stream(sub);
+ camel_object_unref((CamelObject *)sub);
+
+ /* Note: see rfc2015 or rfc3156, section 5 */
+ canon_filter = camel_mime_filter_canon_new (CAMEL_MIME_FILTER_CANON_CRLF);
+ camel_stream_filter_add((CamelStreamFilter *)constream, (CamelMimeFilter *)canon_filter);
+ camel_object_unref((CamelObject *)canon_filter);
+ }
+
+ /* we do this as a normal mime part so we can have it handle transfer encoding etc */
+ sigpart = camel_multipart_get_part((CamelMultipart *)mps, CAMEL_MULTIPART_SIGNED_SIGNATURE);
+
+ /* do the magic, the caller must supply the right context for this kind of object */
+ valid = camel_cipher_verify(context, camel_cipher_id_to_hash(context, mps->micalg), constream, sigpart, ex);
+
+#if 0
+ {
+ CamelStream *sout = camel_stream_fs_new_with_fd(dup(0));
+
+ camel_stream_printf(sout, "-- Verifying:\n");
+ camel_stream_reset(constream);
+ camel_stream_write_to_stream(constream, sout);
+ camel_stream_printf(sout, "-- end\n");
+ camel_object_unref((CamelObject *)sout);
+ }
+#endif
+
+ camel_object_unref(constream);
+
+ return valid;
+#endif
+}
+
+