aboutsummaryrefslogtreecommitdiffstats
path: root/tools/card-call-scd.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2019-01-29 07:48:53 +0000
committerWerner Koch <[email protected]>2019-01-29 08:32:20 +0000
commit237880175f59d372011cd2e20bb49726eeccf058 (patch)
tree3f33ff4bf6d008ca0553ba0a913792970c9c73c3 /tools/card-call-scd.c
parentagent: Clear bogus pinentry cache, when it causes an error. (diff)
downloadgnupg-237880175f59d372011cd2e20bb49726eeccf058.tar.gz
gnupg-237880175f59d372011cd2e20bb49726eeccf058.zip
card: Make printing of key information more flexible.
* tools/card-tool-misc.c: New. * tools/card-tool.h: Rewored data structures for key infos. * tools/gpg-card-tool.c: Ditto. * tools/card-call-scd.c: Ditto. -- Note that this also changes the way the key information is printed. Formerly we printed it like: Signature key ....: <openpgp-fingerprint> created ....: <timestamp> keygrip ... : <keygrip> now we do: Signature key ....: <keygrip> fingerprint : <openpgp-fingerprint> created ....: <timestamp> This is because a keygrip is always available but a fingerprint and the creation date are properties of an OpenPGP card. A standard way of listing keys is better than one depending on the type of card. Signed-off-by: Werner Koch <[email protected]>
Diffstat (limited to 'tools/card-call-scd.c')
-rw-r--r--tools/card-call-scd.c152
1 files changed, 119 insertions, 33 deletions
diff --git a/tools/card-call-scd.c b/tools/card-call-scd.c
index 7df7861d3..abf35ed17 100644
--- a/tools/card-call-scd.c
+++ b/tools/card-call-scd.c
@@ -132,6 +132,7 @@ release_card_info (card_info_t info)
{
int i;
+
if (!info)
return;
@@ -145,12 +146,18 @@ release_card_info (card_info_t info)
xfree (info->pubkey_url); info->pubkey_url = NULL;
xfree (info->login_data); info->login_data = NULL;
info->cafpr1len = info->cafpr2len = info->cafpr3len = 0;
- info->fpr1len = info->fpr2len = info->fpr3len = 0;
for (i=0; i < DIM(info->private_do); i++)
{
xfree (info->private_do[i]);
info->private_do[i] = NULL;
}
+ while (info->kinfo)
+ {
+ key_info_t kinfo = info->kinfo->next;
+ xfree (info->kinfo);
+ info->kinfo = kinfo;
+ }
+
}
@@ -534,6 +541,48 @@ get_serialno_cb (void *opaque, const char *line)
}
+
+/* For historical reasons OpenPGP cards simply use the numbers 1 to 3
+ * for the <keyref>. Other cards and future versions of
+ * scd/app-openpgp.c may print the full keyref; i.e. "OpenPGP.1"
+ * instead of "1". This is a helper to cope with that. */
+static const char *
+parse_keyref_helper (const char *string)
+{
+ if (*string == '1' && spacep (string+1))
+ return "OPENPGP.1";
+ else if (*string == '2' && spacep (string+1))
+ return "OPENPGP.2";
+ else if (*string == '3' && spacep (string+1))
+ return "OPENPGP.3";
+ else
+ return string;
+}
+
+
+/* Create a new key info object with KEYREF. All fields but the
+ * keyref are zeroed out. Never returns NULL. The created object is
+ * appended to the list at INFO. */
+static key_info_t
+create_kinfo (card_info_t info, const char *keyref)
+{
+ key_info_t kinfo, ki;
+
+ kinfo = xcalloc (1, sizeof *kinfo + strlen (keyref));
+ strcpy (kinfo->keyref, keyref);
+
+ if (!info->kinfo)
+ info->kinfo = kinfo;
+ else
+ {
+ for (ki=info->kinfo; ki->next; ki = ki->next)
+ ;
+ ki->next = kinfo;
+ }
+ return kinfo;
+}
+
+
/* The status callback to handle the LEARN and GETATTR commands. */
static gpg_error_t
learn_status_cb (void *opaque, const char *line)
@@ -541,6 +590,10 @@ learn_status_cb (void *opaque, const char *line)
struct card_info_s *parm = opaque;
const char *keyword = line;
int keywordlen;
+ char *line_buffer = NULL; /* In case we need a copy. */
+ char *pline;
+ key_info_t kinfo;
+ const char *keyref;
int i;
for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
@@ -635,18 +688,31 @@ learn_status_cb (void *opaque, const char *line)
}
else if (!memcmp (keyword, "KEY-FPR", keywordlen))
{
- int no = atoi (line);
-
- while (*line && !spacep (line))
- line++;
- while (spacep (line))
- line++;
- if (no == 1)
- parm->fpr1len = unhexify_fpr (line, parm->fpr1, sizeof parm->fpr1);
- else if (no == 2)
- parm->fpr2len = unhexify_fpr (line, parm->fpr2, sizeof parm->fpr2);
- else if (no == 3)
- parm->fpr3len = unhexify_fpr (line, parm->fpr3, sizeof parm->fpr3);
+ /* The format of such a line is:
+ * KEY-FPR <keyref> <fingerprintinhex>
+ */
+ const char *fpr;
+
+ line_buffer = pline = xstrdup (line);
+
+ keyref = parse_keyref_helper (pline);
+ while (*pline && !spacep (pline))
+ pline++;
+ if (*pline)
+ *pline++ = 0; /* Terminate keyref. */
+ while (spacep (pline)) /* Skip to the fingerprint. */
+ pline++;
+ fpr = pline;
+
+ /* Check whether we already have an item for the keyref. */
+ kinfo = find_kinfo (parm, keyref);
+ if (!kinfo) /* No: new entry. */
+ kinfo = create_kinfo (parm, keyref);
+ else /* Existing entry - clear the fpr. */
+ memset (kinfo->fpr, 0, sizeof kinfo->fpr);
+
+ /* Set or update or the fingerprint. */
+ kinfo->fprlen = unhexify_fpr (fpr, kinfo->fpr, sizeof kinfo->fpr);
}
break;
@@ -664,17 +730,28 @@ learn_status_cb (void *opaque, const char *line)
}
else if (!memcmp (keyword, "KEY-TIME", keywordlen))
{
- int no = atoi (line);
- while (* line && !spacep (line))
- line++;
- while (spacep (line))
- line++;
- if (no == 1)
- parm->fpr1time = strtoul (line, NULL, 10);
- else if (no == 2)
- parm->fpr2time = strtoul (line, NULL, 10);
- else if (no == 3)
- parm->fpr3time = strtoul (line, NULL, 10);
+ /* The format of such a line is:
+ * KEY-TIME <keyref> <timestamp>
+ */
+ const char *timestamp;
+
+ line_buffer = pline = xstrdup (line);
+
+ keyref = parse_keyref_helper (pline);
+ while (*pline && !spacep (pline))
+ pline++;
+ if (*pline)
+ *pline++ = 0; /* Terminate keyref. */
+ while (spacep (pline)) /* Skip to the timestamp. */
+ pline++;
+ timestamp = pline;
+
+ /* Check whether we already have an item for the keyref. */
+ kinfo = find_kinfo (parm, keyref);
+ if (!kinfo) /* No: new entry. */
+ kinfo = create_kinfo (parm, keyref);
+
+ kinfo->created = strtoul (timestamp, NULL, 10);
}
else if (!memcmp (keyword, "KEY-ATTR", keywordlen))
{
@@ -767,21 +844,29 @@ learn_status_cb (void *opaque, const char *line)
}
else if (!memcmp (keyword, "KEYPAIRINFO", keywordlen))
{
+ /* The format of such a line is:
+ * KEYPARINFO <hexgrip> <keyref>
+ */
const char *hexgrp = line;
- int no;
while (*line && !spacep (line))
line++;
while (spacep (line))
line++;
- if (strncmp (line, "OPENPGP.", 8))
- ;
- else if ((no = atoi (line+8)) == 1)
- unhexify_fpr (hexgrp, parm->grp1, sizeof parm->grp1);
- else if (no == 2)
- unhexify_fpr (hexgrp, parm->grp2, sizeof parm->grp2);
- else if (no == 3)
- unhexify_fpr (hexgrp, parm->grp3, sizeof parm->grp3);
+
+ keyref = line;
+
+ /* Check whether we already have an item for the keyref. */
+ kinfo = find_kinfo (parm, keyref);
+ if (!kinfo) /* New entry. */
+ kinfo = create_kinfo (parm, keyref);
+ else /* Existing entry - clear the grip. */
+ memset (kinfo->grip, 0, sizeof kinfo->grip);
+
+ /* Set or update the grip. Note that due to the
+ * calloc/memset an erroneous too short grip will be nul
+ * padded on the right. */
+ unhexify_fpr (hexgrp, kinfo->grip, sizeof kinfo->grip);
}
break;
@@ -809,6 +894,7 @@ learn_status_cb (void *opaque, const char *line)
break;
}
+ xfree (line_buffer);
return 0;
}