[gmime-devel] [PATCH] Generalize {set,get}_retrieve_session_key



This is a proposed patch to make the retrival of session keys generic
across different types of GMimeCryptoContext.

Currently, GMimeGpgContext is the only implementation capable of
implementing it, but this provides a framework for other
implementations to offer the same functionality (while providing
sensible default behavior if they don't).

I don't know that i have much preference one way or the other for the
API here, but i figure i'd lay out the two options so that the only
remaining work is choosing between them.

My feelings won't be hurt if this patch is rejected because you plan
to stick with previous API :)
---
 gmime/gmime-crypto-context.c | 67 ++++++++++++++++++++++++++++++++++++++++++++
 gmime/gmime-crypto-context.h | 12 ++++++++
 gmime/gmime-gpg-context.c    | 45 +++++++++++++----------------
 gmime/gmime-gpg-context.h    |  3 --
 tests/test-pgpmime.c         | 13 ++++++++-
 tests/test-smime.c           |  9 ++++++
 6 files changed, 120 insertions(+), 29 deletions(-)

diff --git a/gmime/gmime-crypto-context.c b/gmime/gmime-crypto-context.c
index ef160cc..ef5255e 100644
--- a/gmime/gmime-crypto-context.c
+++ b/gmime/gmime-crypto-context.c
@@ -54,6 +54,10 @@ static const char *crypto_get_encryption_protocol (GMimeCryptoContext *ctx);
 
 static const char *crypto_get_key_exchange_protocol (GMimeCryptoContext *ctx);
 
+static int crypto_set_retrieve_session_key (GMimeCryptoContext *ctx, gboolean retrieve_session_key,
+                                            GError **err);
+static gboolean crypto_get_retrieve_session_key (GMimeCryptoContext *ctx);
+
 static int crypto_sign (GMimeCryptoContext *ctx, const char *userid,
                        GMimeDigestAlgo digest, GMimeStream *istream,
                        GMimeStream *ostream, GError **err);
@@ -130,6 +134,8 @@ g_mime_crypto_context_class_init (GMimeCryptoContextClass *klass)
        klass->get_signature_protocol = crypto_get_signature_protocol;
        klass->get_encryption_protocol = crypto_get_encryption_protocol;
        klass->get_key_exchange_protocol = crypto_get_key_exchange_protocol;
+       klass->get_retrieve_session_key = crypto_get_retrieve_session_key;
+       klass->set_retrieve_session_key = crypto_set_retrieve_session_key;
 }
 
 static void
@@ -162,6 +168,67 @@ g_mime_crypto_context_set_request_password (GMimeCryptoContext *ctx, GMimePasswo
 }
 
 
+static gboolean
+crypto_get_retrieve_session_key (GMimeCryptoContext *ctx)
+{
+       return FALSE;
+};
+
+/**
+ * g_mime_crypto_context_get_retrieve_session_key:
+ * @ctx: a #GMimeCryptoContext
+ *
+ * Returns: an indication of whether @ctx is configured to retrieve a
+ * session key during decryption (see g_mime_decrypt_result_get_session_key()).
+ **/
+gboolean
+g_mime_crypto_context_get_retrieve_session_key (GMimeCryptoContext *ctx)
+{
+       g_return_val_if_fail (GMIME_IS_CRYPTO_CONTEXT (ctx), FALSE);
+
+       return GMIME_CRYPTO_CONTEXT_GET_CLASS (ctx)->get_retrieve_session_key (ctx);
+}
+
+static int
+crypto_set_retrieve_session_key (GMimeCryptoContext *ctx, gboolean retrieve_session_key,
+                                GError **err)
+{
+       if (retrieve_session_key == FALSE)
+               return 0;
+       
+       g_set_error (err, GMIME_ERROR, GMIME_ERROR_NOT_SUPPORTED,
+                    "Session key retrieval is not supported by this crypto context");
+       
+       return -1;
+}
+
+/**
+ * g_mime_crypto_context_set_retrieve_session_key:
+ * @ctx: a #GMimeCryptoContext
+ * @retrieve_session_key: whether to retrieve session keys during decryption
+ * @err: a #GError
+ *
+ * Configures whether @ctx should produce a session key during future
+ * decryption operations (see
+ * g_mime_decrypt_result_get_session_key()).
+ *
+ * Returns: %0 on success or %-1 on fail.
+ **/
+int
+g_mime_crypto_context_set_retrieve_session_key (GMimeCryptoContext *ctx,
+                                               gboolean retrieve_session_key,
+                                               GError **err)
+{
+       if (!GMIME_IS_CRYPTO_CONTEXT (ctx)) {
+               g_set_error (err, GMIME_ERROR, GMIME_ERROR_NOT_SUPPORTED,
+                            "Not a GMimeCryptoContext, can't set retrieve_session_key");
+               return -1;
+       }
+       return GMIME_CRYPTO_CONTEXT_GET_CLASS (ctx)->set_retrieve_session_key (ctx, retrieve_session_key, 
err);
+}
+
+
+
 static GMimeDigestAlgo
 crypto_digest_id (GMimeCryptoContext *ctx, const char *name)
 {
diff --git a/gmime/gmime-crypto-context.h b/gmime/gmime-crypto-context.h
index 6f337c4..33bf224 100644
--- a/gmime/gmime-crypto-context.h
+++ b/gmime/gmime-crypto-context.h
@@ -117,6 +117,12 @@ struct _GMimeCryptoContextClass {
        GMimeDecryptResult *     (* decrypt_session)     (GMimeCryptoContext *ctx, const char *session_key,
                                                          GMimeStream *istream, GMimeStream *ostream,
                                                          GError **err);
+       
+       gboolean                 (* get_retrieve_session_key) (GMimeCryptoContext *ctx);
+       
+       int                      (* set_retrieve_session_key) (GMimeCryptoContext *ctx,
+                                                              gboolean retrieve_session_key,
+                                                              GError **err);
 };
 
 
@@ -124,6 +130,12 @@ GType g_mime_crypto_context_get_type (void);
 
 void g_mime_crypto_context_set_request_password (GMimeCryptoContext *ctx, GMimePasswordRequestFunc 
request_passwd);
 
+gboolean g_mime_crypto_context_get_retrieve_session_key (GMimeCryptoContext *ctx);
+
+int g_mime_crypto_context_set_retrieve_session_key (GMimeCryptoContext *ctx,
+                                                   gboolean retrieve_session_key,
+                                                   GError **err);
+
 /* digest algo mapping */
 GMimeDigestAlgo g_mime_crypto_context_digest_id (GMimeCryptoContext *ctx, const char *name);
 
diff --git a/gmime/gmime-gpg-context.c b/gmime/gmime-gpg-context.c
index e39465c..5e9c14b 100644
--- a/gmime/gmime-gpg-context.c
+++ b/gmime/gmime-gpg-context.c
@@ -86,6 +86,11 @@ static GMimeDigestAlgo gpg_digest_id (GMimeCryptoContext *ctx, const char *name)
 
 static const char *gpg_digest_name (GMimeCryptoContext *ctx, GMimeDigestAlgo digest);
 
+static gboolean gpg_get_retrieve_session_key (GMimeCryptoContext *context);
+
+static int gpg_set_retrieve_session_key (GMimeCryptoContext *ctx, gboolean retrieve_session_key,
+                                        GError **err);
+
 static int gpg_sign (GMimeCryptoContext *ctx, const char *userid,
                     GMimeDigestAlgo digest, GMimeStream *istream,
                     GMimeStream *ostream, GError **err);
@@ -168,6 +173,8 @@ g_mime_gpg_context_class_init (GMimeGpgContextClass *klass)
        crypto_class->get_signature_protocol = gpg_get_signature_protocol;
        crypto_class->get_encryption_protocol = gpg_get_encryption_protocol;
        crypto_class->get_key_exchange_protocol = gpg_get_key_exchange_protocol;
+       crypto_class->get_retrieve_session_key = gpg_get_retrieve_session_key;
+       crypto_class->set_retrieve_session_key = gpg_set_retrieve_session_key;
 }
 
 static void
@@ -2404,38 +2411,26 @@ g_mime_gpg_context_set_use_agent (GMimeGpgContext *ctx, gboolean use_agent)
        ctx->use_agent = use_agent;
 }
 
-/**
- * g_mime_gpg_context_get_retrieve_session_key:
- * @ctx: a #GMimeGpgContext
- *
- * Gets the retrieve_session_key flag on the gpg context.
- *
- * Returns: the retrieve_session_key flag on the gpg context, which
- * indicates that GnuPG should attempt to retrieve the session key for
- * any encrypted message.
- **/
-gboolean
-g_mime_gpg_context_get_retrieve_session_key (GMimeGpgContext *ctx)
+static gboolean
+gpg_get_retrieve_session_key (GMimeCryptoContext *context)
 {
+       GMimeGpgContext *ctx = (GMimeGpgContext *) context;
        g_return_val_if_fail (GMIME_IS_GPG_CONTEXT (ctx), FALSE);
        
        return ctx->retrieve_session_key;
 }
 
 
-/**
- * g_mime_gpg_context_set_retrieve_session_key:
- * @ctx: a #GMimeGpgContext
- * @retrieve_session_key: retrieve session key flag
- *
- * Sets the @retrieve_session_key flag on the gpg context, which
- * indicates that GnuPG should attempt to retrieve the session key for
- * any encrypted message.
- **/
-void
-g_mime_gpg_context_set_retrieve_session_key (GMimeGpgContext *ctx, gboolean retrieve_session_key)
+static int
+gpg_set_retrieve_session_key (GMimeCryptoContext *context, gboolean retrieve_session_key,
+                             GError **err)
 {
-       g_return_if_fail (GMIME_IS_GPG_CONTEXT (ctx));
-       
+       GMimeGpgContext *ctx = (GMimeGpgContext *) context;
+       if (!GMIME_IS_GPG_CONTEXT (ctx)) {
+               g_set_error (err, GMIME_ERROR, GMIME_ERROR_NOT_SUPPORTED,
+                            "Not a GMimeGpgContext, can't set retrieve_session_key");
+               return -1;
+       }
        ctx->retrieve_session_key = retrieve_session_key;
+       return 0;
 }
diff --git a/gmime/gmime-gpg-context.h b/gmime/gmime-gpg-context.h
index 4f17fe0..646a5a4 100644
--- a/gmime/gmime-gpg-context.h
+++ b/gmime/gmime-gpg-context.h
@@ -74,9 +74,6 @@ void g_mime_gpg_context_set_always_trust (GMimeGpgContext *ctx, gboolean always_
 gboolean g_mime_gpg_context_get_use_agent (GMimeGpgContext *ctx);
 void g_mime_gpg_context_set_use_agent (GMimeGpgContext *ctx, gboolean use_agent);
 
-gboolean g_mime_gpg_context_get_retrieve_session_key (GMimeGpgContext *ctx);
-void g_mime_gpg_context_set_retrieve_session_key (GMimeGpgContext *ctx, gboolean retrieve_session_key);
-
 G_END_DECLS
 
 #endif /* __GMIME_GPG_CONTEXT_H__ */
diff --git a/tests/test-pgpmime.c b/tests/test-pgpmime.c
index 90f3e5b..cfd2d81 100644
--- a/tests/test-pgpmime.c
+++ b/tests/test-pgpmime.c
@@ -444,6 +444,7 @@ int main (int argc, char *argv[])
        int i;
        GMimeStream *stream = NULL, *cleartext = NULL;
        char *session_key = NULL;
+       GError *err = NULL;
        
        g_mime_init (0);
        
@@ -466,7 +467,17 @@ int main (int argc, char *argv[])
        
        ctx = g_mime_gpg_context_new (request_passwd, NULL);
        g_mime_gpg_context_set_always_trust ((GMimeGpgContext *) ctx, TRUE);
-       g_mime_gpg_context_set_retrieve_session_key ((GMimeGpgContext *) ctx, TRUE);
+       if (g_mime_crypto_context_set_retrieve_session_key (ctx, TRUE, &err) != 0) {
+               fprintf (stderr, "Failed to set retrieve_session_key on GMimeGpgContext: %s\n",
+                        err ? err->message : "no error info returned" );
+               if (err)
+                       g_error_free (err);
+               return EXIT_FAILURE;
+       }
+       if (!g_mime_crypto_context_get_retrieve_session_key (ctx)) {
+               fprintf (stderr, "We set retrieve_session_key on GMimeGpgContext, but it did not stay 
set.\n");
+               return EXIT_FAILURE;
+       }
        
        testsuite_check ("GMimeGpgContext::import");
        try {
diff --git a/tests/test-smime.c b/tests/test-smime.c
index 3fe47d1..fa838e8 100644
--- a/tests/test-smime.c
+++ b/tests/test-smime.c
@@ -438,6 +438,15 @@ int main (int argc, char *argv[])
        ctx = g_mime_pkcs7_context_new (request_passwd);
        g_mime_pkcs7_context_set_always_trust ((GMimePkcs7Context *) ctx, TRUE);
        
+       if (g_mime_crypto_context_set_retrieve_session_key (ctx, TRUE, NULL) == 0) {
+               fprintf (stderr, "GMimePkcs7Context should not have allowed us to set retrieve_session_key to 
TRUE, since it is not implemented.\n");
+               return EXIT_FAILURE;
+       }
+       if (g_mime_crypto_context_get_retrieve_session_key (ctx)) {
+               fprintf (stderr, "GMimePkcs7Context should have returned FALSE for 
get_retrieve_session_key.\n");
+               return EXIT_FAILURE;
+       }
+       
        testsuite_check ("GMimePkcs7Context::import");
        try {
                key = g_build_filename (datadir, "gmime-cert.p7", NULL);
-- 
2.10.2



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