From d0375813d86145111e6bc5da07e565157de451e9 Mon Sep 17 00:00:00 2001 From: Not Zed Date: Wed, 5 Nov 2003 00:42:40 +0000 Subject: new (unfinished) api to peek inside smime parts to tell us whats in it. 2003-11-05 Not Zed * camel-smime-context.c (camel_smime_context_describe_part): new (unfinished) api to peek inside smime parts to tell us whats in it. 2003-11-03 Not Zed * camel-gpg-context.c (gpg_encrypt): Make this output the full multipart/encrypted part, not just the encrypted content part. * camel-cipher-context.c (camel_cipher_sign): change to output full mime part, not just a stream. (camel_cipher_canonical_to_stream): utility function to canonicalise a mimepart to a stream. * camel-smime-context.c (sm_encode_cmsmessage): removed. (sm_sign): change interface to output a full mime-part, not just a part of a mime part in multipart/signed mode. svn path=/trunk/; revision=23187 --- camel/ChangeLog | 20 +++++ camel/camel-cipher-context.c | 86 ++++++++++++++++++-- camel/camel-cipher-context.h | 7 +- camel/camel-gpg-context.c | 102 ++++++++++++++++++----- camel/camel-multipart-encrypted.c | 6 +- camel/camel-multipart-signed.c | 4 +- camel/camel-smime-context.c | 165 +++++++++++++++++++++----------------- camel/camel-smime-context.h | 8 ++ 8 files changed, 291 insertions(+), 107 deletions(-) diff --git a/camel/ChangeLog b/camel/ChangeLog index d5c01bbca9..a1d59ee9e1 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,3 +1,23 @@ +2003-11-05 Not Zed + + * camel-smime-context.c (camel_smime_context_describe_part): new + (unfinished) api to peek inside smime parts to tell us whats in + it. + +2003-11-03 Not Zed + + * camel-gpg-context.c (gpg_encrypt): Make this output the + full multipart/encrypted part, not just the encrypted content part. + + * camel-cipher-context.c (camel_cipher_sign): change to output + full mime part, not just a stream. + (camel_cipher_canonical_to_stream): utility function to + canonicalise a mimepart to a stream. + + * camel-smime-context.c (sm_encode_cmsmessage): removed. + (sm_sign): change interface to output a full mime-part, not just a + part of a mime part in multipart/signed mode. + 2003-11-04 Jeffrey Stedfast * camel-gpg-context.c (gpg_ctx_parse_status): We might need to diff --git a/camel/camel-cipher-context.c b/camel/camel-cipher-context.c index 212c0fb98c..dff60c25aa 100644 --- a/camel/camel-cipher-context.c +++ b/camel/camel-cipher-context.c @@ -30,6 +30,13 @@ #include "camel-cipher-context.h" #include "camel-stream.h" +#include "camel-mime-utils.h" +#include "camel-medium.h" +#include "camel-multipart.h" +#include "camel-mime-message.h" +#include "camel-mime-filter-canon.h" +#include "camel-stream-filter.h" + #define CIPHER_LOCK(ctx) g_mutex_lock (((CamelCipherContext *) ctx)->priv->lock) #define CIPHER_UNLOCK(ctx) g_mutex_unlock (((CamelCipherContext *) ctx)->priv->lock); @@ -86,7 +93,7 @@ camel_cipher_context_construct (CamelCipherContext *context, CamelSession *sessi static int cipher_sign (CamelCipherContext *ctx, const char *userid, CamelCipherHash hash, - struct _CamelStream *istream, struct _CamelMimePart *sigpart, CamelException *ex) + struct _CamelMimePart *ipart, struct _CamelMimePart *opart, CamelException *ex) { camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Signing is not supported by this cipher")); @@ -98,17 +105,18 @@ cipher_sign (CamelCipherContext *ctx, const char *userid, CamelCipherHash hash, * @context: Cipher Context * @userid: private key to use to sign the stream * @hash: preferred Message-Integrity-Check hash algorithm - * @istream: input stream - * @sigpart: output signature part. + * @ipart: Input part. + * @opart: output part. * @ex: exception * - * Signs the input stream and writes the resulting signature to output @sigpart. + * Converts the (unsigned) part @ipart into a new self-contained mime part @opart. + * This may be a multipart/signed part, or a simple part for enveloped types. * * Return value: 0 for success or -1 for failure. **/ int camel_cipher_sign (CamelCipherContext *context, const char *userid, CamelCipherHash hash, - struct _CamelStream *istream, struct _CamelMimePart *sigpart, CamelException *ex) + struct _CamelMimePart *ipart, struct _CamelMimePart *opart, CamelException *ex) { int retval; @@ -116,7 +124,7 @@ camel_cipher_sign (CamelCipherContext *context, const char *userid, CamelCipherH CIPHER_LOCK(context); - retval = CCC_CLASS (context)->sign (context, userid, hash, istream, sigpart, ex); + retval = CCC_CLASS (context)->sign (context, userid, hash, ipart, opart, ex); CIPHER_UNLOCK(context); @@ -468,3 +476,69 @@ camel_cipher_context_get_type (void) return type; } + +/* 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 +cc_prepare_sign(CamelMimePart *part) +{ + CamelDataWrapper *dw; + CamelTransferEncoding encoding; + int parts, i; + + dw = camel_medium_get_content_object((CamelMedium *)part); + if (!dw) + return; + + if (CAMEL_IS_MULTIPART (dw)) { + parts = camel_multipart_get_number((CamelMultipart *)dw); + for (i = 0; i < parts; i++) + cc_prepare_sign(camel_multipart_get_part((CamelMultipart *)dw, i)); + } else if (CAMEL_IS_MIME_MESSAGE (dw)) { + cc_prepare_sign((CamelMimePart *)dw); + } else { + encoding = camel_mime_part_get_encoding(part); + + if (encoding != CAMEL_TRANSFER_ENCODING_BASE64 + && encoding != CAMEL_TRANSFER_ENCODING_QUOTEDPRINTABLE) { + camel_mime_part_set_encoding(part, CAMEL_TRANSFER_ENCODING_QUOTEDPRINTABLE); + } + } +} + +/** + * camel_cipher_canonical_to_stream: + * @part: Part to write. + * @ostream: stream to write canonicalised output to. + * + * Writes a part to a stream in a canonicalised format, suitable for signing/encrypting. + * + * The transfer encoding paramaters for the part may be changed by this function. + * + * Return value: -1 on error; + **/ +int +camel_cipher_canonical_to_stream(CamelMimePart *part, CamelStream *ostream) +{ + CamelStreamFilter *filter; + CamelMimeFilter *canon; + int res = -1; + + cc_prepare_sign(part); + + filter = camel_stream_filter_new_with_stream(ostream); + canon = 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, canon); + camel_object_unref(canon); + + if (camel_data_wrapper_write_to_stream((CamelDataWrapper *)part, (CamelStream *)filter) != -1 + && camel_stream_flush((CamelStream *)filter) != -1) + res = 0; + + camel_object_unref(filter); + camel_stream_reset(ostream); + + return res; +} diff --git a/camel/camel-cipher-context.h b/camel/camel-cipher-context.h index 5d9218b83e..db83e92438 100644 --- a/camel/camel-cipher-context.h +++ b/camel/camel-cipher-context.h @@ -71,7 +71,7 @@ typedef struct _CamelCipherContextClass { const char * (*hash_to_id)(CamelCipherContext *context, CamelCipherHash hash); int (*sign) (CamelCipherContext *context, const char *userid, CamelCipherHash hash, - struct _CamelStream *istream, struct _CamelMimePart *sigpart, CamelException *ex); + struct _CamelMimePart *ipart, struct _CamelMimePart *opart, CamelException *ex); CamelCipherValidity * (*verify) (CamelCipherContext *context, CamelCipherHash hash, struct _CamelStream *istream, struct _CamelMimePart *sigpart, @@ -107,7 +107,7 @@ const char * camel_cipher_hash_to_id (CamelCipherContext *context, CamelCip /* cipher routines */ int camel_cipher_sign (CamelCipherContext *context, const char *userid, CamelCipherHash hash, - struct _CamelStream *istream, struct _CamelMimePart *sigpart, CamelException *ex); + struct _CamelMimePart *ipart, struct _CamelMimePart *opart, CamelException *ex); CamelCipherValidity *camel_cipher_verify (CamelCipherContext *context, CamelCipherHash hash, struct _CamelStream *istream, struct _CamelMimePart *sigpart, CamelException *ex); @@ -132,6 +132,9 @@ void camel_cipher_validity_set_description (CamelCipherValidity void camel_cipher_validity_clear (CamelCipherValidity *validity); void camel_cipher_validity_free (CamelCipherValidity *validity); +/* utility functions */ +int camel_cipher_canonical_to_stream(CamelMimePart *part, CamelStream *ostream); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/camel/camel-gpg-context.c b/camel/camel-gpg-context.c index ea27ac2926..a3b158d943 100644 --- a/camel/camel-gpg-context.c +++ b/camel/camel-gpg-context.c @@ -52,6 +52,9 @@ #include "camel-mime-part.h" #include "camel-mime-filter-canon.h" +#include "camel-multipart-signed.h" +#include "camel-multipart-encrypted.h" + #define d(x) static CamelCipherContextClass *parent_class = NULL; @@ -1209,14 +1212,26 @@ gpg_ctx_op_wait (struct _GpgCtx *gpg) static int -gpg_sign (CamelCipherContext *context, const char *userid, CamelCipherHash hash, - CamelStream *istream, CamelMimePart *sigpart, CamelException *ex) +gpg_sign (CamelCipherContext *context, const char *userid, CamelCipherHash hash, CamelMimePart *ipart, CamelMimePart *opart, CamelException *ex) { struct _GpgCtx *gpg; - CamelStream *ostream = camel_stream_mem_new(); + CamelStream *ostream = camel_stream_mem_new(), *istream; CamelDataWrapper *dw; CamelContentType *ct; int res = -1; + CamelMimePart *sigpart; + CamelMultipartSigned *mps; + + /* Note: see rfc2015 or rfc3156, section 5 */ + + /* FIXME: stream this, we stream output at least */ + /*prepare_sign(content);*/ + istream = camel_stream_mem_new(); + if (camel_cipher_canonical_to_stream(ipart, 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_SIGN); @@ -1262,6 +1277,7 @@ gpg_sign (CamelCipherContext *context, const char *userid, CamelCipherHash hash, camel_stream_reset(ostream); camel_data_wrapper_construct_from_stream(dw, ostream); + sigpart = camel_mime_part_new(); 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); @@ -1269,8 +1285,23 @@ gpg_sign (CamelCipherContext *context, const char *userid, CamelCipherHash hash, 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")); + mps = camel_multipart_signed_new(); + ct = camel_content_type_new("multipart", "signed"); + camel_content_type_set_param(ct, "micalg", camel_cipher_hash_to_id(context, hash)); + camel_content_type_set_param(ct, "protocol", context->sign_protocol); + camel_data_wrapper_set_mime_type_field((CamelDataWrapper *)mps, ct); + camel_content_type_unref(ct); + camel_multipart_set_boundary((CamelMultipart *)mps, NULL); + + mps->signature = sigpart; + mps->contentraw = istream; + camel_stream_reset(istream); + camel_object_ref(istream); + + camel_medium_set_content_object((CamelMedium *)opart, (CamelDataWrapper *)mps); fail: camel_object_unref(ostream); gpg_ctx_free (gpg); @@ -1397,33 +1428,25 @@ gpg_encrypt (CamelCipherContext *context, const char *userid, GPtrArray *recipie CamelGpgContext *ctx = (CamelGpgContext *) context; struct _GpgCtx *gpg; int i, res = -1; - CamelStream *istream, *filtered_stream, *ostream; - CamelMimeFilter *filter; + CamelStream *istream, *ostream, *vstream; + CamelMimePart *encpart, *verpart; CamelDataWrapper *dw; CamelContentType *ct; + CamelMultipartEncrypted *mpe; 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); + if (camel_cipher_canonical_to_stream(ipart, istream) == -1) { + camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, + _("Could not generate encrypting data: %s"), g_strerror(errno)); + goto fail1; + } 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); @@ -1462,17 +1485,52 @@ gpg_encrypt (CamelCipherContext *context, const char *userid, GPtrArray *recipie res = 0; dw = camel_data_wrapper_new(); + camel_data_wrapper_construct_from_stream(dw, ostream); + + encpart = camel_mime_part_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_medium_set_content_object((CamelMedium *)encpart, dw); camel_object_unref(dw); + camel_mime_part_set_description(encpart, _("This is a digitally encrypted message part")); + + vstream = camel_stream_mem_new(); + camel_stream_write(vstream, "Version: 1\n", strlen("Version: 1\n")); + camel_stream_reset(vstream); + + verpart = camel_mime_part_new(); + dw = camel_data_wrapper_new(); + camel_data_wrapper_set_mime_type(dw, context->encrypt_protocol); + camel_data_wrapper_construct_from_stream(dw, vstream); + camel_object_unref(vstream); + camel_medium_set_content_object((CamelMedium *)verpart, dw); + camel_object_unref(dw); + + mpe = camel_multipart_encrypted_new(); + ct = camel_content_type_new("multipart", "encrypted"); + camel_content_type_set_param(ct, "protocol", context->sign_protocol); + camel_data_wrapper_set_mime_type_field((CamelDataWrapper *)mpe, ct); + camel_content_type_unref(ct); + camel_multipart_set_boundary((CamelMultipart *)mpe, NULL); + + mpe->decrypted = ipart; + camel_object_ref(ipart); + + camel_multipart_add_part((CamelMultipart *)mpe, verpart); + camel_object_unref(verpart); + camel_multipart_add_part((CamelMultipart *)mpe, encpart); + camel_object_unref(encpart); + + camel_medium_set_content_object((CamelMedium *)opart, (CamelDataWrapper *)mpe); fail: - camel_object_unref(ostream); gpg_ctx_free(gpg); +fail1: + camel_object_unref(istream); + camel_object_unref(ostream); return res; } diff --git a/camel/camel-multipart-encrypted.c b/camel/camel-multipart-encrypted.c index d906ae80fc..2dfe3b4914 100644 --- a/camel/camel-multipart-encrypted.c +++ b/camel/camel-multipart-encrypted.c @@ -142,6 +142,9 @@ camel_multipart_encrypted_encrypt (CamelMultipartEncrypted *mpe, CamelMimePart * CamelCipherContext *cipher, const char *userid, GPtrArray *recipients, CamelException *ex) { + abort(); + +#if 0 CamelMimePart *version_part, *encrypted_part; CamelContentType *mime_type; CamelDataWrapper *wrapper; @@ -189,7 +192,8 @@ camel_multipart_encrypted_encrypt (CamelMultipartEncrypted *mpe, CamelMimePart * camel_data_wrapper_set_mime_type_field (CAMEL_DATA_WRAPPER (mpe), mime_type); camel_content_type_unref (mime_type); camel_multipart_set_boundary ((CamelMultipart *) mpe, NULL); - +#endif + return 0; } diff --git a/camel/camel-multipart-signed.c b/camel/camel-multipart-signed.c index bc5e363c8d..2647ba6591 100644 --- a/camel/camel-multipart-signed.c +++ b/camel/camel-multipart-signed.c @@ -592,6 +592,8 @@ prepare_sign(CamelMimePart *mime_part) 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; @@ -649,7 +651,7 @@ camel_multipart_signed_sign(CamelMultipartSigned *mps, CamelCipherContext *conte camel_object_unref((CamelObject *) ((CamelDataWrapper *)mps)->stream); ((CamelDataWrapper *)mps)->stream = NULL; } - +#endif return 0; } diff --git a/camel/camel-smime-context.c b/camel/camel-smime-context.c index 9fad5a1f11..75cbba9e2b 100644 --- a/camel/camel-smime-context.c +++ b/camel/camel-smime-context.c @@ -39,11 +39,14 @@ #include #include +#include + #include #include #include #include +#include #include #include #include @@ -105,6 +108,12 @@ camel_smime_context_set_sign_mode(CamelSMIMEContext *context, camel_smime_sign_t context->priv->sign_mode = type; } +guint32 +camel_smime_context_describe_part(CamelSMIMEContext *context, CamelMimePart *part) +{ + return 0; +} + static const char * sm_hash_to_id(CamelCipherContext *context, CamelCipherHash hash) { @@ -307,13 +316,44 @@ fail: } static int -sm_encode_cmsmessage(CamelSMIMEContext *context, NSSCMSMessage *cmsg, CamelStream *instream, CamelStream *out, CamelException *ex) +sm_sign(CamelCipherContext *context, const char *userid, CamelCipherHash hash, CamelMimePart *ipart, CamelMimePart *opart, CamelException *ex) { + int res = -1; + NSSCMSMessage *cmsg; + CamelStream *ostream, *istream; + SECOidTag sechash; NSSCMSEncoderContext *enc; - CamelStreamMem *mem = NULL; + CamelDataWrapper *dw; + CamelContentType *ct; + + switch (hash) { + case CAMEL_CIPHER_HASH_SHA1: + case CAMEL_CIPHER_HASH_DEFAULT: + default: + sechash = SEC_OID_SHA1; + break; + case CAMEL_CIPHER_HASH_MD5: + sechash = SEC_OID_MD5; + break; + } + + cmsg = sm_signing_cmsmessage((CamelSMIMEContext *)context, userid, sechash, + ((CamelSMIMEContext *)context)->priv->sign_mode == CAMEL_SMIME_SIGN_CLEARSIGN, ex); + if (cmsg == NULL) + return -1; + + ostream = camel_stream_mem_new(); + + /* FIXME: stream this, we stream output at least */ + istream = camel_stream_mem_new(); + if (camel_cipher_canonical_to_stream(ipart, istream) == -1) { + camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, + _("Could not generate signing data: %s"), g_strerror(errno)); + goto fail; + } enc = NSS_CMSEncoder_Start(cmsg, - sm_write_stream, out, /* DER output callback */ + sm_write_stream, ostream, /* DER output callback */ NULL, NULL, /* destination storage */ sm_get_passwd, context, /* password callback */ NULL, NULL, /* decrypt key callback */ @@ -323,13 +363,7 @@ sm_encode_cmsmessage(CamelSMIMEContext *context, NSSCMSMessage *cmsg, CamelStrea goto fail; } - /* Note: see rfc2015 or rfc3156, section 5 */ - - /* FIXME: stream this, we stream output at least */ - mem = (CamelStreamMem *)camel_stream_mem_new(); - camel_stream_write_to_stream(instream, (CamelStream *)mem); - - if (NSS_CMSEncoder_Update(enc, mem->buffer->data, mem->buffer->len) != SECSuccess) { + if (NSS_CMSEncoder_Update(enc, ((CamelStreamMem *)istream)->buffer->data, ((CamelStreamMem *)istream)->buffer->len) != SECSuccess) { NSS_CMSEncoder_Cancel(enc); camel_exception_setv(ex, 1, "Failed to add data to CMS encoder"); goto fail; @@ -340,81 +374,62 @@ sm_encode_cmsmessage(CamelSMIMEContext *context, NSSCMSMessage *cmsg, CamelStrea goto fail; } - camel_object_unref(mem); - - return 0; - -fail: - if (mem) - camel_object_unref(mem); + res = 0; - return -1; -} - -static int -sm_sign(CamelCipherContext *ctx, const char *userid, CamelCipherHash hash, CamelStream *istream, CamelMimePart *sigpart, CamelException *ex) -{ - int res; - NSSCMSMessage *cmsg; - CamelStream *ostream; - SECOidTag sechash; - - switch (hash) { - case CAMEL_CIPHER_HASH_SHA1: - case CAMEL_CIPHER_HASH_DEFAULT: - default: - sechash = SEC_OID_SHA1; - break; - case CAMEL_CIPHER_HASH_MD5: - sechash = SEC_OID_MD5; - break; - } - - cmsg = sm_signing_cmsmessage((CamelSMIMEContext *)ctx, userid, sechash, - ((CamelSMIMEContext *)ctx)->priv->sign_mode == CAMEL_SMIME_SIGN_CLEARSIGN, ex); - if (cmsg == NULL) - return -1; - - ostream = camel_stream_mem_new(); - res = sm_encode_cmsmessage((CamelSMIMEContext *)ctx, cmsg, istream, ostream, ex); - NSS_CMSMessage_Destroy(cmsg); - - if (res == 0) { - CamelDataWrapper *dw; - CamelContentType *ct; + dw = camel_data_wrapper_new(); + camel_stream_reset(ostream); + camel_data_wrapper_construct_from_stream(dw, ostream); + dw->encoding = CAMEL_TRANSFER_ENCODING_BINARY; - dw = camel_data_wrapper_new(); - camel_stream_reset(ostream); - camel_data_wrapper_construct_from_stream(dw, ostream); - dw->encoding = CAMEL_TRANSFER_ENCODING_BINARY; + if (((CamelSMIMEContext *)context)->priv->sign_mode == CAMEL_SMIME_SIGN_CLEARSIGN) { + CamelMultipartSigned *mps; + CamelMimePart *sigpart; - if (((CamelSMIMEContext *)ctx)->priv->sign_mode == CAMEL_SMIME_SIGN_CLEARSIGN) { - ct = camel_content_type_new("application", "x-pkcs7-signature"); - camel_content_type_set_param(ct, "name", "smime.p7s"); - camel_data_wrapper_set_mime_type_field(dw, ct); - camel_content_type_unref(ct); + sigpart = camel_mime_part_new(); + ct = camel_content_type_new("application", "x-pkcs7-signature"); + camel_content_type_set_param(ct, "name", "smime.p7s"); + camel_data_wrapper_set_mime_type_field(dw, ct); + camel_content_type_unref(ct); - camel_mime_part_set_filename(sigpart, "smime.p7s"); - } else { - ct = camel_content_type_new("application", "x-pkcs7-mime"); - camel_content_type_set_param(ct, "name", "smime.p7m"); - camel_content_type_set_param(ct, "smime-type", "signed-data"); - camel_data_wrapper_set_mime_type_field(dw, ct); - camel_content_type_unref(ct); - - camel_mime_part_set_filename(sigpart, "smime.p7m"); - camel_mime_part_set_description(sigpart, "S/MIME Signed Message"); - } + camel_medium_set_content_object((CamelMedium *)sigpart, dw); + camel_mime_part_set_filename(sigpart, "smime.p7s"); camel_mime_part_set_disposition(sigpart, "attachment"); camel_mime_part_set_encoding(sigpart, CAMEL_TRANSFER_ENCODING_BASE64); - camel_medium_set_content_object((CamelMedium *)sigpart, dw); - camel_object_unref(dw); + mps = camel_multipart_signed_new(); + ct = camel_content_type_new("multipart", "signed"); + camel_content_type_set_param(ct, "micalg", camel_cipher_hash_to_id(context, hash)); + camel_content_type_set_param(ct, "protocol", context->sign_protocol); + camel_data_wrapper_set_mime_type_field((CamelDataWrapper *)mps, ct); + camel_content_type_unref(ct); + camel_multipart_set_boundary((CamelMultipart *)mps, NULL); + + mps->signature = sigpart; + mps->contentraw = istream; + camel_stream_reset(istream); + camel_object_ref(istream); + + camel_medium_set_content_object((CamelMedium *)opart, (CamelDataWrapper *)mps); + } else { + ct = camel_content_type_new("application", "x-pkcs7-mime"); + camel_content_type_set_param(ct, "name", "smime.p7m"); + camel_content_type_set_param(ct, "smime-type", "signed-data"); + camel_data_wrapper_set_mime_type_field(dw, ct); + camel_content_type_unref(ct); + + camel_medium_set_content_object((CamelMedium *)opart, dw); + + camel_mime_part_set_filename(opart, "smime.p7m"); + camel_mime_part_set_description(opart, "S/MIME Signed Message"); + camel_mime_part_set_disposition(opart, "attachment"); + camel_mime_part_set_encoding(opart, CAMEL_TRANSFER_ENCODING_BASE64); } - - + + camel_object_unref(dw); +fail: camel_object_unref(ostream); + camel_object_unref(istream); return res; } diff --git a/camel/camel-smime-context.h b/camel/camel-smime-context.h index a68d5e1646..f0e8d45c3b 100644 --- a/camel/camel-smime-context.h +++ b/camel/camel-smime-context.h @@ -41,6 +41,12 @@ typedef enum _camel_smime_sign_t { CAMEL_SMIME_SIGN_ENVELOPED } camel_smime_sign_t; +typedef enum _camel_smime_describe_t { + CAMEL_SMIME_SIGNED = 1, + CAMEL_SMIME_ENCRYPTED = 2, + CAMEL_SMIME_CERTS = 4, +} camel_smime_describe_t; + typedef struct _CamelSMIMEContext CamelSMIMEContext; typedef struct _CamelSMIMEContextClass CamelSMIMEContextClass; @@ -63,6 +69,8 @@ void camel_smime_context_set_encrypt_key(CamelSMIMEContext *context, gboolean us /* set signing mode, clearsigned multipart/signed or enveloped */ void camel_smime_context_set_sign_mode(CamelSMIMEContext *context, camel_smime_sign_t type); +guint32 camel_smime_context_describe_part(CamelSMIMEContext *, struct _CamelMimePart *); + #ifdef __cplusplus } #endif /* __cplusplus */ -- cgit v1.2.3