[gmime] Added support for retrieving gpg session keys
- From: Jeffrey Stedfast <fejj src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gmime] Added support for retrieving gpg session keys
- Date: Sat, 3 Dec 2016 00:20:09 +0000 (UTC)
commit 8b854830e0fa06b968a40f2ab4e4267bd0cc4f97
Author: Jeffrey Stedfast <jestedfa microsoft com>
Date: Fri Dec 2 19:19:33 2016 -0500
Added support for retrieving gpg session keys
2016-12-02 Jeffrey Stedfast <fejj gnome org>
* gmime/gmime-gpg-context.c (gpg_ctx_free): Free the session_key.
(gpg_ctx_get_argv): Pass --show-session-key to gpg if requested.
(gpg_ctx_parse_status): Decode the session-key sent by gpg.
(gpg_decrypt): Set the session_key on the decrypt result.
(g_mime_gpg_context_get_retrieve_session_key): Added.
(g_mime_gpg_context_set_retrieve_session_key): Added.
* gmime/gmime-crypto-context.c (g_mime_decrypt_result_set_session_key): Added.
(g_mime_decryption_result_get_session_key): Added.
Thanks to Daniel Kahn Gillmor for this patch.
ChangeLog | 14 +++++++++++
gmime/gmime-crypto-context.c | 50 +++++++++++++++++++++++++++++++++++++++
gmime/gmime-crypto-context.h | 4 +++
gmime/gmime-gpg-context.c | 53 +++++++++++++++++++++++++++++++++++++++++-
gmime/gmime-gpg-context.h | 4 +++
tests/test-pgp.c | 5 ++++
tests/test-pgpmime.c | 9 ++++++-
7 files changed, 137 insertions(+), 2 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 0efb23c..3f05a1d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,19 @@
2016-12-02 Jeffrey Stedfast <fejj gnome org>
+ * gmime/gmime-gpg-context.c (gpg_ctx_free): Free the session_key.
+ (gpg_ctx_get_argv): Pass --show-session-key to gpg if requested.
+ (gpg_ctx_parse_status): Decode the session-key sent by gpg.
+ (gpg_decrypt): Set the session_key on the decrypt result.
+ (g_mime_gpg_context_get_retrieve_session_key): Added.
+ (g_mime_gpg_context_set_retrieve_session_key): Added.
+
+ * gmime/gmime-crypto-context.c (g_mime_decrypt_result_set_session_key): Added.
+ (g_mime_decryption_result_get_session_key): Added.
+
+ Thanks to Daniel Kahn Gillmor for this patch.
+
+2016-12-02 Jeffrey Stedfast <fejj gnome org>
+
* gmime/gmime-gpg-context.c (g_mime_gpg_context_new): Allow NULL for the gpg path
in order to use the default gpg path (i.e. "gpg").
diff --git a/gmime/gmime-crypto-context.c b/gmime/gmime-crypto-context.c
index 5269440..3b4171c 100644
--- a/gmime/gmime-crypto-context.c
+++ b/gmime/gmime-crypto-context.c
@@ -23,6 +23,8 @@
#include <config.h>
#endif
+#include <string.h>
+
#include "gmime-crypto-context.h"
#include "gmime-error.h"
@@ -573,6 +575,7 @@ g_mime_decrypt_result_init (GMimeDecryptResult *result, GMimeDecryptResultClass
result->mdc = GMIME_DIGEST_ALGO_DEFAULT;
result->recipients = NULL;
result->signatures = NULL;
+ result->session_key = NULL;
}
static void
@@ -586,6 +589,11 @@ g_mime_decrypt_result_finalize (GObject *object)
if (result->signatures)
g_object_unref (result->signatures);
+ if (result->session_key) {
+ memset (result->session_key, 0, strlen (result->session_key));
+ g_free (result->session_key);
+ }
+
G_OBJECT_CLASS (result_parent_class)->finalize (object);
}
@@ -755,3 +763,45 @@ g_mime_decryption_result_get_mdc (GMimeDecryptResult *result)
return result->mdc;
}
+
+
+/**
+ * g_mime_decrypt_result_set_session_key:
+ * @result: a #GMimeDecryptResult
+ * @session_key: a pointer to a null-terminated string representing the session key
+ *
+ * Set the session_key to be returned by this decryption result.
+ **/
+void
+g_mime_decrypt_result_set_session_key (GMimeDecryptResult *result, const char *session_key)
+{
+ g_return_if_fail (GMIME_IS_DECRYPT_RESULT (result));
+
+ if (result->session_key) {
+ memset (result->session_key, 0, strlen (result->session_key));
+ g_free (result->session_key);
+ }
+
+ result->session_key = g_strdup (session_key);
+}
+
+
+/**
+ * g_mime_decrypt_result_get_session_key:
+ * @result: a #GMimeDecryptResult
+ *
+ * Get the session_key used for this decryption, if the underlying
+ * crypto context is capable of and (configured to) retrieve session
+ * keys during decryption. See, for example,
+ * g_mime_gpg_context_set_retrieve_session_key().
+ *
+ * Returns: the session_key digest algorithm used, or NULL if no
+ * session key was requested or found.
+ **/
+const char *
+g_mime_decryption_result_get_session_key (GMimeDecryptResult *result)
+{
+ g_return_val_if_fail (GMIME_IS_DECRYPT_RESULT (result), GMIME_DIGEST_ALGO_DEFAULT);
+
+ return result->session_key;
+}
diff --git a/gmime/gmime-crypto-context.h b/gmime/gmime-crypto-context.h
index cd38760..72573ed 100644
--- a/gmime/gmime-crypto-context.h
+++ b/gmime/gmime-crypto-context.h
@@ -206,6 +206,7 @@ struct _GMimeDecryptResult {
GMimeSignatureList *signatures;
GMimeCipherAlgo cipher;
GMimeDigestAlgo mdc;
+ char *session_key;
};
struct _GMimeDecryptResultClass {
@@ -229,6 +230,9 @@ GMimeCipherAlgo g_mime_decrypt_result_get_cipher (GMimeDecryptResult *result);
void g_mime_decrypt_result_set_mdc (GMimeDecryptResult *result, GMimeDigestAlgo mdc);
GMimeDigestAlgo g_mime_decrypt_result_get_mdc (GMimeDecryptResult *result);
+void g_mime_decrypt_result_set_session_key (GMimeDecryptResult *result, const char *session_key);
+const char *g_mime_decrypt_result_get_session_key (GMimeDecryptResult *result);
+
G_END_DECLS
#endif /* __GMIME_CRYPTO_CONTEXT_H__ */
diff --git a/gmime/gmime-gpg-context.c b/gmime/gmime-gpg-context.c
index afc1d52..74f8a4e 100644
--- a/gmime/gmime-gpg-context.c
+++ b/gmime/gmime-gpg-context.c
@@ -168,6 +168,7 @@ g_mime_gpg_context_class_init (GMimeGpgContextClass *klass)
static void
g_mime_gpg_context_init (GMimeGpgContext *ctx, GMimeGpgContextClass *klass)
{
+ ctx->retrieve_session_key = FALSE;
ctx->auto_key_retrieve = FALSE;
ctx->always_trust = FALSE;
ctx->use_agent = FALSE;
@@ -313,6 +314,7 @@ struct _GpgCtx {
GMimeCertificateList *encrypted_to; /* full list of encrypted-to recipients */
GMimeSignatureList *signatures;
GMimeSignature *signature;
+ char *session_key;
int exit_status;
@@ -375,6 +377,7 @@ gpg_ctx_new (GMimeGpgContext *ctx)
gpg->need_id = NULL;
gpg->encrypted_to = NULL;
+ gpg->session_key = NULL;
gpg->signatures = NULL;
gpg->signature = NULL;
@@ -555,6 +558,11 @@ gpg_ctx_free (struct _GpgCtx *gpg)
if (gpg->encrypted_to)
g_object_unref (gpg->encrypted_to);
+ if (gpg->session_key) {
+ memset (gpg->session_key, 0, strlen (gpg->session_key));
+ g_free (gpg->session_key);
+ }
+
if (gpg->signatures)
g_object_unref (gpg->signatures);
@@ -691,6 +699,9 @@ gpg_ctx_get_argv (struct _GpgCtx *gpg, int status_fd, int secret_fd, char ***str
if (gpg->use_agent)
g_ptr_array_add (args, "--use-agent");
+ if (gpg->ctx->retrieve_session_key)
+ g_ptr_array_add (args, "--show-session-key");
+
g_ptr_array_add (args, "--decrypt");
g_ptr_array_add (args, "--output");
g_ptr_array_add (args, "-");
@@ -1326,6 +1337,8 @@ gpg_ctx_parse_status (struct _GpgCtx *gpg, GError **err)
/* nothing to do... we'll grab the MDC used in DECRYPTION_INFO */
} else if (!strncmp (status, "BADMDC", 6)) {
/* nothing to do, this will only be sent after DECRYPTION_FAILED */
+ } else if (!strncmp (status, "SESSION_KEY", 11)) {
+ status = next_token (status, &gpg->session_key);
} else {
gpg_ctx_parse_signer_info (gpg, status);
}
@@ -2059,10 +2072,12 @@ gpg_decrypt (GMimeCryptoContext *context, GMimeStream *istream,
result = g_mime_decrypt_result_new ();
result->recipients = gpg->encrypted_to;
result->signatures = gpg->signatures;
+ result->session_key = gpg->session_key;
result->cipher = gpg->cipher;
result->mdc = gpg->digest;
gpg->encrypted_to = NULL;
gpg->signatures = NULL;
+ gpg->session_key = NULL;
gpg_ctx_free (gpg);
@@ -2305,7 +2320,7 @@ g_mime_gpg_context_get_use_agent (GMimeGpgContext *ctx)
/**
* g_mime_gpg_context_set_use_agent:
* @ctx: a #GMimeGpgContext
- * @use_agent: always trust flag
+ * @use_agent: use agent flag
*
* Sets the @use_agent flag on the gpg context, which indicates that
* GnuPG should attempt to use gpg-agent for credentials.
@@ -2317,3 +2332,39 @@ 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)
+{
+ 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)
+{
+ g_return_if_fail (GMIME_IS_GPG_CONTEXT (ctx));
+
+ ctx->retrieve_session_key = retrieve_session_key;
+}
diff --git a/gmime/gmime-gpg-context.h b/gmime/gmime-gpg-context.h
index a088e90..4f17fe0 100644
--- a/gmime/gmime-gpg-context.h
+++ b/gmime/gmime-gpg-context.h
@@ -51,6 +51,7 @@ struct _GMimeGpgContext {
gboolean always_trust;
gboolean use_agent;
char *path;
+ gboolean retrieve_session_key;
};
struct _GMimeGpgContextClass {
@@ -73,6 +74,9 @@ 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-pgp.c b/tests/test-pgp.c
index 928f7f1..81a4b9d 100644
--- a/tests/test-pgp.c
+++ b/tests/test-pgp.c
@@ -163,6 +163,11 @@ test_decrypt (GMimeCryptoContext *ctx, gboolean sign, GMimeStream *cleartext, GM
ex = exception_new ("unexpected signature");
}
+ /* Did not ask for session_key -- it should not be present.
+ We test asking for session_key over in test-pgpmime.c */
+ if (ex == NULL && result->session_key)
+ ex = exception_new ("got session_key when not requested");
+
g_object_unref (result);
if (ex != NULL) {
diff --git a/tests/test-pgpmime.c b/tests/test-pgpmime.c
index cdb83e4..27e6b6b 100644
--- a/tests/test-pgpmime.c
+++ b/tests/test-pgpmime.c
@@ -351,9 +351,15 @@ test_multipart_encrypted (GMimeCryptoContext *ctx, gboolean sign)
throw (ex);
}
+ if (!result->session_key) {
+ ex = exception_new ("No session key returned!");
+ g_object_unref (cleartext);
+ throw (ex);
+ }
+
if (result->signatures)
v(print_verify_results (result->signatures));
-
+
if (sign) {
if (!result->signatures || get_sig_status (result->signatures) != GMIME_SIGNATURE_STATUS_GOOD)
ex = exception_new ("signature status expected to be GOOD");
@@ -436,6 +442,7 @@ 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);
testsuite_check ("GMimeGpgContext::import");
try {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]