[gmime] Make GMimeMultipartSigned/Encrypted easier to use
- From: Jeffrey Stedfast <fejj src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gmime] Make GMimeMultipartSigned/Encrypted easier to use
- Date: Sun, 12 Mar 2017 12:11:49 +0000 (UTC)
commit 1ed4d589ea96999e09ae8a6397d6e9a1f62ba74b
Author: Jeffrey Stedfast <jestedfa microsoft com>
Date: Sat Mar 11 16:23:57 2017 -0500
Make GMimeMultipartSigned/Encrypted easier to use
PORTING | 8 +++
README.md | 117 ++++++++++++++++++++++++++++++++++
docs/reference/changes-3.0.sgml | 2 +
gmime/gmime-multipart-encrypted.c | 126 ++++++++++++++++++-------------------
gmime/gmime-multipart-encrypted.h | 10 +--
gmime/gmime-multipart-signed.c | 89 +++++++++++++-------------
gmime/gmime-multipart-signed.h | 6 +-
tests/test-pgpmime.c | 90 ++++++++++++++------------
tests/test-smime.c | 8 +--
9 files changed, 288 insertions(+), 168 deletions(-)
---
diff --git a/PORTING b/PORTING
index e8ebe54..4669de7 100644
--- a/PORTING
+++ b/PORTING
@@ -118,6 +118,14 @@ Porting from GMime 2.6 to GMime 3.0
- g_mime_part_[get,set]_content_object() have been renamed to
g_mime_part_[get,set]_content().
+- g_mime_multipart_encrypted_encrypt() no longer takes a GMimeMultipartEncrypted
+ argument nor does it return int. Instead, this function now returns a newly
+ allocated GMimeMultipartEncrypted.
+
+- g_mime_multipart_signed_sign() no longer takes a GMimeMultipartSigned
+ argument nor does it return int. Instead, this function now returns a newly
+ allocated GMimeMultipartSigned.
+
Porting from GMime 2.4 to GMime 2.6
-----------------------------------
diff --git a/README.md b/README.md
index 579dd2c..6a23ec2 100644
--- a/README.md
+++ b/README.md
@@ -355,6 +355,123 @@ g_mime_message_set_mime_part (message, (GMimeObject *) mixed);
g_object_unref (mixed);
```
+### Encrypting Messages with S/MIME
+
+S/MIME uses an `application/pkcs7-mime` MIME part to encapsulate encrypted content (as well as other things).
+
+```c
+GMimeApplicationPkcs7Mime *encrypted;
+GMimeMessage *message;
+GError *err = NULL;
+GMimeObject *body;
+GPtrArray *rcpts;
+
+message = g_mime_message_new (TRUE);
+g_mime_message_add_mailbox (message, GMIME_ADDRESS_TYPE_FROM, "Joey", "joey friends com");
+g_mime_message_add_mailbox (message, GMIME_ADDRESS_TYPE_TO, "Alice", "alice wonderland com");
+g_mime_message_set_subject (message, "How you doin?", NULL);
+
+/* create our message body (perhaps a multipart/mixed with the message text and some
+ * image attachments, for example) */
+body = CreateMessageBody ();
+
+/* create a list of key ids to encrypt to */
+rcpts = g_ptr_array_new ();
+g_ptr_array_add (rcpts, "alice wonderland com"); // or use her fingerprint
+
+/* now to encrypt our message body */
+if (!(encrypted = g_mime_application_pkcs7_mime_encrypt (body, GMIME_ENCRYPT_FLAGS_NONE, rcpts, &err))) {
+ fprintf (stderr, "encrypt failed: %s\n", err->message);
+ g_object_unref (body);
+ g_error_free (err);
+ return;
+}
+
+g_object_unref (body);
+
+g_mime_message_set_mime_part (message, encrypted);
+g_object_unref (encrypted);
+```
+
+### Decrypting S/MIME Messages
+
+As mentioned earlier, S/MIME uses an `application/pkcs7-mime` part with an "smime-type" parameter with a
value of
+"enveloped-data" to encapsulate the encrypted content.
+
+The first thing you must do is find the `GMimeApplicationPkcs7Mime` part (see the section on traversing MIME
parts).
+
+```c
+if (GMIME_IS_APPLICATION_PKCS7_MIME (entity)) {
+ GMimeApplicationPkcs7Mime *pkcs7_mime = (GMimeApplicationPkcs7Mime *) entity;
+ GMimeSecureMimeType smime_type;
+
+ smime_type = g_mime_application_pkcs7_mime_get_smime_type (pkcs7_mime);
+ if (smime_type == GMIME_SECURE_MIME_TYPE_ENVELOPED_DATA)
+ return g_mime_application_pkcs7_mime_decrypt (pkcs7_mime, GMIME_DECRYPT_FLAGS_NONE, NULL, NULL,
&err);
+}
+```
+
+### Encrypting Messages with PGP/MIME
+
+Unlike S/MIME, PGP/MIME uses `multipart/encrypted` to encapsulate its encrypted data.
+
+```c
+GMimeMultipartEncrypted *encrypted;
+GMimeCryptoContext *ctx;
+GMimeMessage *message;
+GError *err = NULL;
+GMimeObject *body;
+GPtrArray *rcpts;
+
+message = g_mime_message_new (TRUE);
+g_mime_message_add_mailbox (message, GMIME_ADDRESS_TYPE_FROM, "Joey", "joey friends com");
+g_mime_message_add_mailbox (message, GMIME_ADDRESS_TYPE_TO, "Alice", "alice wonderland com");
+g_mime_message_set_subject (message, "How you doin?", NULL);
+
+/* create our message body (perhaps a multipart/mixed with the message text and some
+ * image attachments, for example) */
+body = CreateMessageBody ();
+
+/* create a list of key ids to encrypt to */
+rcpts = g_ptr_array_new ();
+g_ptr_array_add (rcpts, "alice wonderland com"); // or use her fingerprint
+
+/* now to encrypt our message body */
+ctx = g_mime_gpg_context_new ();
+
+encrypted = g_mime_multipart_encrypted_encrypt (ctx, body, FALSE, NULL, GMIME_DIGEST_ALGO_DEFAULT,
+ GMIME_ENCRYPT_FLAGS_NONE, rcpts, &err);
+g_ptr_array_free (rcpts, TRUE);
+g_object_unref (body);
+g_object_unref (ctx);
+
+if (encrypted == NULL) {
+ fprintf (stderr, "encrypt failed: %s\n", err->message);
+ g_error_free (err);
+ return;
+}
+
+g_mime_message_set_mime_part (message, encrypted);
+g_object_unref (encrypted);
+```
+
+### Decrypting PGP/MIME Messages
+
+As mentioned earlier, PGP/MIME uses a `multipart/encrypted` part to encapsulate the encrypted content.
+
+A `multipart/encrypted` contains exactly 2 parts: the first `GMimeObject` is the version information while
the
+second `GMimeObject` is the actual encrypted content and will typically be an `application/octet-stream`.
+
+The first thing you must do is find the `GMimeMultipartEncrypted` part (see the section on traversing MIME
parts).
+
+```c
+if (GMIME_IS_MULTIPART_ENCRYPTED (entity)) {
+ GMimeMultipartEncrypted *encrypted = (GMimeMultipartEncrypted *) entity;
+
+ return g_mime_multipart_encrypted_decrypt (encrypted, GMIME_DECRYPT_FLAGS_NONE, NULL, NULL, &err);
+}
+```
+
## Documentation
This is the README file for GMime. Additional documentation related to
diff --git a/docs/reference/changes-3.0.sgml b/docs/reference/changes-3.0.sgml
index 64d3d10..d990eee 100644
--- a/docs/reference/changes-3.0.sgml
+++ b/docs/reference/changes-3.0.sgml
@@ -32,6 +32,8 @@
<listitem><para><function>g_mime_crypto_context_verify()</function> no longer takes a 'digest'
argument as it was unused (it was originally meant to be a hint but wasnever really needed).</para></listitem>
<listitem><para><function>g_mime_multipart_signed_verify()</function> and
<function>g_mime_multipart_encrypted_decrypt()</function> no longer take GMimeCryptoContext arguments.
Instead, they instantiate their own contexts based on the protocol specified in the Content-Type header.
These methods now also take a flags argument and in the case of the decrypt() method, it now also takes a
session_key argument.</para></listitem>
<listitem><para>GMimeSignatureStatus and GMimeSignatureErrors have been merged into a single bitfield
(GMimeSignatureStatus) which mirrors gpgme_sigsum_t and thus
<function>g_mime_signature_get_errors()</function> and <function>g_mime_signature_set_errors()</function>
have been removed.</para></listitem>
+ <listitem><para><function>g_mime_multipart_encrypted_encrypt()</function> no longer takes a
GMimeMultipartEncrypted argument nor does it return int. Instead, this function now returns a newly allocated
GMimeMultipartEncrypted.</para></listitem>
+ <listitem><para><function>g_mime_multipart_signed_sign()</function> no longer takes a
GMimeMultipartSigned argument nor does it return int. Instead, this function now returns a newly allocated
GMimeMultipartSigned.</para></listitem>
</itemizedlist>
<para>Other API changes:</para>
<listitem><para><function>g_mime_set_user_charsets()</function> and
<function>g_mime_user_charsets()</function> have been removed. All encoding API's now have a way to specify a
charset to use and all decoder API's take a GMimeParserOptions argument that allows for specifying fallback
charsets.</para></listitem>
diff --git a/gmime/gmime-multipart-encrypted.c b/gmime/gmime-multipart-encrypted.c
index 5793654..f0a383a 100644
--- a/gmime/gmime-multipart-encrypted.c
+++ b/gmime/gmime-multipart-encrypted.c
@@ -129,7 +129,7 @@ g_mime_multipart_encrypted_new (void)
multipart = g_object_newv (GMIME_TYPE_MULTIPART_ENCRYPTED, 0, NULL);
content_type = g_mime_content_type_new ("multipart", "encrypted");
- g_mime_object_set_content_type (GMIME_OBJECT (multipart), content_type);
+ g_mime_object_set_content_type ((GMimeObject *) multipart, content_type);
g_object_unref (content_type);
return multipart;
@@ -138,9 +138,8 @@ g_mime_multipart_encrypted_new (void)
/**
* g_mime_multipart_encrypted_encrypt:
- * @mpe: multipart/encrypted object
- * @content: MIME part to encrypt
- * @ctx: encryption context
+ * @ctx: a #GMimeCryptoContext
+ * @entity: MIME part to encrypt
* @sign: %TRUE if the content should also be signed or %FALSE otherwise
* @userid: user id to use for signing (only used if @sign is %TRUE)
* @digest: digest algorithm to use when signing
@@ -148,49 +147,47 @@ g_mime_multipart_encrypted_new (void)
* @recipients: (element-type utf8): an array of recipients to encrypt to
* @err: a #GError
*
- * Attempts to encrypt (and conditionally sign) the @content MIME part
+ * Attempts to encrypt (and conditionally sign) the @entity MIME part
* to the public keys of @recipients using the @ctx encryption
- * context. If successful, the encrypted #GMimeObject is set as the
- * encrypted part of the multipart/encrypted object @mpe.
+ * context. If successful, a new multipart/encrypted object is returned.
*
- * Returns: %0 on success or %-1 on fail. If the encryption fails, an
- * exception will be set on @err to provide information as to why the
- * failure occured.
+ * Returns: a new #GMimeMultipartEncrypted object on success or %NULL on fail.
+ * If encrypting fails, an exception will be set on @err to provide information
+ * as to why the failure occured.
**/
-int
-g_mime_multipart_encrypted_encrypt (GMimeMultipartEncrypted *mpe, GMimeObject *content,
- GMimeCryptoContext *ctx, gboolean sign, const char *userid,
- GMimeDigestAlgo digest, GMimeEncryptFlags flags,
- GPtrArray *recipients, GError **err)
+GMimeMultipartEncrypted *
+g_mime_multipart_encrypted_encrypt (GMimeCryptoContext *ctx, GMimeObject *entity,
+ gboolean sign, const char *userid, GMimeDigestAlgo digest,
+ GMimeEncryptFlags flags, GPtrArray *recipients, GError **err)
{
GMimeParserOptions *options = g_mime_parser_options_get_default ();
- GMimeStream *filtered_stream, *ciphertext, *stream;
+ GMimeStream *filtered, *stream, *ciphertext;
GMimePart *version_part, *encrypted_part;
+ GMimeMultipartEncrypted *encrypted;
GMimeContentType *content_type;
- GMimeDataWrapper *wrapper;
- GMimeFilter *crlf_filter;
+ GMimeDataWrapper *content;
const char *protocol;
+ GMimeFilter *filter;
- g_return_val_if_fail (GMIME_IS_MULTIPART_ENCRYPTED (mpe), -1);
- g_return_val_if_fail (GMIME_IS_CRYPTO_CONTEXT (ctx), -1);
- g_return_val_if_fail (GMIME_IS_OBJECT (content), -1);
+ g_return_val_if_fail (GMIME_IS_CRYPTO_CONTEXT (ctx), NULL);
+ g_return_val_if_fail (GMIME_IS_OBJECT (entity), NULL);
if (!(protocol = g_mime_crypto_context_get_encryption_protocol (ctx))) {
g_set_error_literal (err, GMIME_ERROR, GMIME_ERROR_NOT_SUPPORTED, _("Encryption not
supported."));
- return -1;
+ return NULL;
}
/* get the cleartext */
stream = g_mime_stream_mem_new ();
- filtered_stream = g_mime_stream_filter_new (stream);
+ filtered = 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);
+ filter = g_mime_filter_crlf_new (TRUE, FALSE);
+ g_mime_stream_filter_add ((GMimeStreamFilter *) filtered, filter);
+ g_object_unref (filter);
- g_mime_object_write_to_stream (content, filtered_stream);
- g_mime_stream_flush (filtered_stream);
- g_object_unref (filtered_stream);
+ g_mime_object_write_to_stream (entity, filtered);
+ g_mime_stream_flush (filtered);
+ g_object_unref (filtered);
/* reset the content stream */
g_mime_stream_reset (stream);
@@ -200,7 +197,7 @@ g_mime_multipart_encrypted_encrypt (GMimeMultipartEncrypted *mpe, GMimeObject *c
if (g_mime_crypto_context_encrypt (ctx, sign, userid, digest, flags, recipients, stream, ciphertext,
err) == -1) {
g_object_unref (ciphertext);
g_object_unref (stream);
- return -1;
+ return NULL;
}
g_object_unref (stream);
@@ -212,47 +209,47 @@ g_mime_multipart_encrypted_encrypt (GMimeMultipartEncrypted *mpe, GMimeObject *c
g_object_unref (content_type);
content_type = g_mime_content_type_parse (options, protocol);
- g_mime_object_set_content_type (GMIME_OBJECT (version_part), content_type);
+ g_mime_object_set_content_type ((GMimeObject *) version_part, content_type);
g_mime_part_set_content_encoding (version_part, GMIME_CONTENT_ENCODING_7BIT);
stream = g_mime_stream_mem_new_with_buffer ("Version: 1\n", strlen ("Version: 1\n"));
- wrapper = g_mime_data_wrapper_new_with_stream (stream, GMIME_CONTENT_ENCODING_7BIT);
- g_mime_part_set_content (version_part, wrapper);
- g_object_unref (wrapper);
+ content = g_mime_data_wrapper_new_with_stream (stream, GMIME_CONTENT_ENCODING_7BIT);
+ g_mime_part_set_content (version_part, content);
+ g_object_unref (content);
g_object_unref (stream);
/* construct the encrypted mime part */
encrypted_part = g_mime_part_new_with_type ("application", "octet-stream");
g_mime_part_set_content_encoding (encrypted_part, GMIME_CONTENT_ENCODING_7BIT);
- wrapper = g_mime_data_wrapper_new_with_stream (ciphertext, GMIME_CONTENT_ENCODING_7BIT);
- g_mime_part_set_content (encrypted_part, wrapper);
+ content = g_mime_data_wrapper_new_with_stream (ciphertext, GMIME_CONTENT_ENCODING_7BIT);
+ g_mime_part_set_content (encrypted_part, content);
g_object_unref (ciphertext);
- g_object_unref (wrapper);
+ g_object_unref (content);
/* save the version and encrypted parts */
- /* FIXME: make sure there aren't any other parts?? */
- g_mime_multipart_add (GMIME_MULTIPART (mpe), GMIME_OBJECT (version_part));
- g_mime_multipart_add (GMIME_MULTIPART (mpe), GMIME_OBJECT (encrypted_part));
+ encrypted = g_mime_multipart_encrypted_new ();
+ g_mime_multipart_add ((GMimeMultipart *) encrypted, (GMimeObject *) version_part);
+ g_mime_multipart_add ((GMimeMultipart *) encrypted, (GMimeObject *) encrypted_part);
g_object_unref (encrypted_part);
g_object_unref (version_part);
/* set the content-type params for this multipart/encrypted part */
- g_mime_object_set_content_type_parameter (GMIME_OBJECT (mpe), "protocol", protocol);
- g_mime_multipart_set_boundary (GMIME_MULTIPART (mpe), NULL);
+ g_mime_object_set_content_type_parameter ((GMimeObject *) encrypted, "protocol", protocol);
+ g_mime_multipart_set_boundary ((GMimeMultipart *) encrypted, NULL);
- return 0;
+ return encrypted;
}
/**
* g_mime_multipart_encrypted_decrypt:
- * @mpe: multipart/encrypted object
+ * @encrypted: a #GMimeMultipartEncrypted
* @flags: a #GMimeDecryptFlags
* @session_key: session key to use or %NULL
* @result: a #GMimeDecryptionResult
* @err: a #GError
*
* Attempts to decrypt the encrypted MIME part contained within the
- * multipart/encrypted object @mpe.
+ * multipart/encrypted object @encrypted.
*
* When non-%NULL, @session_key should be a %NULL-terminated string,
* such as the one returned by g_mime_decrypt_result_get_session_key()
@@ -269,28 +266,27 @@ g_mime_multipart_encrypted_encrypt (GMimeMultipartEncrypted *mpe, GMimeObject *c
* @err to provide information as to why the failure occured.
**/
GMimeObject *
-g_mime_multipart_encrypted_decrypt (GMimeMultipartEncrypted *mpe, GMimeDecryptFlags flags,
+g_mime_multipart_encrypted_decrypt (GMimeMultipartEncrypted *encrypted, GMimeDecryptFlags flags,
const char *session_key, GMimeDecryptResult **result,
GError **err)
{
- GMimeObject *decrypted, *version, *encrypted;
- GMimeStream *stream, *ciphertext;
+ GMimeObject *decrypted, *version_part, *encrypted_part;
+ GMimeStream *filtered, *stream, *ciphertext;
const char *protocol, *supported;
- GMimeStream *filtered_stream;
GMimeContentType *mime_type;
GMimeDataWrapper *content;
- GMimeFilter *crlf_filter;
GMimeDecryptResult *res;
GMimeCryptoContext *ctx;
+ GMimeFilter *filter;
GMimeParser *parser;
char *content_type;
- g_return_val_if_fail (GMIME_IS_MULTIPART_ENCRYPTED (mpe), NULL);
+ g_return_val_if_fail (GMIME_IS_MULTIPART_ENCRYPTED (encrypted), NULL);
if (result)
*result = NULL;
- if (!(protocol = g_mime_object_get_content_type_parameter (GMIME_OBJECT (mpe), "protocol"))) {
+ if (!(protocol = g_mime_object_get_content_type_parameter ((GMimeObject *) encrypted, "protocol"))) {
g_set_error_literal (err, GMIME_ERROR, GMIME_ERROR_PROTOCOL_ERROR,
_("Cannot decrypt multipart/encrypted part: unspecified encryption
protocol."));
@@ -317,10 +313,10 @@ g_mime_multipart_encrypted_decrypt (GMimeMultipartEncrypted *mpe, GMimeDecryptFl
return NULL;
}
- version = g_mime_multipart_get_part (GMIME_MULTIPART (mpe), GMIME_MULTIPART_ENCRYPTED_VERSION);
+ version_part = g_mime_multipart_get_part ((GMimeMultipart *) encrypted,
GMIME_MULTIPART_ENCRYPTED_VERSION);
/* make sure the protocol matches the version part's content-type */
- content_type = g_mime_content_type_to_string (version->content_type);
+ content_type = g_mime_content_type_to_string (version_part->content_type);
if (g_ascii_strcasecmp (content_type, protocol) != 0) {
g_set_error_literal (err, GMIME_ERROR, GMIME_ERROR_PARSE_ERROR,
_("Cannot decrypt multipart/encrypted part: content-type does not match
protocol."));
@@ -333,8 +329,8 @@ g_mime_multipart_encrypted_decrypt (GMimeMultipartEncrypted *mpe, GMimeDecryptFl
g_free (content_type);
/* get the encrypted part and check that it is of type application/octet-stream */
- encrypted = g_mime_multipart_get_part (GMIME_MULTIPART (mpe), GMIME_MULTIPART_ENCRYPTED_CONTENT);
- mime_type = g_mime_object_get_content_type (encrypted);
+ encrypted_part = g_mime_multipart_get_part ((GMimeMultipart *) encrypted,
GMIME_MULTIPART_ENCRYPTED_CONTENT);
+ mime_type = g_mime_object_get_content_type (encrypted_part);
if (!g_mime_content_type_is_type (mime_type, "application", "octet-stream")) {
g_set_error_literal (err, GMIME_ERROR, GMIME_ERROR_PARSE_ERROR,
_("Cannot decrypt multipart/encrypted part: unexpected content type."));
@@ -344,30 +340,30 @@ g_mime_multipart_encrypted_decrypt (GMimeMultipartEncrypted *mpe, GMimeDecryptFl
}
/* get the ciphertext stream */
- content = g_mime_part_get_content (GMIME_PART (encrypted));
+ content = g_mime_part_get_content ((GMimePart *) encrypted_part);
ciphertext = g_mime_stream_mem_new ();
g_mime_data_wrapper_write_to_stream (content, ciphertext);
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);
+ filtered = g_mime_stream_filter_new (stream);
+ filter = g_mime_filter_crlf_new (FALSE, FALSE);
+ g_mime_stream_filter_add ((GMimeStreamFilter *) filtered, filter);
+ g_object_unref (filter);
/* get the cleartext */
- if (!(res = g_mime_crypto_context_decrypt (ctx, flags, session_key, ciphertext, filtered_stream,
err))) {
- g_object_unref (filtered_stream);
+ if (!(res = g_mime_crypto_context_decrypt (ctx, flags, session_key, ciphertext, filtered, err))) {
g_object_unref (ciphertext);
+ g_object_unref (filtered);
g_object_unref (stream);
g_object_unref (ctx);
return NULL;
}
- g_mime_stream_flush (filtered_stream);
- g_object_unref (filtered_stream);
+ g_mime_stream_flush (filtered);
g_object_unref (ciphertext);
+ g_object_unref (filtered);
g_object_unref (ctx);
g_mime_stream_reset (stream);
diff --git a/gmime/gmime-multipart-encrypted.h b/gmime/gmime-multipart-encrypted.h
index 8f6c771..6567aef 100644
--- a/gmime/gmime-multipart-encrypted.h
+++ b/gmime/gmime-multipart-encrypted.h
@@ -64,13 +64,11 @@ GType g_mime_multipart_encrypted_get_type (void);
GMimeMultipartEncrypted *g_mime_multipart_encrypted_new (void);
-int g_mime_multipart_encrypted_encrypt (GMimeMultipartEncrypted *mpe, GMimeObject *content,
- GMimeCryptoContext *ctx, gboolean sign,
- const char *userid, GMimeDigestAlgo digest,
- GMimeEncryptFlags flags, GPtrArray *recipients,
- GError **err);
+GMimeMultipartEncrypted *g_mime_multipart_encrypted_encrypt (GMimeCryptoContext *ctx, GMimeObject *entity,
+ gboolean sign, const char *user_id,
GMimeDigestAlgo digest,
+ GMimeEncryptFlags flags, GPtrArray *recipients,
GError **err);
-GMimeObject *g_mime_multipart_encrypted_decrypt (GMimeMultipartEncrypted *mpe,
+GMimeObject *g_mime_multipart_encrypted_decrypt (GMimeMultipartEncrypted *encrypted,
GMimeDecryptFlags flags,
const char *session_key,
GMimeDecryptResult **result,
diff --git a/gmime/gmime-multipart-signed.c b/gmime/gmime-multipart-signed.c
index 0632c9a..c12c601 100644
--- a/gmime/gmime-multipart-signed.c
+++ b/gmime/gmime-multipart-signed.c
@@ -143,7 +143,7 @@ g_mime_multipart_signed_new (void)
multipart = g_object_newv (GMIME_TYPE_MULTIPART_SIGNED, 0, NULL);
content_type = g_mime_content_type_new ("multipart", "signed");
- g_mime_object_set_content_type (GMIME_OBJECT (multipart), content_type);
+ g_mime_object_set_content_type ((GMimeObject *) multipart, content_type);
g_object_unref (content_type);
return multipart;
@@ -184,60 +184,57 @@ sign_prepare (GMimeObject *mime_part)
subpart = GMIME_MESSAGE_PART (mime_part)->message->mime_part;
sign_prepare (subpart);
} else {
- encoding = g_mime_part_get_content_encoding (GMIME_PART (mime_part));
+ encoding = g_mime_part_get_content_encoding ((GMimePart *) mime_part);
if (encoding != GMIME_CONTENT_ENCODING_BASE64)
- g_mime_part_set_content_encoding (GMIME_PART (mime_part),
- GMIME_CONTENT_ENCODING_QUOTEDPRINTABLE);
+ g_mime_part_set_content_encoding ((GMimePart *) mime_part,
GMIME_CONTENT_ENCODING_QUOTEDPRINTABLE);
}
}
/**
* g_mime_multipart_signed_sign:
- * @mps: multipart/signed object
- * @content: MIME part to sign
- * @ctx: encryption crypto context
+ * @ctx: a #GMimeCryptoContext
+ * @entity: MIME part to sign
* @userid: user id to sign with
* @digest: preferred digest algorithm
- * @err: exception
+ * @err: a #GError
*
* Attempts to sign the @content MIME part with @userid's private key
* using the @ctx signing context with the @digest algorithm. If
- * successful, the signed #GMimeObject is set as the signed part of
- * the multipart/signed object @mps.
+ * successful, a new multipart/signed object is returned.
*
- * Returns: %0 on success or %-1 on fail. If the signing fails, an
- * exception will be set on @err to provide information as to why the
- * failure occured.
+ * Returns: a new #GMimeMultipartSigned object on success or %NULL on fail.
+ * If signing fails, an exception will be set on @err to provide information
+ * as to why the failure occured.
**/
-int
-g_mime_multipart_signed_sign (GMimeMultipartSigned *mps, GMimeObject *content,
- GMimeCryptoContext *ctx, const char *userid,
- GMimeDigestAlgo digest, GError **err)
+GMimeMultipartSigned *
+g_mime_multipart_signed_sign (GMimeCryptoContext *ctx, GMimeObject *entity,
+ const char *userid, GMimeDigestAlgo digest,
+ GError **err)
{
GMimeParserOptions *options = g_mime_parser_options_get_default ();
GMimeStream *stream, *filtered, *sigstream;
GMimeContentType *content_type;
- GMimeDataWrapper *wrapper;
+ GMimeDataWrapper *content;
+ GMimeMultipartSigned *mps;
GMimePart *signature;
GMimeFilter *filter;
GMimeParser *parser;
const char *protocol;
const char *micalg;
- int rv;
+ int algo;
- g_return_val_if_fail (GMIME_IS_MULTIPART_SIGNED (mps), -1);
- g_return_val_if_fail (GMIME_IS_CRYPTO_CONTEXT (ctx), -1);
- g_return_val_if_fail (GMIME_IS_OBJECT (content), -1);
+ g_return_val_if_fail (GMIME_IS_CRYPTO_CONTEXT (ctx), NULL);
+ g_return_val_if_fail (GMIME_IS_OBJECT (entity), NULL);
if (!(protocol = g_mime_crypto_context_get_signature_protocol (ctx))) {
g_set_error_literal (err, GMIME_ERROR, GMIME_ERROR_NOT_SUPPORTED, _("Signing not
supported."));
- return -1;
+ return NULL;
}
/* Prepare all the parts for signing... */
- sign_prepare (content);
+ sign_prepare (entity);
/* get the cleartext */
stream = g_mime_stream_mem_new ();
@@ -245,34 +242,34 @@ g_mime_multipart_signed_sign (GMimeMultipartSigned *mps, GMimeObject *content,
/* Note: see rfc3156, section 3 - second note */
filter = g_mime_filter_from_new (GMIME_FILTER_FROM_MODE_ARMOR);
- g_mime_stream_filter_add (GMIME_STREAM_FILTER (filtered), filter);
+ g_mime_stream_filter_add ((GMimeStreamFilter *) filtered, filter);
g_object_unref (filter);
/* Note: see rfc3156, section 5.4 (this is the main difference between rfc2015 and rfc3156) */
filter = g_mime_filter_strip_new ();
- g_mime_stream_filter_add (GMIME_STREAM_FILTER (filtered), filter);
+ g_mime_stream_filter_add ((GMimeStreamFilter *) filtered, filter);
g_object_unref (filter);
- g_mime_object_write_to_stream (content, filtered);
+ g_mime_object_write_to_stream (entity, filtered);
g_mime_stream_flush (filtered);
- g_object_unref (filtered);
g_mime_stream_reset (stream);
+ g_object_unref (filtered);
/* Note: see rfc2015 or rfc3156, section 5.1 */
filtered = g_mime_stream_filter_new (stream);
filter = g_mime_filter_crlf_new (TRUE, FALSE);
- g_mime_stream_filter_add (GMIME_STREAM_FILTER (filtered), filter);
+ g_mime_stream_filter_add ((GMimeStreamFilter *) filtered, filter);
g_object_unref (filter);
/* construct the signature stream */
sigstream = g_mime_stream_mem_new ();
/* sign the content stream */
- if ((rv = g_mime_crypto_context_sign (ctx, TRUE, userid, digest, filtered, sigstream, err)) == -1) {
+ if ((algo = g_mime_crypto_context_sign (ctx, TRUE, userid, digest, filtered, sigstream, err)) == -1) {
g_object_unref (sigstream);
g_object_unref (filtered);
g_object_unref (stream);
- return -1;
+ return NULL;
}
g_object_unref (filtered);
@@ -280,15 +277,15 @@ g_mime_multipart_signed_sign (GMimeMultipartSigned *mps, GMimeObject *content,
g_mime_stream_reset (stream);
/* set the multipart/signed protocol and micalg */
- content_type = g_mime_object_get_content_type (GMIME_OBJECT (mps));
+ content_type = g_mime_object_get_content_type ((GMimeObject *) mps);
g_mime_content_type_set_parameter (content_type, "protocol", protocol);
- micalg = g_strdup (g_mime_crypto_context_digest_name (ctx, (GMimeDigestAlgo) rv));
+ micalg = g_strdup (g_mime_crypto_context_digest_name (ctx, (GMimeDigestAlgo) algo));
g_mime_content_type_set_parameter (content_type, "micalg", micalg);
- g_mime_multipart_set_boundary (GMIME_MULTIPART (mps), NULL);
+ g_mime_multipart_set_boundary ((GMimeMultipart *) mps, NULL);
/* construct the content part */
parser = g_mime_parser_new_with_stream (stream);
- content = g_mime_parser_construct_part (parser);
+ entity = g_mime_parser_construct_part (parser);
g_object_unref (stream);
g_object_unref (parser);
@@ -297,11 +294,11 @@ g_mime_multipart_signed_sign (GMimeMultipartSigned *mps, GMimeObject *content,
signature = g_mime_part_new_with_type (content_type->type, content_type->subtype);
g_object_unref (content_type);
- wrapper = g_mime_data_wrapper_new ();
- g_mime_data_wrapper_set_stream (wrapper, sigstream);
- g_mime_part_set_content (signature, wrapper);
+ content = g_mime_data_wrapper_new ();
+ g_mime_data_wrapper_set_stream (content, sigstream);
+ g_mime_part_set_content (signature, content);
g_object_unref (sigstream);
- g_object_unref (wrapper);
+ g_object_unref (content);
/* FIXME: temporary hack, this info should probably be set in
* the CryptoContext class - maybe ::sign can take/output a
@@ -312,13 +309,13 @@ g_mime_multipart_signed_sign (GMimeMultipartSigned *mps, GMimeObject *content,
}
/* save the content and signature parts */
- /* FIXME: make sure there aren't any other parts?? */
- g_mime_multipart_add (GMIME_MULTIPART (mps), content);
- g_mime_multipart_add (GMIME_MULTIPART (mps), (GMimeObject *) signature);
+ mps = g_mime_multipart_signed_new ();
+ g_mime_multipart_add ((GMimeMultipart *) mps, entity);
+ g_mime_multipart_add ((GMimeMultipart *) mps, (GMimeObject *) signature);
g_object_unref (signature);
- g_object_unref (content);
+ g_object_unref (entity);
- return 0;
+ return mps;
}
static gboolean
@@ -358,9 +355,9 @@ check_protocol_supported (const char *protocol, const char *supported)
/**
* g_mime_multipart_signed_verify:
- * @mps: multipart/signed object
+ * @mps: a #GMimeMultipartSigned
* @flags: a #GMimeVerifyFlags
- * @err: exception
+ * @err: a #GError
*
* Attempts to verify the signed MIME part contained within the
* multipart/signed object @mps.
diff --git a/gmime/gmime-multipart-signed.h b/gmime/gmime-multipart-signed.h
index b61c75a..b82f3d1 100644
--- a/gmime/gmime-multipart-signed.h
+++ b/gmime/gmime-multipart-signed.h
@@ -64,9 +64,9 @@ GType g_mime_multipart_signed_get_type (void);
GMimeMultipartSigned *g_mime_multipart_signed_new (void);
-int g_mime_multipart_signed_sign (GMimeMultipartSigned *mps, GMimeObject *content,
- GMimeCryptoContext *ctx, const char *userid,
- GMimeDigestAlgo digest, GError **err);
+GMimeMultipartSigned *g_mime_multipart_signed_sign (GMimeCryptoContext *ctx, GMimeObject *entity,
+ const char *userid, GMimeDigestAlgo digest,
+ GError **err);
GMimeSignatureList *g_mime_multipart_signed_verify (GMimeMultipartSigned *mps, GMimeVerifyFlags flags,
GError **err);
diff --git a/tests/test-pgpmime.c b/tests/test-pgpmime.c
index f31a9b9..9b0cebc 100644
--- a/tests/test-pgpmime.c
+++ b/tests/test-pgpmime.c
@@ -160,44 +160,14 @@ print_verify_results (GMimeSignatureList *signatures)
}
}
-#define MULTIPART_SIGNED_CONTENT "This is a test of the emergency broadcast system \
-with an sha1 detach-sign.\n\nFrom now on, there will be text to try and break \t\
- \nvarious things. For example, the F in \"From\" in the previous line...\n...and \
-the first dot of this line have been pre-encoded in the QP encoding in order to test \
-that GMime properly treats MIME part content as opaque.\nIf this still verifies okay, \
-then we have ourselves a winner I guess...\n"
-
-static void
-test_multipart_signed (GMimeCryptoContext *ctx)
+static GMimeMessage *
+create_message (GMimeObject *body)
{
- GMimeSignatureList *signatures;
- GMimeMultipartSigned *mps;
InternetAddressList *list;
InternetAddress *mailbox;
GMimeMessage *message;
- GMimeStream *stream;
GMimeParser *parser;
- GMimeTextPart *part;
- GError *err = NULL;
- Exception *ex;
-
- part = g_mime_text_part_new_with_subtype ("plain");
- g_mime_text_part_set_text (part, MULTIPART_SIGNED_CONTENT);
-
- /* create the multipart/signed container part */
- mps = g_mime_multipart_signed_new ();
-
- /* sign the part */
- g_mime_multipart_signed_sign (mps, GMIME_OBJECT (part), ctx, "no.user@no.domain",
- GMIME_DIGEST_ALGO_SHA1, &err);
- g_object_unref (part);
-
- if (err != NULL) {
- ex = exception_new ("signing failed: %s", err->message);
- g_object_unref (mps);
- g_error_free (err);
- throw (ex);
- }
+ GMimeStream *stream;
message = g_mime_message_new (TRUE);
@@ -218,14 +188,17 @@ test_multipart_signed (GMimeCryptoContext *ctx)
g_mime_message_set_subject (message, "This is a test message", NULL);
g_mime_object_set_header ((GMimeObject *) message, "X-Mailer", "main.c");
- g_mime_message_set_mime_part (message, GMIME_OBJECT (mps));
- g_object_unref (mps);
+ g_mime_message_set_mime_part (message, body);
stream = g_mime_stream_mem_new ();
g_mime_object_write_to_stream ((GMimeObject *) message, stream);
g_mime_stream_reset (stream);
g_object_unref (message);
+ /*fprintf (stderr, "-----BEGIN RAW MESSAGE-----\n%.*s-----END RAW MESSAGE-----\n",
+ GMIME_STREAM_MEM (stream)->buffer->len,
+ GMIME_STREAM_MEM (stream)->buffer->data);*/
+
parser = g_mime_parser_new ();
g_mime_parser_init_with_stream (parser, stream);
g_object_unref (stream);
@@ -233,6 +206,43 @@ test_multipart_signed (GMimeCryptoContext *ctx)
message = g_mime_parser_construct_message (parser);
g_object_unref (parser);
+ return message;
+}
+
+#define MULTIPART_SIGNED_CONTENT "This is a test of the emergency broadcast system \
+with an sha1 detach-sign.\n\nFrom now on, there will be text to try and break \t\
+ \nvarious things. For example, the F in \"From\" in the previous line...\n...and \
+the first dot of this line have been pre-encoded in the QP encoding in order to test \
+that GMime properly treats MIME part content as opaque.\nIf this still verifies okay, \
+then we have ourselves a winner I guess...\n"
+
+static void
+test_multipart_signed (GMimeCryptoContext *ctx)
+{
+ GMimeSignatureList *signatures;
+ GMimeMultipartSigned *mps;
+ GMimeMessage *message;
+ GMimeTextPart *part;
+ GError *err = NULL;
+ Exception *ex;
+
+ part = g_mime_text_part_new_with_subtype ("plain");
+ g_mime_text_part_set_text (part, MULTIPART_SIGNED_CONTENT);
+
+ /* sign the part */
+ mps = g_mime_multipart_signed_sign (ctx, (GMimeObject *) part, "no.user@no.domain",
+ GMIME_DIGEST_ALGO_SHA1, &err);
+ g_object_unref (part);
+
+ if (err != NULL) {
+ ex = exception_new ("signing failed: %s", err->message);
+ g_error_free (err);
+ throw (ex);
+ }
+
+ message = create_message ((GMimeObject *) mps);
+ g_object_unref (mps);
+
if (!GMIME_IS_MULTIPART_SIGNED (message->mime_part)) {
ex = exception_new ("resultant top-level mime part not a multipart/signed?");
g_object_unref (message);
@@ -278,22 +288,18 @@ create_encrypted_message (GMimeCryptoContext *ctx, gboolean sign,
g_mime_object_write_to_stream ((GMimeObject *) part, cleartext);
g_mime_stream_reset (cleartext);
- /* create the multipart/encrypted container part */
- mpe = g_mime_multipart_encrypted_new ();
-
/* encrypt the part */
recipients = g_ptr_array_new ();
g_ptr_array_add (recipients, "no.user@no.domain");
- g_mime_multipart_encrypted_encrypt (mpe, GMIME_OBJECT (part), ctx, sign,
- "no.user@no.domain", GMIME_DIGEST_ALGO_SHA256,
- GMIME_ENCRYPT_FLAGS_ALWAYS_TRUST, recipients, &err);
+ mpe = g_mime_multipart_encrypted_encrypt (ctx, (GMimeObject *) part,
+ sign, "no.user@no.domain", GMIME_DIGEST_ALGO_SHA256,
+ GMIME_ENCRYPT_FLAGS_ALWAYS_TRUST, recipients, &err);
g_ptr_array_free (recipients, TRUE);
g_object_unref (part);
if (err != NULL) {
ex = exception_new ("encryption failed: %s", err->message);
g_object_unref (cleartext);
- g_object_unref (mpe);
g_error_free (err);
throw (ex);
}
diff --git a/tests/test-smime.c b/tests/test-smime.c
index f842601..c3f7dc0 100644
--- a/tests/test-smime.c
+++ b/tests/test-smime.c
@@ -231,17 +231,13 @@ test_multipart_signed (GMimeCryptoContext *ctx)
part = g_mime_text_part_new_with_subtype ("plain");
g_mime_text_part_set_text (part, MULTIPART_SIGNED_CONTENT);
- /* create the multipart/signed container part */
- mps = g_mime_multipart_signed_new ();
-
/* sign the part */
- g_mime_multipart_signed_sign (mps, GMIME_OBJECT (part), ctx, "mimekit example com",
- GMIME_DIGEST_ALGO_SHA1, &err);
+ mps = g_mime_multipart_signed_sign (ctx, (GMimeObject *) part, "mimekit example com",
+ GMIME_DIGEST_ALGO_SHA1, &err);
g_object_unref (part);
if (err != NULL) {
ex = exception_new ("signing failed: %s", err->message);
- g_object_unref (mps);
g_error_free (err);
throw (ex);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]