summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeffrey Stedfast <jestedfa@microsoft.com>2020-03-09 19:47:48 -0400
committerJeffrey Stedfast <jestedfa@microsoft.com>2020-03-09 19:47:48 -0400
commit9493bb491aebfd8cff1d8e4d5290ad810e600a78 (patch)
tree9efb7cc189a990e6dbf48d591062ea47d16f3641
parent96f23da05a4df623e4eefacc925801e0a1738d58 (diff)
downloadgmime-9493bb491aebfd8cff1d8e4d5290ad810e600a78.tar.gz
Improved gpg key lookup code
-rw-r--r--gmime/gmime-gpgme-utils.c95
1 files changed, 56 insertions, 39 deletions
diff --git a/gmime/gmime-gpgme-utils.c b/gmime/gmime-gpgme-utils.c
index 041dd020..08699dbc 100644
--- a/gmime/gmime-gpgme-utils.c
+++ b/gmime/gmime-gpgme-utils.c
@@ -97,18 +97,61 @@ g_mime_gpgme_passphrase_callback (void *hook, const char *uid_hint, const char *
}
-#define KEY_IS_OK(k) (!((k)->expired || (k)->revoked || (k)->disabled || (k)->invalid))
+static gboolean
+g_mime_gpgme_key_is_usable (gpgme_key_t key, gboolean secret, time_t now, gpgme_error_t *err)
+{
+ gpgme_subkey_t subkey;
+
+ *err = GPG_ERR_NO_ERROR;
+
+ /* first, check the state of the key itself... */
+ if (key->expired)
+ *err = GPG_ERR_KEY_EXPIRED;
+ else if (key->revoked)
+ *err = GPG_ERR_CERT_REVOKED;
+ else if (key->disabled)
+ *err = GPG_ERR_KEY_DISABLED;
+ else if (key->invalid)
+ *err = GPG_ERR_BAD_KEY;
+
+ if (*err != GPG_ERR_NO_ERROR)
+ return FALSE;
+
+ /* now check if there is a subkey that we can use */
+ subkey = key->subkeys;
+
+ while (subkey) {
+ if ((secret && subkey->can_sign) || (!secret && subkey->can_encrypt)) {
+ if (subkey->expired || (subkey->expires != 0 && subkey->expires <= now))
+ *err = GPG_ERR_KEY_EXPIRED;
+ else if (subkey->revoked)
+ *err = GPG_ERR_CERT_REVOKED;
+ else if (subkey->disabled)
+ *err = GPG_ERR_KEY_DISABLED;
+ else if (subkey->invalid)
+ *err = GPG_ERR_BAD_KEY;
+ else
+ return TRUE;
+ }
+
+ subkey = subkey->next;
+ }
+
+ if (*err == GPG_ERR_NO_ERROR)
+ *err = GPG_ERR_BAD_KEY;
+
+ return FALSE;
+}
/* Note: this function based on code in Balsa written by Albrecht Dreß. */
static gpgme_key_t
g_mime_gpgme_get_key_by_name (gpgme_ctx_t ctx, const char *name, gboolean secret, GError **err)
{
+ gpgme_error_t key_error = GPG_ERR_NO_ERROR;
time_t now = time (NULL);
gpgme_key_t key = NULL;
- gpgme_subkey_t subkey;
- gboolean bad = FALSE;
+ gboolean found = FALSE;
gpgme_error_t error;
- int errval = 0;
if ((error = gpgme_op_keylist_start (ctx, name, secret)) != GPG_ERR_NO_ERROR) {
if (secret) {
@@ -126,37 +169,11 @@ g_mime_gpgme_get_key_by_name (gpgme_ctx_t ctx, const char *name, gboolean secret
while ((error = gpgme_op_keylist_next (ctx, &key)) == GPG_ERR_NO_ERROR) {
/* check if this key and the relevant subkey are usable */
- if (KEY_IS_OK (key)) {
- subkey = key->subkeys;
-
- while (subkey) {
- if ((secret && subkey->can_sign) || (!secret && subkey->can_encrypt)) {
- if (KEY_IS_OK (subkey) && (subkey->expires == 0 || subkey->expires > now)) {
- errval = GPG_ERR_NO_ERROR;
- break;
- }
-
- if (subkey->expired)
- errval = GPG_ERR_KEY_EXPIRED;
- }
-
- subkey = subkey->next;
- }
-
- if (subkey)
- break;
-
- if (errval == GPG_ERR_NO_ERROR)
- errval = GPG_ERR_BAD_KEY;
- } else {
- if (key->expired)
- errval = GPG_ERR_KEY_EXPIRED;
- else
- errval = GPG_ERR_BAD_KEY;
- }
+ if (g_mime_gpgme_key_is_usable (key, secret, now, &key_error))
+ break;
gpgme_key_unref (key);
- bad = TRUE;
+ found = TRUE;
key = NULL;
}
@@ -178,22 +195,22 @@ g_mime_gpgme_get_key_by_name (gpgme_ctx_t ctx, const char *name, gboolean secret
if (!key) {
if (strchr (name, '@')) {
- if (bad) {
- g_set_error (err, GMIME_GPGME_ERROR, errval,
+ if (found && key_error != GPG_ERR_NO_ERROR) {
+ g_set_error (err, GMIME_GPGME_ERROR, key_error,
_("A key for %s is present, but it is expired, disabled, revoked or invalid"),
name);
} else {
g_set_error (err, GMIME_GPGME_ERROR, GPG_ERR_NOT_FOUND,
- _("Could not find a key for %s"), name);
+ _("Could not find a suitable key for %s"), name);
}
} else {
- if (bad) {
- g_set_error (err, GMIME_GPGME_ERROR, errval,
+ if (found && key_error != GPG_ERR_NO_ERROR) {
+ g_set_error (err, GMIME_GPGME_ERROR, key_error,
_("A key with id %s is present, but it is expired, disabled, revoked or invalid"),
name);
} else {
g_set_error (err, GMIME_GPGME_ERROR, GPG_ERR_NOT_FOUND,
- _("Could not find a key with id %s"), name);
+ _("Could not find a suitable key with id %s"), name);
}
}