[gmime] Implemented g_mime_application_pkcs7_mime_verify()
- From: Jeffrey Stedfast <fejj src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gmime] Implemented g_mime_application_pkcs7_mime_verify()
- Date: Wed, 8 Mar 2017 13:33:30 +0000 (UTC)
commit 02dc4fe673bb8de9ad94dcefc051f6d57ac4a145
Author: Jeffrey Stedfast <jestedfa microsoft com>
Date: Sun Feb 19 16:36:12 2017 -0500
Implemented g_mime_application_pkcs7_mime_verify()
gmime/gmime-application-pkcs7-mime.c | 81 ++++++++++++++++++++++++++++++---
gmime/gmime-application-pkcs7-mime.h | 8 ++--
gmime/gmime-crypto-context.c | 19 +++++---
gmime/gmime-crypto-context.h | 6 ++-
gmime/gmime-gpg-context.c | 27 ++++++++++--
gmime/gmime-multipart-encrypted.c | 2 +-
gmime/gmime-multipart-signed.c | 2 +-
gmime/gmime-pkcs7-context.c | 25 +++++++++-
8 files changed, 139 insertions(+), 31 deletions(-)
---
diff --git a/gmime/gmime-application-pkcs7-mime.c b/gmime/gmime-application-pkcs7-mime.c
index dc6b45b..4ef5268 100644
--- a/gmime/gmime-application-pkcs7-mime.c
+++ b/gmime/gmime-application-pkcs7-mime.c
@@ -342,7 +342,6 @@ g_mime_data_wrapper_get_decoded_stream (GMimeDataWrapper *wrapper)
/**
* g_mime_application_pkcs7_mime_decrypt:
* @pkcs7_mime: a #GMimeApplicationPkcs7Mime
- * @ctx: a #GMimePkcs7Context
* @flags: a #GMimeDecryptFlags
* @session_key: session key to use or %NULL
* @result: the decryption result
@@ -365,23 +364,30 @@ g_mime_data_wrapper_get_decoded_stream (GMimeDataWrapper *wrapper)
* @err to provide information as to why the failure occured.
**/
GMimeObject *
-g_mime_application_pkcs7_mime_decrypt (GMimeApplicationPkcs7Mime *pkcs7_mime, GMimePkcs7Context *ctx,
+g_mime_application_pkcs7_mime_decrypt (GMimeApplicationPkcs7Mime *pkcs7_mime,
GMimeDecryptFlags flags, const char *session_key,
GMimeDecryptResult **result, GError **err)
{
GMimeStream *filtered_stream, *ciphertext, *stream;
GMimeDataWrapper *wrapper;
GMimeFilter *crlf_filter;
+ GMimeCryptoContext *ctx;
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;
+ if (!(ctx = g_mime_crypto_context_new ("application/pkcs7-mime"))) {
+ g_set_error (err, GMIME_ERROR, GMIME_ERROR_PROTOCOL_ERROR,
+ _("Cannot decrypt application/pkcs7-mime part: no crypto context registered for
this type."));
+
+ return 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);
@@ -394,10 +400,11 @@ g_mime_application_pkcs7_mime_decrypt (GMimeApplicationPkcs7Mime *pkcs7_mime, GM
g_object_unref (crlf_filter);
/* decrypt the content stream */
- if (!(res = g_mime_crypto_context_decrypt ((GMimeCryptoContext *) ctx, flags, session_key,
ciphertext, filtered_stream, err))) {
+ if (!(res = g_mime_crypto_context_decrypt (ctx, flags, session_key, ciphertext, filtered_stream,
err))) {
g_object_unref (filtered_stream);
g_object_unref (ciphertext);
g_object_unref (stream);
+ g_object_unref (ctx);
return NULL;
}
@@ -405,6 +412,7 @@ g_mime_application_pkcs7_mime_decrypt (GMimeApplicationPkcs7Mime *pkcs7_mime, GM
g_mime_stream_flush (filtered_stream);
g_object_unref (filtered_stream);
g_object_unref (ciphertext);
+ g_object_unref (ctx);
g_mime_stream_reset (stream);
parser = g_mime_parser_new ();
@@ -497,7 +505,6 @@ g_mime_application_pkcs7_mime_sign (GMimePkcs7Context *ctx, GMimeObject *entity,
/**
* g_mime_application_pkcs7_mime_verify:
* @pkcs7_mime: a #GMimeApplicationPkcs7Mime
- * @ctx: a #GMimePkcs7Context
* @flags: a #GMimeVerifyFlags
* @entity: the extracted entity
* @err: a #GError
@@ -507,11 +514,69 @@ g_mime_application_pkcs7_mime_sign (GMimePkcs7Context *ctx, GMimeObject *entity,
* Returns: the list of signers.
**/
GMimeSignatureList *
-g_mime_application_pkcs7_mime_verify (GMimeApplicationPkcs7Mime *pkcs7_mime, GMimePkcs7Context *ctx,
GMimeVerifyFlags flags, GMimeObject **entity, GError **err)
+g_mime_application_pkcs7_mime_verify (GMimeApplicationPkcs7Mime *pkcs7_mime, GMimeVerifyFlags flags,
GMimeObject **entity, GError **err)
{
+ GMimeStream *filtered_stream, *ciphertext, *stream;
+ GMimeSignatureList *signatures;
+ GMimeDataWrapper *wrapper;
+ GMimeFilter *crlf_filter;
+ GMimeCryptoContext *ctx;
+ 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);
g_return_val_if_fail (entity != NULL, NULL);
- return NULL;
+ *entity = NULL;
+
+ if (!(ctx = g_mime_crypto_context_new ("application/pkcs7-mime"))) {
+ g_set_error (err, GMIME_ERROR, GMIME_ERROR_PROTOCOL_ERROR,
+ _("Cannot decrypt application/pkcs7-mime part: no crypto context registered for
this type."));
+
+ return 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 (!(signatures = g_mime_crypto_context_verify (ctx, flags, GMIME_DIGEST_ALGO_DEFAULT, ciphertext,
NULL, filtered_stream, err))) {
+ g_object_unref (filtered_stream);
+ g_object_unref (ciphertext);
+ g_object_unref (stream);
+ g_object_unref (ctx);
+
+ return NULL;
+ }
+
+ g_mime_stream_flush (filtered_stream);
+ g_object_unref (filtered_stream);
+ g_object_unref (ciphertext);
+ g_object_unref (ctx);
+
+ g_mime_stream_reset (stream);
+ parser = g_mime_parser_new ();
+ g_mime_parser_init_with_stream (parser, stream);
+ g_object_unref (stream);
+
+ *entity = g_mime_parser_construct_part (parser);
+ g_object_unref (parser);
+
+ if (*entity == NULL) {
+ g_set_error_literal (err, GMIME_ERROR, GMIME_ERROR_PARSE_ERROR,
+ _("Cannot verify application/pkcs7-mime part: failed to parse extracted
content."));
+
+ g_object_unref (signatures);
+
+ return NULL;
+ }
+
+ return signatures;
}
diff --git a/gmime/gmime-application-pkcs7-mime.h b/gmime/gmime-application-pkcs7-mime.h
index c197d48..ac38e48 100644
--- a/gmime/gmime-application-pkcs7-mime.h
+++ b/gmime/gmime-application-pkcs7-mime.h
@@ -82,13 +82,13 @@ GMimeApplicationPkcs7Mime *g_mime_application_pkcs7_mime_new (GMimeSecureMimeTyp
GMimeSecureMimeType g_mime_application_pkcs7_mime_get_smime_type (GMimeApplicationPkcs7Mime *pkcs7_mime);
/*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);*/
+/*GMimeObject *g_mime_application_pkcs7_mime_decompress (GMimeApplicationPkcs7Mime *pkcs7_mime);*/
GMimeApplicationPkcs7Mime *g_mime_application_pkcs7_mime_encrypt (GMimePkcs7Context *ctx, GMimeObject
*entity,
GMimeEncryptFlags flags, GPtrArray
*recipients,
GError **err);
-GMimeObject *g_mime_application_pkcs7_mime_decrypt (GMimeApplicationPkcs7Mime *pkcs7_mime, GMimePkcs7Context
*ctx,
+GMimeObject *g_mime_application_pkcs7_mime_decrypt (GMimeApplicationPkcs7Mime *pkcs7_mime,
GMimeDecryptFlags flags, const char *session_key,
GMimeDecryptResult **result, GError **err);
@@ -96,8 +96,8 @@ GMimeApplicationPkcs7Mime *g_mime_application_pkcs7_mime_sign (GMimePkcs7Context
const char *userid, GMimeDigestAlgo digest,
GError **err);
-GMimeSignatureList *g_mime_application_pkcs7_mime_verify (GMimeApplicationPkcs7Mime *pkcs7_mime,
GMimePkcs7Context *ctx,
- GMimeVerifyFlags flags, GMimeObject **entity,
GError **err);
+GMimeSignatureList *g_mime_application_pkcs7_mime_verify (GMimeApplicationPkcs7Mime *pkcs7_mime,
GMimeVerifyFlags flags,
+ GMimeObject **entity, GError **err);
G_END_DECLS
diff --git a/gmime/gmime-crypto-context.c b/gmime/gmime-crypto-context.c
index 54d8d1e..ec84b6a 100644
--- a/gmime/gmime-crypto-context.c
+++ b/gmime/gmime-crypto-context.c
@@ -60,7 +60,8 @@ static int crypto_sign (GMimeCryptoContext *ctx, gboolean detach,
static GMimeSignatureList *crypto_verify (GMimeCryptoContext *ctx, GMimeVerifyFlags flags,
GMimeDigestAlgo digest, GMimeStream *istream,
- GMimeStream *sigstream, GError **err);
+ GMimeStream *sigstream, GMimeStream *ostream,
+ GError **err);
static int crypto_encrypt (GMimeCryptoContext *ctx, gboolean sign,
const char *userid, GMimeDigestAlgo digest,
@@ -391,7 +392,7 @@ g_mime_crypto_context_sign (GMimeCryptoContext *ctx, gboolean detach, const char
static GMimeSignatureList *
crypto_verify (GMimeCryptoContext *ctx, GMimeVerifyFlags flags, GMimeDigestAlgo digest,
- GMimeStream *istream, GMimeStream *sigstream, GError **err)
+ GMimeStream *istream, GMimeStream *sigstream, GMimeStream *ostream, GError **err)
{
g_set_error (err, GMIME_ERROR, GMIME_ERROR_NOT_SUPPORTED,
"Verifying is not supported by this crypto context");
@@ -407,24 +408,26 @@ crypto_verify (GMimeCryptoContext *ctx, GMimeVerifyFlags flags, GMimeDigestAlgo
* @digest: digest algorithm used, if known
* @istream: input stream
* @sigstream: optional detached-signature stream
+ * @ostream: optional output stream for use with encapsulated signature input streams
* @err: a #GError
*
- * Verifies the signature. If @istream is a clearsigned stream,
- * you should pass %NULL as the sigstream parameter. Otherwise
- * @sigstream is assumed to be the signature stream and is used to
- * verify the integirity of the @istream.
+ * Verifies the signature. If @istream is a clearsigned stream, you
+ * should pass %NULL as the @sigstream parameter and may wish to
+ * provide an @ostream argument for GMime to output the original
+ * plaintext into. Otherwise @sigstream is assumed to be the signature
+ * stream and is used to verify the integirity of the @istream.
*
* Returns: (transfer full): a #GMimeSignatureList object containing
* the status of each signature or %NULL on error.
**/
GMimeSignatureList *
g_mime_crypto_context_verify (GMimeCryptoContext *ctx, GMimeVerifyFlags flags, GMimeDigestAlgo digest,
- GMimeStream *istream, GMimeStream *sigstream, GError **err)
+ GMimeStream *istream, GMimeStream *sigstream, GMimeStream *ostream, GError
**err)
{
g_return_val_if_fail (GMIME_IS_CRYPTO_CONTEXT (ctx), NULL);
g_return_val_if_fail (GMIME_IS_STREAM (istream), NULL);
- return GMIME_CRYPTO_CONTEXT_GET_CLASS (ctx)->verify (ctx, flags, digest, istream, sigstream, err);
+ return GMIME_CRYPTO_CONTEXT_GET_CLASS (ctx)->verify (ctx, flags, digest, istream, sigstream, ostream,
err);
}
diff --git a/gmime/gmime-crypto-context.h b/gmime/gmime-crypto-context.h
index 6051527..5423324 100644
--- a/gmime/gmime-crypto-context.h
+++ b/gmime/gmime-crypto-context.h
@@ -145,7 +145,8 @@ struct _GMimeCryptoContextClass {
GMimeSignatureList * (* verify) (GMimeCryptoContext *ctx, GMimeVerifyFlags flags,
GMimeDigestAlgo digest, GMimeStream *istream,
- GMimeStream *sigstream, GError **err);
+ GMimeStream *sigstream, GMimeStream *ostream,
+ GError **err);
int (* encrypt) (GMimeCryptoContext *ctx, gboolean sign,
const char *userid, GMimeDigestAlgo digest,
@@ -192,7 +193,8 @@ int g_mime_crypto_context_sign (GMimeCryptoContext *ctx, gboolean detach,
GMimeSignatureList *g_mime_crypto_context_verify (GMimeCryptoContext *ctx, GMimeVerifyFlags flags,
GMimeDigestAlgo digest, GMimeStream *istream,
- GMimeStream *sigstream, GError **err);
+ GMimeStream *sigstream, GMimeStream *ostream,
+ GError **err);
int g_mime_crypto_context_encrypt (GMimeCryptoContext *ctx, gboolean sign,
const char *userid, GMimeDigestAlgo digest,
diff --git a/gmime/gmime-gpg-context.c b/gmime/gmime-gpg-context.c
index 4f96197..0959cf2 100644
--- a/gmime/gmime-gpg-context.c
+++ b/gmime/gmime-gpg-context.c
@@ -99,7 +99,8 @@ static const char *gpg_get_key_exchange_protocol (GMimeCryptoContext *ctx);
static GMimeSignatureList *gpg_verify (GMimeCryptoContext *ctx, GMimeVerifyFlags flags,
GMimeDigestAlgo digest, GMimeStream *istream,
- GMimeStream *sigstream, GError **err);
+ GMimeStream *sigstream, GMimeStream *ostream,
+ GError **err);
static int gpg_encrypt (GMimeCryptoContext *ctx, gboolean sign, const char *userid, GMimeDigestAlgo digest,
GMimeEncryptFlags flags, GPtrArray *recipients, GMimeStream *istream, GMimeStream
*ostream,
@@ -597,11 +598,11 @@ gpg_get_signatures (GMimeGpgContext *gpg, gboolean verify)
static GMimeSignatureList *
gpg_verify (GMimeCryptoContext *context, GMimeVerifyFlags flags, GMimeDigestAlgo digest,
- GMimeStream *istream, GMimeStream *sigstream, GError **err)
+ GMimeStream *istream, GMimeStream *sigstream, GMimeStream *ostream, GError **err)
{
#ifdef ENABLE_CRYPTO
GMimeGpgContext *gpg = (GMimeGpgContext *) context;
- gpgme_data_t message, signature;
+ gpgme_data_t message, signature, plaintext;
gpgme_error_t error;
if ((error = gpgme_data_new_from_cbs (&message, &gpg_stream_funcs, istream)) != GPG_ERR_NO_ERROR) {
@@ -620,16 +621,34 @@ gpg_verify (GMimeCryptoContext *context, GMimeVerifyFlags flags, GMimeDigestAlgo
signature = NULL;
}
+ /* if @ostream is non-NULL, then we are expected to write the extracted plaintext to it */
+ if (ostream != NULL) {
+ if ((error = gpgme_data_new_from_cbs (&plaintext, &gpg_stream_funcs, ostream)) !=
GPG_ERR_NO_ERROR) {
+ g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open output stream"));
+ if (signature)
+ gpgme_data_release (signature);
+ gpgme_data_release (message);
+ return NULL;
+ }
+ } else {
+ plaintext = NULL;
+ }
+
// FIXME: enable auto-key-retrieve
- if ((error = gpgme_op_verify (gpg->ctx, signature, message, NULL)) != GPG_ERR_NO_ERROR) {
+ if ((error = gpgme_op_verify (gpg->ctx, signature, message, plaintext)) != GPG_ERR_NO_ERROR) {
g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not verify gpg signature"));
+ if (plaintext)
+ gpgme_data_release (plaintext);
if (signature)
gpgme_data_release (signature);
gpgme_data_release (message);
return NULL;
}
+ if (plaintext)
+ gpgme_data_release (plaintext);
+
if (signature)
gpgme_data_release (signature);
diff --git a/gmime/gmime-multipart-encrypted.c b/gmime/gmime-multipart-encrypted.c
index f37dfff..db6c6f4 100644
--- a/gmime/gmime-multipart-encrypted.c
+++ b/gmime/gmime-multipart-encrypted.c
@@ -326,7 +326,7 @@ g_mime_multipart_encrypted_decrypt (GMimeMultipartEncrypted *mpe, GMimeDecryptFl
if (!(ctx = g_mime_crypto_context_new (protocol))) {
g_set_error (err, GMIME_ERROR, GMIME_ERROR_PROTOCOL_ERROR,
- _("Cannot verify multipart/encrypted part: unregistered encryption protocol
'%s'."),
+ _("Cannot decrypt multipart/encrypted part: unregistered encryption protocol
'%s'."),
protocol);
return NULL;
diff --git a/gmime/gmime-multipart-signed.c b/gmime/gmime-multipart-signed.c
index 9ffaf74..054a79e 100644
--- a/gmime/gmime-multipart-signed.c
+++ b/gmime/gmime-multipart-signed.c
@@ -470,7 +470,7 @@ g_mime_multipart_signed_verify (GMimeMultipartSigned *mps, GMimeVerifyFlags flag
/* verify the signature */
digest = g_mime_crypto_context_digest_id (ctx, micalg);
- signatures = g_mime_crypto_context_verify (ctx, flags, digest, stream, sigstream, err);
+ signatures = g_mime_crypto_context_verify (ctx, flags, digest, stream, sigstream, NULL, err);
d(printf ("attempted to verify:\n----- BEGIN SIGNED PART -----\n%.*s----- END SIGNED PART -----\n",
(int) GMIME_STREAM_MEM (stream)->buffer->len, GMIME_STREAM_MEM (stream)->buffer->data));
diff --git a/gmime/gmime-pkcs7-context.c b/gmime/gmime-pkcs7-context.c
index 8b9f8a1..3626757 100644
--- a/gmime/gmime-pkcs7-context.c
+++ b/gmime/gmime-pkcs7-context.c
@@ -98,7 +98,8 @@ static int pkcs7_sign (GMimeCryptoContext *ctx, gboolean detach,
static GMimeSignatureList *pkcs7_verify (GMimeCryptoContext *ctx, GMimeVerifyFlags flags,
GMimeDigestAlgo digest, GMimeStream *istream,
- GMimeStream *sigstream, GError **err);
+ GMimeStream *sigstream, GMimeStream *ostream,
+ GError **err);
static int pkcs7_encrypt (GMimeCryptoContext *ctx, gboolean sign, const char *userid, GMimeDigestAlgo digest,
GMimeEncryptFlags flags, GPtrArray *recipients, GMimeStream *istream,
@@ -591,11 +592,11 @@ pkcs7_get_signatures (GMimePkcs7Context *pkcs7, gboolean verify)
static GMimeSignatureList *
pkcs7_verify (GMimeCryptoContext *context, GMimeVerifyFlags flags, GMimeDigestAlgo digest,
- GMimeStream *istream, GMimeStream *sigstream, GError **err)
+ GMimeStream *istream, GMimeStream *sigstream, GMimeStream *ostream, GError **err)
{
#ifdef ENABLE_CRYPTO
GMimePkcs7Context *pkcs7 = (GMimePkcs7Context *) context;
- gpgme_data_t message, signature;
+ gpgme_data_t message, signature, plaintext;
gpgme_error_t error;
if ((error = gpgme_data_new_from_cbs (&message, &pkcs7_stream_funcs, istream)) != GPG_ERR_NO_ERROR) {
@@ -614,16 +615,34 @@ pkcs7_verify (GMimeCryptoContext *context, GMimeVerifyFlags flags, GMimeDigestAl
signature = NULL;
}
+ /* if @ostream is non-NULL, then we are expected to write the extracted plaintext to it */
+ if (ostream != NULL) {
+ if ((error = gpgme_data_new_from_cbs (&plaintext, &gpg_stream_funcs, ostream)) !=
GPG_ERR_NO_ERROR) {
+ g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open output stream"));
+ if (signature)
+ gpgme_data_release (signature);
+ gpgme_data_release (message);
+ return NULL;
+ }
+ } else {
+ plaintext = NULL;
+ }
+
// FIXME: enable auto-key-retrieve
if ((error = gpgme_op_verify (pkcs7->ctx, signature, message, NULL)) != GPG_ERR_NO_ERROR) {
g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not verify pkcs7 signature"));
+ if (plaintext)
+ gpgme_data_release (plaintext);
if (signature)
gpgme_data_release (signature);
gpgme_data_release (message);
return NULL;
}
+ if (plaintext)
+ gpgme_data_release (plaintext);
+
if (signature)
gpgme_data_release (signature);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]