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:
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user