about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorJames Booth <boothj5@gmail.com>2015-08-25 00:21:49 +0100
committerJames Booth <boothj5@gmail.com>2015-08-25 00:21:49 +0100
commitf6a91145b60ce924daaee6b2d5b9449c6170d9f9 (patch)
tree98f6fc96549928caca38276459dcbdaa7d7802b6 /src
parentd6ff72cf48bddf64e0e7e4b77929d0996770b2e6 (diff)
downloadprofani-tty-f6a91145b60ce924daaee6b2d5b9449c6170d9f9.tar.gz
Show public/private indicator when listing PGP keys
Diffstat (limited to 'src')
-rw-r--r--src/command/commands.c19
-rw-r--r--src/pgp/gpg.c102
-rw-r--r--src/pgp/gpg.h9
3 files changed, 98 insertions, 32 deletions
diff --git a/src/command/commands.c b/src/command/commands.c
index 082b1bf8..f3911aad 100644
--- a/src/command/commands.c
+++ b/src/command/commands.c
@@ -4211,22 +4211,29 @@ cmd_pgp(ProfWin *window, const char * const command, gchar **args)
     }
 
     if (g_strcmp0(args[0], "keys") == 0) {
-        GSList *keys = p_gpg_list_keys();
-        if (!keys) {
+        GHashTable *keys = p_gpg_list_keys();
+        if (!keys || g_hash_table_size(keys) == 0) {
             cons_show("No keys found");
             return TRUE;
         }
 
         cons_show("PGP keys:");
-        GSList *curr = keys;
+        GList *keylist = g_hash_table_get_keys(keys);
+        GList *curr = keylist;
         while (curr) {
-            ProfPGPKey *key = curr->data;
+            ProfPGPKey *key = g_hash_table_lookup(keys, curr->data);
             cons_show("  %s", key->name);
             cons_show("    ID          : %s", key->id);
             cons_show("    Fingerprint : %s", key->fp);
-            curr = g_slist_next(curr);
+            if (key->secret) {
+                cons_show("    Type        : PUBLIC, PRIVATE");
+            } else {
+                cons_show("    Type        : PUBLIC");
+            }
+            curr = g_list_next(curr);
         }
-        g_slist_free_full(keys, (GDestroyNotify)p_gpg_free_key);
+        g_list_free(keylist);
+        p_gpg_free_keys(keys);
         return TRUE;
     }
 
diff --git a/src/pgp/gpg.c b/src/pgp/gpg.c
index 6edab8d1..9d594be4 100644
--- a/src/pgp/gpg.c
+++ b/src/pgp/gpg.c
@@ -215,11 +215,38 @@ p_gpg_addkey(const char * const jid, const char * const keyid)
     return TRUE;
 }
 
-GSList *
+static ProfPGPKey *
+_p_gpg_key_new(void)
+{
+    ProfPGPKey *p_pgpkey = malloc(sizeof(ProfPGPKey));
+    p_pgpkey->id = NULL;
+    p_pgpkey->name = NULL;
+    p_pgpkey->fp = NULL;
+    p_pgpkey->encrypt = FALSE;
+    p_pgpkey->sign = FALSE;
+    p_pgpkey->certify = FALSE;
+    p_pgpkey->authenticate = FALSE;
+    p_pgpkey->secret = FALSE;
+
+    return p_pgpkey;
+}
+
+static void
+_p_gpg_free_key(ProfPGPKey *key)
+{
+    if (key) {
+        free(key->id);
+        free(key->name);
+        free(key->fp);
+        free(key);
+    }
+}
+
+GHashTable *
 p_gpg_list_keys(void)
 {
     gpgme_error_t error;
-    GSList *result = NULL;
+    GHashTable *result = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)_p_gpg_free_key);
 
     gpgme_ctx_t ctx;
     error = gpgme_new(&ctx);
@@ -231,25 +258,56 @@ p_gpg_list_keys(void)
 
     error = gpgme_op_keylist_start(ctx, NULL, 0);
     if (error == GPG_ERR_NO_ERROR) {
+        gpgme_key_t key;
+        error = gpgme_op_keylist_next(ctx, &key);
         while (!error) {
-            gpgme_key_t key;
-            error = gpgme_op_keylist_next(ctx, &key);
+            gpgme_subkey_t sub = key->subkeys;
 
-            if (error) {
-                break;
+            ProfPGPKey *p_pgpkey = _p_gpg_key_new();
+            p_pgpkey->id = strdup(sub->keyid);
+            p_pgpkey->name = strdup(key->uids->uid);
+            p_pgpkey->fp = strdup(sub->fpr);
+            if (sub->can_encrypt) p_pgpkey->encrypt = TRUE;
+            if (sub->can_authenticate) p_pgpkey->authenticate = TRUE;
+            if (sub->can_certify) p_pgpkey->certify = TRUE;
+            if (sub->can_sign) p_pgpkey->sign = TRUE;
+
+            sub = sub->next;
+            while (sub) {
+                if (sub->can_encrypt) p_pgpkey->encrypt = TRUE;
+                if (sub->can_authenticate) p_pgpkey->authenticate = TRUE;
+                if (sub->can_certify) p_pgpkey->certify = TRUE;
+                if (sub->can_sign) p_pgpkey->sign = TRUE;
+
+                sub = sub->next;
             }
 
-            ProfPGPKey *p_pgpkey = malloc(sizeof(ProfPGPKey));
-            p_pgpkey->id = strdup(key->subkeys->keyid);
-            p_pgpkey->name = strdup(key->uids->uid);
-            p_pgpkey->fp = strdup(key->subkeys->fpr);
+            g_hash_table_insert(result, strdup(p_pgpkey->name), p_pgpkey);
 
-            result = g_slist_append(result, p_pgpkey);
+            gpgme_key_unref(key);
+            error = gpgme_op_keylist_next(ctx, &key);
+        }
+    }
+
+    error = gpgme_op_keylist_start(ctx, NULL, 1);
+    if (error == GPG_ERR_NO_ERROR) {
+        gpgme_key_t key;
+        error = gpgme_op_keylist_next(ctx, &key);
+        while (!error) {
+            gpgme_subkey_t sub = key->subkeys;
+            while (sub) {
+                if (sub->secret) {
+                    ProfPGPKey *p_pgpkey = g_hash_table_lookup(result, key->uids->uid);
+                    if (p_pgpkey) {
+                        p_pgpkey->secret = TRUE;
+                    }
+                }
+                sub = sub->next;
+            }
 
             gpgme_key_unref(key);
+            error = gpgme_op_keylist_next(ctx, &key);
         }
-    } else {
-        log_error("GPG: Could not list keys. %s %s", gpgme_strsource(error), gpgme_strerror(error));
     }
 
     gpgme_release(ctx);
@@ -257,6 +315,13 @@ p_gpg_list_keys(void)
     return result;
 }
 
+void
+p_gpg_free_keys(GHashTable *keys)
+{
+    g_hash_table_destroy(keys);
+}
+
+
 GHashTable *
 p_gpg_fingerprints(void)
 {
@@ -269,17 +334,6 @@ p_gpg_libver(void)
     return libversion;
 }
 
-void
-p_gpg_free_key(ProfPGPKey *key)
-{
-    if (key) {
-        free(key->id);
-        free(key->name);
-        free(key->fp);
-        free(key);
-    }
-}
-
 gboolean
 p_gpg_valid_key(const char * const keyid)
 {
diff --git a/src/pgp/gpg.h b/src/pgp/gpg.h
index 3bdae37e..f4c3f4a2 100644
--- a/src/pgp/gpg.h
+++ b/src/pgp/gpg.h
@@ -39,19 +39,24 @@ typedef struct pgp_key_t {
     char *id;
     char *name;
     char *fp;
+    gboolean encrypt;
+    gboolean sign;
+    gboolean certify;
+    gboolean authenticate;
+    gboolean secret;
 } ProfPGPKey;
 
 void p_gpg_init(void);
 void p_gpg_close(void);
 void p_gpg_on_connect(const char * const barejid);
 void p_gpg_on_disconnect(void);
-GSList* p_gpg_list_keys(void);
+GHashTable* p_gpg_list_keys(void);
+void p_gpg_free_keys(GHashTable *keys);
 gboolean p_gpg_addkey(const char * const jid, const char * const keyid);
 GHashTable* p_gpg_fingerprints(void);
 gboolean p_gpg_valid_key(const char * const keyid);
 gboolean p_gpg_available(const char * const barejid);
 const char* p_gpg_libver(void);
-void p_gpg_free_key(ProfPGPKey *key);
 char* p_gpg_sign(const char * const str, const char * const fp);
 void p_gpg_verify(const char * const barejid, const char *const sign);
 char* p_gpg_encrypt(const char * const barejid, const char * const message);