aboutsummaryrefslogtreecommitdiffstats
path: root/camel/camel-smime-context.c
diff options
context:
space:
mode:
Diffstat (limited to 'camel/camel-smime-context.c')
-rw-r--r--camel/camel-smime-context.c999
1 files changed, 0 insertions, 999 deletions
diff --git a/camel/camel-smime-context.c b/camel/camel-smime-context.c
deleted file mode 100644
index 9ba1d2be74..0000000000
--- a/camel/camel-smime-context.c
+++ /dev/null
@@ -1,999 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Authors: Jeffrey Stedfast <fejj@ximian.com>
- *
- * Copyright 2001 Ximian, Inc. (www.ximian.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef HAVE_NSS
-#include "camel-smime-context.h"
-
-#include "camel-mime-filter-from.h"
-#include "camel-mime-filter-crlf.h"
-#include "camel-stream-filter.h"
-#include "camel-stream-fs.h"
-#include "camel-stream-mem.h"
-#include "camel-mime-part.h"
-#include "camel-multipart.h"
-
-#include "nss.h"
-#include <cms.h>
-#include <cert.h>
-#include <certdb.h>
-#include <pkcs11.h>
-#include <smime.h>
-
-#define d(x)
-
-struct _CamelSMimeContextPrivate {
- CERTCertDBHandle *certdb;
-};
-
-
-static CamelMimeMessage *smime_sign (CamelCMSContext *ctx, CamelMimeMessage *message,
- const char *userid, gboolean signing_time,
- gboolean detached, CamelException *ex);
-
-static CamelMimeMessage *smime_certsonly (CamelCMSContext *ctx, CamelMimeMessage *message,
- const char *userid, GPtrArray *recipients,
- CamelException *ex);
-
-static CamelMimeMessage *smime_encrypt (CamelCMSContext *ctx, CamelMimeMessage *message,
- const char *userid, GPtrArray *recipients,
- CamelException *ex);
-
-static CamelMimeMessage *smime_envelope (CamelCMSContext *ctx, CamelMimeMessage *message,
- const char *userid, GPtrArray *recipients,
- CamelException *ex);
-
-static CamelMimeMessage *smime_decode (CamelCMSContext *ctx, CamelMimeMessage *message,
- CamelCMSValidityInfo **info, CamelException *ex);
-
-static CamelCMSContextClass *parent_class;
-
-static void
-camel_smime_context_init (CamelSMimeContext *context)
-{
- context->priv = g_new0 (struct _CamelSMimeContextPrivate, 1);
-}
-
-static void
-camel_smime_context_finalise (CamelObject *o)
-{
- CamelSMimeContext *context = (CamelSMimeContext *)o;
-
- g_free (context->encryption_key);
- g_free (context->priv);
-}
-
-static void
-camel_smime_context_class_init (CamelSMimeContextClass *camel_smime_context_class)
-{
- CamelCMSContextClass *camel_cms_context_class =
- CAMEL_CMS_CONTEXT_CLASS (camel_smime_context_class);
-
- parent_class = CAMEL_CMS_CONTEXT_CLASS (camel_type_get_global_classfuncs (camel_cms_context_get_type ()));
-
- camel_cms_context_class->sign = smime_sign;
- camel_cms_context_class->certsonly = smime_certsonly;
- camel_cms_context_class->encrypt = smime_encrypt;
- camel_cms_context_class->envelope = smime_envelope;
- camel_cms_context_class->decode = smime_decode;
-}
-
-CamelType
-camel_smime_context_get_type (void)
-{
- static CamelType type = CAMEL_INVALID_TYPE;
-
- if (type == CAMEL_INVALID_TYPE) {
- type = camel_type_register (camel_cms_context_get_type (),
- "CamelSMimeContext",
- sizeof (CamelSMimeContext),
- sizeof (CamelSMimeContextClass),
- (CamelObjectClassInitFunc) camel_smime_context_class_init,
- NULL,
- (CamelObjectInitFunc) camel_smime_context_init,
- (CamelObjectFinalizeFunc) camel_smime_context_finalise);
- }
-
- return type;
-}
-
-
-/**
- * camel_smime_context_new:
- * @session: CamelSession
- * @encryption_key: preferred encryption key (used when attaching cert chains to messages)
- *
- * This creates a new CamelSMimeContext object which is used to sign,
- * verify, encrypt and decrypt streams.
- *
- * Return value: the new CamelSMimeContext
- **/
-CamelSMimeContext *
-camel_smime_context_new (CamelSession *session, const char *encryption_key)
-{
- CamelSMimeContext *context;
- CERTCertDBHandle *certdb;
-
- g_return_val_if_fail (session != NULL, NULL);
- g_return_val_if_fail (CAMEL_IS_SESSION (session), NULL);
-
- certdb = CERT_GetDefaultCertDB ();
- if (!certdb)
- return NULL;
-
- context = CAMEL_SMIME_CONTEXT (camel_object_new (CAMEL_SMIME_CONTEXT_TYPE));
-
- camel_cms_context_construct (CAMEL_CMS_CONTEXT (context), session);
-
- context->encryption_key = g_strdup (encryption_key);
- context->priv->certdb = certdb;
-
- return context;
-}
-
-
-struct _GetPasswdData {
- CamelSession *session;
- const char *userid;
- CamelException *ex;
-};
-
-static char *
-smime_get_password (PK11SlotInfo *info, PRBool retry, void *arg)
-{
- CamelSession *session = ((struct _GetPasswdData *)arg)->session;
- const char *userid = ((struct _GetPasswdData *)arg)->userid;
- CamelException *ex = ((struct _GetPasswdData *)arg)->ex;
- char *prompt, *passwd, *ret;
-
- prompt = g_strdup_printf (_("Please enter your password for %s"), userid);
- passwd = camel_session_get_password (session, prompt, FALSE, TRUE,
- NULL, userid, ex);
- g_free (prompt);
-
- ret = PL_strdup (passwd);
- g_free (passwd);
-
- return ret;
-}
-
-static PK11SymKey *
-decode_key_cb (void *arg, SECAlgorithmID *algid)
-{
- return (PK11SymKey *)arg;
-}
-
-
-static NSSCMSMessage *
-signed_data (CamelSMimeContext *ctx, const char *userid, gboolean signing_time,
- gboolean detached, CamelException *ex)
-{
- NSSCMSMessage *cmsg = NULL;
- NSSCMSContentInfo *cinfo;
- NSSCMSSignedData *sigd;
- NSSCMSSignerInfo *signerinfo;
- CERTCertificate *cert, *ekpcert;
-
- if (!userid) {
- camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Please indicate the nickname of a certificate to sign with."));
- return NULL;
- }
-
- if ((cert = CERT_FindCertByNickname (ctx->priv->certdb, (char *) userid)) == NULL) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("The signature certificate for \"%s\" does not exist."),
- userid);
- return NULL;
- }
-
- /* create the cms message object */
- cmsg = NSS_CMSMessage_Create (NULL);
-
- /* build chain of objects: message->signedData->data */
- sigd = NSS_CMSSignedData_Create (cmsg);
-
- cinfo = NSS_CMSMessage_GetContentInfo (cmsg);
- NSS_CMSContentInfo_SetContent_SignedData (cmsg, cinfo, sigd);
-
- cinfo = NSS_CMSSignedData_GetContentInfo (sigd);
-
- /* speciffy whether we want detached signatures or not */
- NSS_CMSContentInfo_SetContent_Data (cmsg, cinfo, NULL, detached);
-
- /* create & attach signer information */
- signerinfo = NSS_CMSSignerInfo_Create (cmsg, cert, SEC_OID_SHA1);
-
- /* include the cert chain */
- NSS_CMSSignerInfo_IncludeCerts (signerinfo, NSSCMSCM_CertChain,
- certUsageEmailSigner);
-
- if (signing_time) {
- NSS_CMSSignerInfo_AddSigningTime (signerinfo, PR_Now ());
- }
-
- if (TRUE) {
- /* Add S/MIME Capabilities */
- NSS_CMSSignerInfo_AddSMIMECaps (signerinfo);
- }
-
- if (ctx->encryption_key) {
- /* get the cert, add it to the message */
- ekpcert = CERT_FindCertByNickname (ctx->priv->certdb, ctx->encryption_key);
- if (!ekpcert) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("The encryption certificate for \"%s\" does not exist."),
- ctx->encryption_key);
- goto exception;
- }
-
- NSS_CMSSignerInfo_AddSMIMEEncKeyPrefs (signerinfo, ekpcert, ctx->priv->certdb);
-
- NSS_CMSSignedData_AddCertificate (sigd, ekpcert);
- } else {
- /* check signing cert for fitness as encryption cert */
- /* if yes, add signing cert as EncryptionKeyPreference */
- NSS_CMSSignerInfo_AddSMIMEEncKeyPrefs (signerinfo, cert, ctx->priv->certdb);
- }
-
- NSS_CMSSignedData_AddSignerInfo (sigd, signerinfo);
-
- return cmsg;
-
- exception:
-
- NSS_CMSMessage_Destroy (cmsg);
-
- return NULL;
-}
-
-static void
-smime_sign_restore (CamelMimePart *mime_part, GSList **encodings)
-{
- CamelDataWrapper *wrapper;
-
- wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part));
- if (!wrapper)
- return;
-
- if (CAMEL_IS_MULTIPART (wrapper)) {
- int parts, i;
-
- parts = camel_multipart_get_number (CAMEL_MULTIPART (wrapper));
- for (i = 0; i < parts; i++) {
- CamelMimePart *part = camel_multipart_get_part (CAMEL_MULTIPART (wrapper), i);
-
- smime_sign_restore (part, encodings);
- *encodings = (*encodings)->next;
- }
- } else {
- CamelMimePartEncodingType encoding;
-
- if (CAMEL_IS_MIME_MESSAGE (wrapper)) {
- /* restore the message parts' subparts */
- smime_sign_restore (CAMEL_MIME_PART (wrapper), encodings);
- } else {
- encoding = GPOINTER_TO_INT ((*encodings)->data);
-
- camel_mime_part_set_encoding (mime_part, encoding);
- }
- }
-}
-
-static void
-smime_sign_prepare (CamelMimePart *mime_part, GSList **encodings)
-{
- CamelDataWrapper *wrapper;
- 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 (CAMEL_MULTIPART (wrapper));
- for (i = 0; i < parts; i++) {
- CamelMimePart *part = camel_multipart_get_part (CAMEL_MULTIPART (wrapper), i);
-
- smime_sign_prepare (part, encodings);
- }
- } else {
- CamelMimePartEncodingType encoding;
-
- if (CAMEL_IS_MIME_MESSAGE (wrapper)) {
- /* prepare the message parts' subparts */
- smime_sign_prepare (CAMEL_MIME_PART (wrapper), encodings);
- } else {
- encoding = camel_mime_part_get_encoding (mime_part);
-
- /* FIXME: find the best encoding for this part and use that instead?? */
- /* the encoding should really be QP or Base64 */
- if (encoding != CAMEL_MIME_PART_ENCODING_BASE64)
- camel_mime_part_set_encoding (mime_part, CAMEL_MIME_PART_ENCODING_QUOTEDPRINTABLE);
-
- *encodings = g_slist_append (*encodings, GINT_TO_POINTER (encoding));
- }
- }
-}
-
-
-static CamelMimeMessage *
-smime_sign (CamelCMSContext *ctx, CamelMimeMessage *message,
- const char *userid, gboolean signing_time,
- gboolean detached, CamelException *ex)
-{
- CamelMimeMessage *mesg = NULL;
- NSSCMSMessage *cmsg = NULL;
- struct _GetPasswdData *data;
- PLArenaPool *arena;
- NSSCMSEncoderContext *ecx;
- SECItem output = { 0, 0, 0 };
- CamelStream *stream;
- GSList *list, *encodings = NULL;
- GByteArray *buf;
-
- cmsg = signed_data (CAMEL_SMIME_CONTEXT (ctx), userid, signing_time, detached, ex);
- if (!cmsg)
- return NULL;
-
- arena = PORT_NewArena (1024);
- data = g_new (struct _GetPasswdData, 1);
- data->session = ctx->session;
- data->userid = userid;
- data->ex = ex;
- ecx = NSS_CMSEncoder_Start (cmsg, NULL, NULL, &output, arena,
- smime_get_password, data, NULL, NULL,
- NULL, NULL);
-
- stream = camel_stream_mem_new ();
-
- smime_sign_prepare (CAMEL_MIME_PART (message), &encodings);
- camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (message), stream);
- list = encodings;
- smime_sign_restore (CAMEL_MIME_PART (message), &list);
- g_slist_free (encodings);
-
- buf = CAMEL_STREAM_MEM (stream)->buffer;
-
- NSS_CMSEncoder_Update (ecx, buf->data, buf->len);
- NSS_CMSEncoder_Finish (ecx);
-
- camel_object_unref (CAMEL_OBJECT (stream));
- g_free (data);
-
- /* write the result to a camel stream */
- stream = camel_stream_mem_new ();
- camel_stream_write (stream, output.data, output.len);
- PORT_FreeArena (arena, PR_FALSE);
-
- NSS_CMSMessage_Destroy (cmsg);
-
- /* parse the stream into a new CamelMimeMessage */
- mesg = camel_mime_message_new ();
- camel_stream_reset (stream);
- camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (mesg), stream);
- camel_object_unref (CAMEL_OBJECT (stream));
-
- return mesg;
-}
-
-
-static NSSCMSMessage *
-certsonly_data (CamelSMimeContext *ctx, const char *userid, GPtrArray *recipients, CamelException *ex)
-{
- NSSCMSMessage *cmsg = NULL;
- NSSCMSContentInfo *cinfo;
- NSSCMSSignedData *sigd;
- CERTCertificate **rcerts;
- int i = 0;
-
- /* find the signer's and the recipients' certs */
- rcerts = g_new (CERTCertificate *, recipients->len + 2);
- rcerts[0] = CERT_FindCertByNicknameOrEmailAddr (ctx->priv->certdb, (char *) userid);
- if (!rcerts[0]) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Failed to find certificate for \"%s\"."),
- recipients->pdata[i]);
- goto exception;
- }
-
- for (i = 0; i < recipients->len; i++) {
- rcerts[i + 1] = CERT_FindCertByNicknameOrEmailAddr (ctx->priv->certdb,
- recipients->pdata[i]);
-
- if (!rcerts[i + 1]) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Failed to find certificate for \"%s\"."),
- recipients->pdata[i]);
- goto exception;
- }
- }
- rcerts[i + 1] = NULL;
-
- /* create the cms message object */
- cmsg = NSS_CMSMessage_Create (NULL);
-
- sigd = NSS_CMSSignedData_CreateCertsOnly (cmsg, rcerts[0], PR_TRUE);
-
- /* add the recipient cert chain */
- for (i = 0; i < recipients->len; i++) {
- NSS_CMSSignedData_AddCertChain (sigd, rcerts[i]);
- }
-
- cinfo = NSS_CMSMessage_GetContentInfo (cmsg);
- NSS_CMSContentInfo_SetContent_SignedData (cmsg, cinfo, sigd);
-
- cinfo = NSS_CMSSignedData_GetContentInfo (sigd);
- NSS_CMSContentInfo_SetContent_Data (cmsg, cinfo, NULL, PR_FALSE);
-
- g_free (rcerts);
-
- return cmsg;
-
- exception:
-
- NSS_CMSMessage_Destroy (cmsg);
-
- g_free (rcerts);
-
- return NULL;
-}
-
-static CamelMimeMessage *
-smime_certsonly (CamelCMSContext *ctx, CamelMimeMessage *message,
- const char *userid, GPtrArray *recipients,
- CamelException *ex)
-{
- CamelMimeMessage *mesg = NULL;
- struct _GetPasswdData *data;
- NSSCMSMessage *cmsg = NULL;
- PLArenaPool *arena;
- NSSCMSEncoderContext *ecx;
- SECItem output = { 0, 0, 0 };
- CamelStream *stream;
- GByteArray *buf;
-
- cmsg = certsonly_data (CAMEL_SMIME_CONTEXT (ctx), userid, recipients, ex);
- if (!cmsg)
- return NULL;
-
- arena = PORT_NewArena (1024);
- data = g_new (struct _GetPasswdData, 1);
- data->session = ctx->session;
- data->userid = userid;
- data->ex = ex;
- ecx = NSS_CMSEncoder_Start (cmsg, NULL, NULL, &output, arena,
- smime_get_password, data, NULL, NULL,
- NULL, NULL);
-
- stream = camel_stream_mem_new ();
- camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (message), stream);
- buf = CAMEL_STREAM_MEM (stream)->buffer;
-
- NSS_CMSEncoder_Update (ecx, buf->data, buf->len);
- NSS_CMSEncoder_Finish (ecx);
-
- camel_object_unref (CAMEL_OBJECT (stream));
- g_free (data);
-
- /* write the result to a camel stream */
- stream = camel_stream_mem_new ();
- camel_stream_write (stream, output.data, output.len);
- PORT_FreeArena (arena, PR_FALSE);
-
- NSS_CMSMessage_Destroy (cmsg);
-
- /* parse the stream into a new CamelMimeMessage */
- mesg = camel_mime_message_new ();
- camel_stream_reset (stream);
- camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (mesg), stream);
- camel_object_unref (CAMEL_OBJECT (stream));
-
- return mesg;
-}
-
-
-static NSSCMSMessage *
-enveloped_data (CamelSMimeContext *ctx, const char *userid, GPtrArray *recipients, CamelException *ex)
-{
- NSSCMSMessage *cmsg = NULL;
- NSSCMSContentInfo *cinfo;
- NSSCMSEnvelopedData *envd;
- NSSCMSRecipientInfo *rinfo;
- CERTCertificate **rcerts;
- SECOidTag bulkalgtag;
- int keysize, i;
-
- /* find the recipient certs by email address or nickname */
- rcerts = g_new (CERTCertificate *, recipients->len + 2);
- rcerts[0] = CERT_FindCertByNicknameOrEmailAddr (ctx->priv->certdb, (char *) userid);
- if (!rcerts[0]) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Failed to find certificate for \"%s\"."),
- userid);
- goto exception;
- }
-
- for (i = 0; i < recipients->len; i++) {
- rcerts[i + 1] = CERT_FindCertByNicknameOrEmailAddr (ctx->priv->certdb,
- recipients->pdata[i]);
- if (!rcerts[i + 1]) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Failed to find certificate for \"%s\"."),
- recipients->pdata[i]);
- goto exception;
- }
- }
- rcerts[i + 1] = NULL;
-
- /* find a nice bulk algorithm */
- if (!NSS_SMIMEUtil_FindBulkAlgForRecipients (rcerts, &bulkalgtag, &keysize)) {
- camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Failed to find a common bulk algorithm."));
- goto exception;
- }
-
- /* create a cms message object */
- cmsg = NSS_CMSMessage_Create (NULL);
-
- envd = NSS_CMSEnvelopedData_Create (cmsg, bulkalgtag, keysize);
- cinfo = NSS_CMSMessage_GetContentInfo (cmsg);
- NSS_CMSContentInfo_SetContent_EnvelopedData (cmsg, cinfo, envd);
-
- cinfo = NSS_CMSEnvelopedData_GetContentInfo (envd);
- NSS_CMSContentInfo_SetContent_Data (cmsg, cinfo, NULL, PR_FALSE);
-
- /* create & attach recipient information */
- for (i = 0; rcerts[i] != NULL; i++) {
- rinfo = NSS_CMSRecipientInfo_Create (cmsg, rcerts[i]);
- NSS_CMSEnvelopedData_AddRecipient (envd, rinfo);
- }
-
- g_free (rcerts);
-
- return cmsg;
-
- exception:
-
- NSS_CMSMessage_Destroy (cmsg);
-
- g_free (rcerts);
-
- return NULL;
-}
-
-static CamelMimeMessage *
-smime_envelope (CamelCMSContext *ctx, CamelMimeMessage *message,
- const char *userid, GPtrArray *recipients,
- CamelException *ex)
-{
- CamelMimeMessage *mesg = NULL;
- struct _GetPasswdData *data;
- NSSCMSMessage *cmsg = NULL;
- PLArenaPool *arena;
- NSSCMSEncoderContext *ecx;
- SECItem output = { 0, 0, 0 };
- CamelStream *stream;
- GByteArray *buf;
-
- cmsg = enveloped_data (CAMEL_SMIME_CONTEXT (ctx), userid, recipients, ex);
- if (!cmsg)
- return NULL;
-
- arena = PORT_NewArena (1024);
- data = g_new (struct _GetPasswdData, 1);
- data->session = ctx->session;
- data->userid = userid;
- data->ex = ex;
- ecx = NSS_CMSEncoder_Start (cmsg, NULL, NULL, &output, arena,
- smime_get_password, data, NULL, NULL,
- NULL, NULL);
-
- stream = camel_stream_mem_new ();
- camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (message), stream);
- buf = CAMEL_STREAM_MEM (stream)->buffer;
-
- NSS_CMSEncoder_Update (ecx, buf->data, buf->len);
- NSS_CMSEncoder_Finish (ecx);
-
- camel_object_unref (CAMEL_OBJECT (stream));
- g_free (data);
-
- /* write the result to a camel stream */
- stream = camel_stream_mem_new ();
- camel_stream_write (stream, output.data, output.len);
- PORT_FreeArena (arena, PR_FALSE);
-
- NSS_CMSMessage_Destroy (cmsg);
-
- /* parse the stream into a new CamelMimeMessage */
- mesg = camel_mime_message_new ();
- camel_stream_reset (stream);
- camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (mesg), stream);
- camel_object_unref (CAMEL_OBJECT (stream));
-
- return mesg;
-}
-
-
-struct _BulkKey {
- PK11SymKey *bulkkey;
- SECOidTag bulkalgtag;
- int keysize;
-};
-
-static NSSCMSMessage *
-encrypted_data (CamelSMimeContext *ctx, GByteArray *input, struct _BulkKey *key,
- CamelStream *ostream, CamelException *ex)
-{
- NSSCMSMessage *cmsg = NULL;
- NSSCMSContentInfo *cinfo;
- NSSCMSEncryptedData *encd;
- NSSCMSEncoderContext *ecx = NULL;
- PLArenaPool *arena = NULL;
- SECItem output = { 0, 0, 0 };
-
- /* arena for output */
- arena = PORT_NewArena (1024);
-
- /* create cms message object */
- cmsg = NSS_CMSMessage_Create (NULL);
-
- encd = NSS_CMSEncryptedData_Create (cmsg, key->bulkalgtag, key->keysize);
-
- cinfo = NSS_CMSMessage_GetContentInfo (cmsg);
- NSS_CMSContentInfo_SetContent_EncryptedData (cmsg, cinfo, encd);
-
- cinfo = NSS_CMSEncryptedData_GetContentInfo (encd);
- NSS_CMSContentInfo_SetContent_Data (cmsg, cinfo, NULL, PR_FALSE);
-
- ecx = NSS_CMSEncoder_Start (cmsg, NULL, NULL, &output, arena, NULL, NULL,
- decode_key_cb, key->bulkkey, NULL, NULL);
-
- NSS_CMSEncoder_Update (ecx, input->data, input->len);
-
- NSS_CMSEncoder_Finish (ecx);
-
- camel_stream_write (ostream, output.data, output.len);
-
- if (arena)
- PORT_FreeArena (arena, PR_FALSE);
-
- return cmsg;
-}
-
-static struct _BulkKey *
-get_bulkkey (CamelSMimeContext *ctx, const char *userid, GPtrArray *recipients, CamelException *ex)
-{
- struct _BulkKey *bulkkey = NULL;
- NSSCMSMessage *env_cmsg;
- NSSCMSContentInfo *cinfo;
- SECItem dummyOut = { 0, 0, 0 };
- SECItem dummyIn = { 0, 0, 0 };
- char str[] = "You are not a beautiful and unique snowflake.";
- PLArenaPool *arena;
- int i, nlevels;
-
- /* construct an enveloped data message to obtain bulk keys */
- arena = PORT_NewArena (1024);
- dummyIn.data = (unsigned char *)str;
- dummyIn.len = strlen (str);
-
- env_cmsg = enveloped_data (ctx, userid, recipients, ex);
- NSS_CMSDEREncode (env_cmsg, &dummyIn, &dummyOut, arena);
- /*camel_stream_write (envstream, dummyOut.data, dummyOut.len);*/
- PORT_FreeArena (arena, PR_FALSE);
-
- /* get the content info for the enveloped data */
- nlevels = NSS_CMSMessage_ContentLevelCount (env_cmsg);
- for (i = 0; i < nlevels; i++) {
- SECOidTag typetag;
-
- cinfo = NSS_CMSMessage_ContentLevel (env_cmsg, i);
- typetag = NSS_CMSContentInfo_GetContentTypeTag (cinfo);
- if (typetag == SEC_OID_PKCS7_DATA) {
- bulkkey = g_new (struct _BulkKey, 1);
-
- /* get the symmertic key */
- bulkkey->bulkalgtag = NSS_CMSContentInfo_GetContentEncAlgTag (cinfo);
- bulkkey->keysize = NSS_CMSContentInfo_GetBulkKeySize (cinfo);
- bulkkey->bulkkey = NSS_CMSContentInfo_GetBulkKey (cinfo);
-
- return bulkkey;
- }
- }
-
- return NULL;
-}
-
-static CamelMimeMessage *
-smime_encrypt (CamelCMSContext *ctx, CamelMimeMessage *message,
- const char *userid, GPtrArray *recipients,
- CamelException *ex)
-{
- struct _BulkKey *bulkkey = NULL;
- CamelMimeMessage *mesg = NULL;
- NSSCMSMessage *cmsg = NULL;
- CamelStream *stream;
- GByteArray *buf;
-
- bulkkey = get_bulkkey (CAMEL_SMIME_CONTEXT (ctx), userid, recipients, ex);
- if (!bulkkey)
- return NULL;
-
- buf = g_byte_array_new ();
- stream = camel_stream_mem_new ();
- camel_stream_mem_set_byte_array (CAMEL_STREAM_MEM (stream), buf);
- camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (message), stream);
- camel_object_unref (CAMEL_OBJECT (stream));
-
- stream = camel_stream_mem_new ();
- cmsg = encrypted_data (CAMEL_SMIME_CONTEXT (ctx), buf, bulkkey, stream, ex);
- g_byte_array_free (buf, TRUE);
- g_free (bulkkey);
- if (!cmsg) {
- camel_object_unref (CAMEL_OBJECT (stream));
- return NULL;
- }
-
- NSS_CMSMessage_Destroy (cmsg);
-
- /* parse the stream into a new CamelMimeMessage */
- mesg = camel_mime_message_new ();
- camel_stream_reset (stream);
- camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (mesg), stream);
- camel_object_unref (CAMEL_OBJECT (stream));
-
- return mesg;
-}
-
-
-static NSSCMSMessage *
-decode_data (CamelSMimeContext *ctx, GByteArray *input, CamelStream *ostream,
- CamelCMSValidityInfo **info, CamelException *ex)
-{
- NSSCMSDecoderContext *dcx;
- struct _GetPasswdData *data;
- CamelCMSValidityInfo *vinfo = NULL;
- NSSCMSMessage *cmsg = NULL;
- NSSCMSContentInfo *cinfo;
- NSSCMSSignedData *sigd = NULL;
- NSSCMSEnvelopedData *envd;
- NSSCMSEncryptedData *encd;
- int nlevels, i, nsigners, j;
- char *signercn;
- NSSCMSSignerInfo *si;
- SECOidTag typetag;
- SECItem *item;
-
- data = g_new (struct _GetPasswdData, 1);
- data->session = CAMEL_CMS_CONTEXT (ctx)->session;
- data->userid = NULL;
- data->ex = ex;
-
- dcx = NSS_CMSDecoder_Start (NULL,
- NULL, NULL,
- smime_get_password, data,
- decode_key_cb,
- NULL);
-
- NSS_CMSDecoder_Update (dcx, input->data, input->len);
-
- cmsg = NSS_CMSDecoder_Finish (dcx);
- g_free (data);
- if (cmsg == NULL) {
- camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Failed to decode message."));
- return NULL;
- }
-
- nlevels = NSS_CMSMessage_ContentLevelCount (cmsg);
- for (i = 0; i < nlevels; i++) {
- CamelCMSSigner *signers = NULL;
-
- cinfo = NSS_CMSMessage_ContentLevel (cmsg, i);
- typetag = NSS_CMSContentInfo_GetContentTypeTag (cinfo);
-
- if (info && !vinfo) {
- vinfo = g_new0 (CamelCMSValidityInfo, 1);
- *info = vinfo;
- } else if (vinfo) {
- vinfo->next = g_new0 (CamelCMSValidityInfo, 1);
- vinfo = vinfo->next;
- }
-
- switch (typetag) {
- case SEC_OID_PKCS7_SIGNED_DATA:
- if (vinfo)
- vinfo->type = CAMEL_CMS_TYPE_SIGNED;
-
- sigd = (NSSCMSSignedData *)NSS_CMSContentInfo_GetContent (cinfo);
-
- /* import the certificates */
- NSS_CMSSignedData_ImportCerts (sigd, ctx->priv->certdb,
- certUsageEmailSigner, PR_FALSE);
-
- /* find out about signers */
- nsigners = NSS_CMSSignedData_SignerInfoCount (sigd);
-
- if (nsigners == 0) {
- /* must be a cert transport message */
- SECStatus retval;
-
- /* XXX workaround for bug #54014 */
- NSS_CMSSignedData_ImportCerts (sigd, ctx->priv->certdb,
- certUsageEmailSigner, PR_TRUE);
-
- retval = NSS_CMSSignedData_VerifyCertsOnly (sigd, ctx->priv->certdb,
- certUsageEmailSigner);
- if (retval != SECSuccess) {
- camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Failed to verify certificates."));
- goto exception;
- }
-
- return cmsg;
- }
-
- for (j = 0; vinfo && j < nsigners; j++) {
- if (!signers) {
- signers = g_new0 (CamelCMSSigner, 1);
- vinfo->signers = signers;
- } else {
- signers->next = g_new0 (CamelCMSSigner, 1);
- signers = signers->next;
- }
-
- si = NSS_CMSSignedData_GetSignerInfo (sigd, j);
- signercn = NSS_CMSSignerInfo_GetSignerCommonName (si);
- if (signercn == NULL)
- signercn = "";
-
- NSS_CMSSignedData_VerifySignerInfo (sigd, j, ctx->priv->certdb,
- certUsageEmailSigner);
-
- if (signers) {
- signers->signercn = g_strdup (signercn);
- signers->status = g_strdup (
- NSS_CMSUtil_VerificationStatusToString (
- NSS_CMSSignerInfo_GetVerificationStatus (si)));
- }
- }
- break;
- case SEC_OID_PKCS7_ENVELOPED_DATA:
- if (vinfo)
- vinfo->type = CAMEL_CMS_TYPE_ENVELOPED;
-
- envd = (NSSCMSEnvelopedData *)NSS_CMSContentInfo_GetContent (cinfo);
- break;
- case SEC_OID_PKCS7_ENCRYPTED_DATA:
- if (vinfo)
- vinfo->type = CAMEL_CMS_TYPE_ENCRYPTED;
-
- encd = (NSSCMSEncryptedData *)NSS_CMSContentInfo_GetContent (cinfo);
- break;
- case SEC_OID_PKCS7_DATA:
- break;
- default:
- break;
- }
- }
-
- item = NSS_CMSMessage_GetContent (cmsg);
- camel_stream_write (ostream, item->data, item->len);
-
- return cmsg;
-
- exception:
-
- if (info)
- camel_cms_validity_info_free (*info);
-
- if (cmsg)
- NSS_CMSMessage_Destroy (cmsg);
-
- return NULL;
-}
-
-
-static CamelMimeMessage *
-smime_decode (CamelCMSContext *ctx, CamelMimeMessage *message,
- CamelCMSValidityInfo **info, CamelException *ex)
-{
- CamelMimeMessage *mesg = NULL;
- NSSCMSMessage *cmsg = NULL;
- CamelStream *stream, *ostream;
- GByteArray *buf;
-
- stream = camel_stream_mem_new ();
- camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (message), stream);
- buf = CAMEL_STREAM_MEM (stream)->buffer;
-
- ostream = camel_stream_mem_new ();
- cmsg = decode_data (CAMEL_SMIME_CONTEXT (ctx), buf, ostream, info, ex);
- camel_object_unref (CAMEL_OBJECT (stream));
- if (!cmsg) {
- camel_object_unref (CAMEL_OBJECT (ostream));
- return NULL;
- }
-
- /* construct a new mime message from the stream */
- mesg = camel_mime_message_new ();
- camel_stream_reset (ostream);
- camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (mesg), ostream);
- camel_object_unref (CAMEL_OBJECT (ostream));
-
- return mesg;
-}
-
-#if 0
-
-/* Ugh, so smime context inherets from cms context, not cipher context
- this needs to be fixed ... */
-
-/* this has a 1:1 relationship to CamelCipherHash */
-static char **name_table[] = {
- "sha1", /* we use sha1 as the 'default' */
- NULL,
- "md5",
- "sha1",
- NULL,
-};
-
-static const char *smime_hash_to_id(CamelCipherContext *context, CamelCipherHash hash)
-{
- /* if we dont know, just use default? */
- if (hash > sizeof(name_table)/sizeof(name_table[0])
- || name_table[hash] == NULL;
- hash = CAMEL_CIPHER_HASH_DEFAULT;
-
- return name_table[hash];
-}
-
-static CamelCipherHash smime_id_to_hash(CamelCipherContext *context, const char *id)
-{
- int i;
- unsigned char *tmpid, *o, *in;
- unsigned char c;
-
- if (id == NULL)
- return CAMEL_CIPHER_HASH_DEFAULT;
-
- tmpid = alloca(strlen(id)+1);
- in = id;
- o = tmpid;
- while ((c = *in++))
- *o++ = tolower(c);
-
- for (i=1;i<sizeof(name_table)/sizeof(name_table[0]);i++) {
- if (!strcmp(name_table[i], tmpid))
- return i;
- }
-
- return CAMEL_CIPHER_HASH_DEFAULT;
-}
-#endif
-
-#endif /* HAVE_NSS */