[gmime] Implemented a bunch of GMimeApplicationPkcs7Mime



commit 0833266ae45af43392cfe3c4338ac7c9dce04916
Author: Jeffrey Stedfast <jestedfa microsoft com>
Date:   Fri Feb 17 17:47:21 2017 -0500

    Implemented a bunch of GMimeApplicationPkcs7Mime

 gmime/Makefile.am                    |    2 +
 gmime/gmime-application-pkcs7-mime.c |  283 ++++++++++++++++++++++++++++++++++
 gmime/gmime-application-pkcs7-mime.h |    4 +-
 gmime/gmime.c                        |    2 +
 4 files changed, 289 insertions(+), 2 deletions(-)
---
diff --git a/gmime/Makefile.am b/gmime/Makefile.am
index 59c8e70..521bcf6 100644
--- a/gmime/Makefile.am
+++ b/gmime/Makefile.am
@@ -21,6 +21,7 @@ lib_LTLIBRARIES = libgmime-3.0.la
 
 libgmime_3_0_la_SOURCES =              \
        gmime.c                         \
+       gmime-application-pkcs7-mime.c  \
        gmime-certificate.c             \
        gmime-charset.c                 \
        gmime-common.c                  \
@@ -78,6 +79,7 @@ libgmime_3_0_la_SOURCES =             \
 
 gmimeinclude_HEADERS =                         \
        gmime.h                         \
+       gmime-application-pkcs7-mime.h  \
        gmime-certificate.h             \
        gmime-charset.h                 \
        gmime-content-type.h            \
diff --git a/gmime/gmime-application-pkcs7-mime.c b/gmime/gmime-application-pkcs7-mime.c
index 19f940d..c2dfbe4 100644
--- a/gmime/gmime-application-pkcs7-mime.c
+++ b/gmime/gmime-application-pkcs7-mime.c
@@ -23,6 +23,18 @@
 #include <config.h>
 #endif
 
+#include <string.h>
+
+#include "gmime-application-pkcs7-mime.h"
+#include "gmime-stream-filter.h"
+#include "gmime-filter-basic.h"
+#include "gmime-filter-crlf.h"
+#include "gmime-stream-mem.h"
+#include "gmime-parser.h"
+#include "gmime-error.h"
+
+#define _(x) x
+
 /**
  * SECTION: gmime-application-pkcs7-mime
  * @title: GMimeApplicationPkcs7Mime
@@ -171,6 +183,9 @@ g_mime_application_pkcs7_mime_new (GMimeSecureMimeType type)
 {
        GMimeApplicationPkcs7Mime *pkcs7_mime;
        GMimeContentType *content_type;
+       const char *name;
+       
+       g_return_val_if_fail (type != GMIME_SECURE_MIME_TYPE_UNKNOWN, NULL);
        
        pkcs7_mime = g_object_newv (GMIME_TYPE_APPLICATION_PKCS7_MIME, 0, NULL);
        content_type = g_mime_content_type_new ("application", "pkcs7-mime");
@@ -178,15 +193,19 @@ g_mime_application_pkcs7_mime_new (GMimeSecureMimeType type)
        switch (type) {
        case GMIME_SECURE_MIME_TYPE_COMPRESSED_DATA:
                g_mime_content_type_set_parameter (content_type, "smime-type", "compressed-data");
+               name = "smime.p7z";
                break;
        case GMIME_SECURE_MIME_TYPE_ENVELOPED_DATA:
                g_mime_content_type_set_parameter (content_type, "smime-type", "enveloped-data");
+               name = "smime.p7m";
                break;
        case GMIME_SECURE_MIME_TYPE_SIGNED_DATA:
                g_mime_content_type_set_parameter (content_type, "smime-type", "signed-data");
+               name = "smime.p7m";
                break;
        case GMIME_SECURE_MIME_TYPE_CERTS_ONLY:
                g_mime_content_type_set_parameter (content_type, "smime-type", "certs-only");
+               name = "smime.p7c";
                break;
        default:
                break;
@@ -195,6 +214,8 @@ g_mime_application_pkcs7_mime_new (GMimeSecureMimeType type)
        g_mime_object_set_content_type (GMIME_OBJECT (pkcs7_mime), content_type);
        g_object_unref (content_type);
        
+       g_mime_part_set_filename (GMIME_PART (pkcs7_mime), name);
+       
        return pkcs7_mime;
 }
 
@@ -214,3 +235,265 @@ g_mime_application_pkcs7_mime_get_smime_type (GMimeApplicationPkcs7Mime *pkcs7_m
        
        return pkcs7_mime->smime_type;
 }
+
+
+#if 0
+GMimeApplicationPkcs7Mime *
+g_mime_application_pkcs7_mime_compress (GMimePkcs7Context *ctx, GMimeObject *entity, GError **err)
+{
+}
+
+
+GMimeObject *
+g_mime_application_pkcs7_mime_decompress (GMimeApplicationPkcs7Mime *pkcs7_mime, GMimePkcs7Context *ctx)
+{
+}
+#endif
+
+
+/**
+ * g_mime_application_pkcs7_mime_encrypt:
+ * @ctx: a #GMimePkcs7Context
+ * @entity: a #GMimeObject to encrypt
+ * @recipients: the list of recipients to encrypt to
+ * @err: a #GError
+ *
+ * Encrypts @entity using S/MIME.
+ *
+ * Returns: The encrypted @entity.
+ **/
+GMimeApplicationPkcs7Mime *
+g_mime_application_pkcs7_mime_encrypt (GMimePkcs7Context *ctx, GMimeObject *entity, GPtrArray *recipients, 
GError **err)
+{
+       GMimeStream *filtered_stream, *ciphertext, *stream;
+       GMimeApplicationPkcs7Mime *pkcs7_mime;
+       GMimeContentType *content_type;
+       GMimeDataWrapper *wrapper;
+       GMimeFilter *crlf_filter;
+       
+       g_return_val_if_fail (GMIME_IS_PKCS7_CONTEXT (ctx), NULL);
+       g_return_val_if_fail (GMIME_IS_OBJECT (entity), NULL);
+       g_return_val_if_fail (recipients != NULL, NULL);
+       
+       /* get the cleartext */
+       stream = g_mime_stream_mem_new ();
+       filtered_stream = g_mime_stream_filter_new (stream);
+       
+       crlf_filter = g_mime_filter_crlf_new (TRUE, FALSE);
+       g_mime_stream_filter_add (GMIME_STREAM_FILTER (filtered_stream), crlf_filter);
+       g_object_unref (crlf_filter);
+       
+       g_mime_object_write_to_stream (entity, filtered_stream);
+       g_mime_stream_flush (filtered_stream);
+       g_object_unref (filtered_stream);
+       
+       /* reset the content stream */
+       g_mime_stream_reset (stream);
+       
+       /* encrypt the content stream */
+       ciphertext = g_mime_stream_mem_new ();
+       if (g_mime_crypto_context_encrypt ((GMimeCryptoContext *) ctx, FALSE, NULL, 
GMIME_DIGEST_ALGO_DEFAULT, recipients, stream, ciphertext, err) == -1) {
+               g_object_unref (ciphertext);
+               g_object_unref (stream);
+               return NULL;
+       }
+       
+       g_object_unref (stream);
+       g_mime_stream_reset (ciphertext);
+       
+       /* construct the application/pkcs7-mime part */
+       pkcs7_mime = g_mime_application_pkcs7_mime_new (GMIME_SECURE_MIME_TYPE_ENVELOPED_DATA);
+       wrapper = g_mime_data_wrapper_new_with_stream (ciphertext, GMIME_CONTENT_ENCODING_DEFAULT);
+       g_mime_part_set_content_object (GMIME_PART (pkcs7_mime), wrapper);
+       g_object_unref (ciphertext);
+       g_object_unref (wrapper);
+       
+       return pkcs7_mime;
+}
+
+static GMimeStream *
+g_mime_data_wrapper_get_decoded_stream (GMimeDataWrapper *wrapper)
+{
+       GMimeStream *decoded_stream;
+       GMimeFilter *decoder;
+       
+       g_mime_stream_reset (wrapper->stream);
+       
+       switch (wrapper->encoding) {
+       case GMIME_CONTENT_ENCODING_BASE64:
+       case GMIME_CONTENT_ENCODING_QUOTEDPRINTABLE:
+       case GMIME_CONTENT_ENCODING_UUENCODE:
+               decoder = g_mime_filter_basic_new (wrapper->encoding, FALSE);
+               decoded_stream = g_mime_stream_filter_new (wrapper->stream);
+               g_mime_stream_filter_add (GMIME_STREAM_FILTER (decoded_stream), decoder);
+               g_object_unref (decoder);
+               break;
+       default:
+               decoded_stream = wrapper->stream;
+               g_object_ref (wrapper->stream);
+               break;
+       }
+       
+       return decoded_stream;
+}
+
+
+/**
+ * g_mime_application_pkcs7_mime_decrypt:
+ * @pkcs7_mime: a #GMimeApplicationPkcs7Mime
+ * @ctx: a #GMimePkcs7Context
+ * @result: the decryption result
+ * @err: a #GError
+ *
+ * Decrypts the @pkcs7_mime part.
+ *
+ * Returns: the decrypted @pkcs7_mime part.
+ **/
+GMimeObject *
+g_mime_application_pkcs7_mime_decrypt (GMimeApplicationPkcs7Mime *pkcs7_mime, GMimePkcs7Context *ctx, 
GMimeDecryptResult **result, GError **err)
+{
+       GMimeStream *filtered_stream, *ciphertext, *stream;
+       GMimeDataWrapper *wrapper;
+       GMimeFilter *crlf_filter;
+       GMimeDecryptResult *res;
+       GMimeObject *decrypted;
+       GMimeParser *parser;
+       
+       g_return_val_if_fail (GMIME_IS_APPLICATION_PKCS7_MIME (pkcs7_mime), NULL);
+       g_return_val_if_fail (GMIME_IS_PKCS7_CONTEXT (ctx), NULL);
+       
+       if (result)
+               *result = NULL;
+       
+       /* get the ciphertext stream */
+       wrapper = g_mime_part_get_content_object (GMIME_PART (pkcs7_mime));
+       ciphertext = g_mime_data_wrapper_get_decoded_stream (wrapper);
+       g_mime_stream_reset (ciphertext);
+       
+       stream = g_mime_stream_mem_new ();
+       filtered_stream = g_mime_stream_filter_new (stream);
+       crlf_filter = g_mime_filter_crlf_new (FALSE, FALSE);
+       g_mime_stream_filter_add (GMIME_STREAM_FILTER (filtered_stream), crlf_filter);
+       g_object_unref (crlf_filter);
+       
+       /* decrypt the content stream */
+       if (!(res = g_mime_crypto_context_decrypt ((GMimeCryptoContext *) ctx, ciphertext, filtered_stream, 
err))) {
+               g_object_unref (filtered_stream);
+               g_object_unref (ciphertext);
+               g_object_unref (stream);
+               
+               return NULL;
+       }
+       
+       g_mime_stream_flush (filtered_stream);
+       g_object_unref (filtered_stream);
+       g_object_unref (ciphertext);
+       
+       g_mime_stream_reset (stream);
+       parser = g_mime_parser_new ();
+       g_mime_parser_init_with_stream (parser, stream);
+       g_object_unref (stream);
+       
+       decrypted = g_mime_parser_construct_part (parser);
+       g_object_unref (parser);
+       
+       if (!decrypted) {
+               g_set_error_literal (err, GMIME_ERROR, GMIME_ERROR_PARSE_ERROR,
+                                    _("Cannot decrypt application/pkcs7-mime part: failed to parse decrypted 
content."));
+               
+               g_object_unref (res);
+               
+               return NULL;
+       }
+       
+       if (!result)
+               g_object_unref (res);
+       else
+               *result = res;
+       
+       return decrypted;
+}
+
+
+/**
+ * g_mime_application_pkcs7_mime_sign:
+ * @ctx: a #GMimePkcs7Context
+ * @entity: a #GMimeObject
+ * @userid: the user id to sign with
+ * @digest: a #GMimeDigestAlgo
+ * @err: a #GError
+ *
+ * Signs the @entity using S/MIME.
+ *
+ * Returns: the signed @entity.
+ **/
+GMimeApplicationPkcs7Mime *
+g_mime_application_pkcs7_mime_sign (GMimePkcs7Context *ctx, GMimeObject *entity, const char *userid, 
GMimeDigestAlgo digest, GError **err)
+{
+       GMimeStream *filtered_stream, *ciphertext, *stream;
+       GMimeApplicationPkcs7Mime *pkcs7_mime;
+       GMimeContentType *content_type;
+       GMimeDataWrapper *wrapper;
+       GMimeFilter *crlf_filter;
+       
+       g_return_val_if_fail (GMIME_IS_PKCS7_CONTEXT (ctx), NULL);
+       g_return_val_if_fail (GMIME_IS_OBJECT (entity), NULL);
+       g_return_val_if_fail (userid != NULL, NULL);
+       
+       /* get the cleartext */
+       stream = g_mime_stream_mem_new ();
+       filtered_stream = g_mime_stream_filter_new (stream);
+       
+       crlf_filter = g_mime_filter_crlf_new (TRUE, FALSE);
+       g_mime_stream_filter_add (GMIME_STREAM_FILTER (filtered_stream), crlf_filter);
+       g_object_unref (crlf_filter);
+       
+       g_mime_object_write_to_stream (entity, filtered_stream);
+       g_mime_stream_flush (filtered_stream);
+       g_object_unref (filtered_stream);
+       
+       /* reset the content stream */
+       g_mime_stream_reset (stream);
+       
+       /* sign the content stream */
+       ciphertext = g_mime_stream_mem_new ();
+       if (g_mime_crypto_context_sign ((GMimeCryptoContext *) ctx, userid, digest, stream, ciphertext, err) 
== -1) {
+               g_object_unref (ciphertext);
+               g_object_unref (stream);
+               return NULL;
+       }
+       
+       g_object_unref (stream);
+       g_mime_stream_reset (ciphertext);
+       
+       /* construct the application/pkcs7-mime part */
+       pkcs7_mime = g_mime_application_pkcs7_mime_new (GMIME_SECURE_MIME_TYPE_SIGNED_DATA);
+       wrapper = g_mime_data_wrapper_new_with_stream (ciphertext, GMIME_CONTENT_ENCODING_DEFAULT);
+       g_mime_part_set_content_object (GMIME_PART (pkcs7_mime), wrapper);
+       g_object_unref (ciphertext);
+       g_object_unref (wrapper);
+       
+       return pkcs7_mime;
+}
+
+
+/**
+ * g_mime_application_pkcs7_mime_verify:
+ * @pkcs7_mime: a #GMimeApplicationPkcs7Mime
+ * @ctx: a #GMimePkcs7Context
+ * @entity: the extracted entity
+ * @err: a #GError
+ *
+ * Verifies the signed @pkcs7_mime part and extracts the original MIME entity.
+ *
+ * Returns: the list of signers.
+ **/
+GMimeSignatureList *
+g_mime_application_pkcs7_mime_verify (GMimeApplicationPkcs7Mime *pkcs7_mime, GMimePkcs7Context *ctx, 
GMimeObject **entity, GError **err)
+{
+       g_return_val_if_fail (GMIME_IS_APPLICATION_PKCS7_MIME (pkcs7_mime), NULL);
+       g_return_val_if_fail (GMIME_IS_PKCS7_CONTEXT (ctx), NULL);
+       g_return_val_if_fail (entity != NULL, NULL);
+       
+       return NULL;
+}
diff --git a/gmime/gmime-application-pkcs7-mime.h b/gmime/gmime-application-pkcs7-mime.h
index 51c23ff..289f29d 100644
--- a/gmime/gmime-application-pkcs7-mime.h
+++ b/gmime/gmime-application-pkcs7-mime.h
@@ -86,13 +86,13 @@ GMimeSecureMimeType g_mime_application_pkcs7_mime_get_smime_type (GMimeApplicati
 
 GMimeApplicationPkcs7Mime *g_mime_application_pkcs7_mime_encrypt (GMimePkcs7Context *ctx, GMimeObject 
*entity,
                                                                  GPtrArray *recipients, GError **err);
-GMimeObject *g_mime_application_pkcs7_mime_decrypt (GMimeApplicationPkcs7Mime *pkcs7_mime, 
GMimeCryptoContext *ctx,
+GMimeObject *g_mime_application_pkcs7_mime_decrypt (GMimeApplicationPkcs7Mime *pkcs7_mime, GMimePkcs7Context 
*ctx,
                                                    GMimeDecryptResult **result, GError **err);
 
 GMimeApplicationPkcs7Mime *g_mime_application_pkcs7_mime_sign (GMimePkcs7Context *ctx, GMimeObject *entity,
                                                               const char *userid, GMimeDigestAlgo digest,
                                                               GError **err);
-GMimeSignatureList *g_mime_application_pkcs7_mime_verify (GMimeApplicationPkcs7Mime *pkcs7_mime, 
GMimeCryptoContext *ctx,
+GMimeSignatureList *g_mime_application_pkcs7_mime_verify (GMimeApplicationPkcs7Mime *pkcs7_mime, 
GMimePkcs7Context *ctx,
                                                          GMimeObject **entity, GError **err);
 
 G_END_DECLS
diff --git a/gmime/gmime.c b/gmime/gmime.c
index 63ba849..b174c05 100644
--- a/gmime/gmime.c
+++ b/gmime/gmime.c
@@ -184,6 +184,8 @@ g_mime_init (void)
        /* register our default mime object types */
        g_mime_object_type_registry_init ();
        g_mime_object_register_type ("*", "*", g_mime_part_get_type ());
+       g_mime_object_register_type ("application", "x-pkcs7-mime", g_mime_application_pkcs7_mime_get_type 
());
+       g_mime_object_register_type ("application", "pkcs7-mime", g_mime_application_pkcs7_mime_get_type ());
        g_mime_object_register_type ("multipart", "*", g_mime_multipart_get_type ());
        g_mime_object_register_type ("multipart", "encrypted", g_mime_multipart_encrypted_get_type ());
        g_mime_object_register_type ("multipart", "signed", g_mime_multipart_signed_get_type ());


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]