new (unfinished) api to peek inside smime parts to tell us whats in it.

2003-11-05  Not Zed  <NotZed@Ximian.com>

        * 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  <NotZed@Ximian.com>

        * 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
This commit is contained in:
Not Zed
2003-11-05 00:42:40 +00:00
committed by Michael Zucci
parent 0c29bfd43c
commit d0375813d8
8 changed files with 294 additions and 110 deletions

View File

@ -1,3 +1,23 @@
2003-11-05 Not Zed <NotZed@Ximian.com>
* 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 <NotZed@Ximian.com>
* 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 <fejj@ximian.com>
* camel-gpg-context.c (gpg_ctx_parse_status): We might need to

View File

@ -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;
}

View File

@ -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 */

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -39,11 +39,14 @@
#include <pkcs11t.h>
#include <pk11func.h>
#include <errno.h>
#include <camel/camel-exception.h>
#include <camel/camel-stream-mem.h>
#include <camel/camel-data-wrapper.h>
#include <camel/camel-mime-part.h>
#include <camel/camel-multipart-signed.h>
#include <camel/camel-stream-fs.h>
#include <camel/camel-stream-filter.h>
#include <camel/camel-mime-filter-basic.h>
@ -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,57 +316,15 @@ 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)
{
NSSCMSEncoderContext *enc;
CamelStreamMem *mem = NULL;
enc = NSS_CMSEncoder_Start(cmsg,
sm_write_stream, out, /* DER output callback */
NULL, NULL, /* destination storage */
sm_get_passwd, context, /* password callback */
NULL, NULL, /* decrypt key callback */
NULL, NULL ); /* detached digests */
if (!enc) {
camel_exception_setv(ex, 1, "Cannot create encoder context");
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) {
NSS_CMSEncoder_Cancel(enc);
camel_exception_setv(ex, 1, "Failed to add data to CMS encoder");
goto fail;
}
if (NSS_CMSEncoder_Finish(enc) != SECSuccess) {
camel_exception_setv(ex, 1, "Failed to encode data");
goto fail;
}
camel_object_unref(mem);
return 0;
fail:
if (mem)
camel_object_unref(mem);
return -1;
}
static int
sm_sign(CamelCipherContext *ctx, const char *userid, CamelCipherHash hash, CamelStream *istream, CamelMimePart *sigpart, CamelException *ex)
{
int res;
int res = -1;
NSSCMSMessage *cmsg;
CamelStream *ostream;
CamelStream *ostream, *istream;
SECOidTag sechash;
NSSCMSEncoderContext *enc;
CamelDataWrapper *dw;
CamelContentType *ct;
switch (hash) {
case CAMEL_CIPHER_HASH_SHA1:
@ -370,51 +337,99 @@ sm_sign(CamelCipherContext *ctx, const char *userid, CamelCipherHash hash, Camel
break;
}
cmsg = sm_signing_cmsmessage((CamelSMIMEContext *)ctx, userid, sechash,
((CamelSMIMEContext *)ctx)->priv->sign_mode == CAMEL_SMIME_SIGN_CLEARSIGN, ex);
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();
res = sm_encode_cmsmessage((CamelSMIMEContext *)ctx, cmsg, istream, ostream, ex);
NSS_CMSMessage_Destroy(cmsg);
if (res == 0) {
CamelDataWrapper *dw;
CamelContentType *ct;
/* 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;
}
dw = camel_data_wrapper_new();
camel_stream_reset(ostream);
camel_data_wrapper_construct_from_stream(dw, ostream);
dw->encoding = CAMEL_TRANSFER_ENCODING_BINARY;
enc = NSS_CMSEncoder_Start(cmsg,
sm_write_stream, ostream, /* DER output callback */
NULL, NULL, /* destination storage */
sm_get_passwd, context, /* password callback */
NULL, NULL, /* decrypt key callback */
NULL, NULL ); /* detached digests */
if (!enc) {
camel_exception_setv(ex, 1, "Cannot create encoder context");
goto fail;
}
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);
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;
}
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);
if (NSS_CMSEncoder_Finish(enc) != SECSuccess) {
camel_exception_setv(ex, 1, "Failed to encode data");
goto fail;
}
camel_mime_part_set_filename(sigpart, "smime.p7m");
camel_mime_part_set_description(sigpart, "S/MIME Signed Message");
}
res = 0;
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;
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_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;
}

View File

@ -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 */