aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--g10/free-packet.c21
-rw-r--r--g10/getkey.c49
-rw-r--r--g10/gpgv.c8
-rw-r--r--g10/import.c77
-rw-r--r--g10/keylist.c82
-rw-r--r--g10/main.h2
-rw-r--r--g10/packet.h14
-rw-r--r--g10/test-stubs.c9
8 files changed, 188 insertions, 74 deletions
diff --git a/g10/free-packet.c b/g10/free-packet.c
index 0962af0fc..3a9e17665 100644
--- a/g10/free-packet.c
+++ b/g10/free-packet.c
@@ -161,6 +161,11 @@ release_public_key_parts (PKT_public_key *pk)
xfree (pk->updateurl);
pk->updateurl = NULL;
}
+ if (pk->revoked.reason_comment)
+ {
+ xfree (pk->revoked.reason_comment);
+ pk->revoked.reason_comment = NULL;
+ }
}
@@ -231,6 +236,10 @@ copy_public_key_basics (PKT_public_key *d, PKT_public_key *s)
d->seckey_info = NULL;
d->user_id = NULL;
d->prefs = NULL;
+ d->revoked.got_reason = 0;
+ d->revoked.reason_code = 0;
+ d->revoked.reason_comment = NULL;
+ d->revoked.reason_comment_len = 0;
n = pubkey_get_npkey (s->pubkey_algo);
i = 0;
@@ -274,6 +283,18 @@ copy_public_key (PKT_public_key *d, PKT_public_key *s)
d->serialno = xstrdup (s->serialno);
if (s->updateurl)
d->updateurl = xstrdup (s->updateurl);
+ if (s->revoked.got_reason)
+ {
+ d->revoked.got_reason = s->revoked.got_reason;
+ d->revoked.reason_code = s->revoked.reason_code;
+ if (s->revoked.reason_comment_len)
+ {
+ d->revoked.reason_comment = xmalloc (s->revoked.reason_comment_len);
+ memcpy (d->revoked.reason_comment, s->revoked.reason_comment,
+ s->revoked.reason_comment_len);
+ d->revoked.reason_comment_len = s->revoked.reason_comment_len;
+ }
+ }
return d;
}
diff --git a/g10/getkey.c b/g10/getkey.c
index e438859f4..6af6dc0a5 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -2738,13 +2738,42 @@ fixup_uidnode (KBNODE uidnode, KBNODE signode, u32 keycreated)
uid->flags.ks_modify = 0;
}
+
+/* Store the revocation signature into the RINFO struct. */
static void
sig_to_revoke_info (PKT_signature * sig, struct revoke_info *rinfo)
{
+ int reason_seq = 0;
+ size_t reason_n;
+ const byte *reason_p;
+
rinfo->date = sig->timestamp;
rinfo->algo = sig->pubkey_algo;
rinfo->keyid[0] = sig->keyid[0];
rinfo->keyid[1] = sig->keyid[1];
+ xfree (rinfo->reason_comment);
+ rinfo->reason_comment = NULL;
+ rinfo->reason_comment_len = 0;
+ rinfo->reason_code = 0;
+ rinfo->got_reason = 0;
+
+ while ((reason_p = enum_sig_subpkt (sig, 1, SIGSUBPKT_REVOC_REASON,
+ &reason_n, &reason_seq, NULL))
+ && !reason_n)
+ ; /* Skip over empty reason packets. */
+
+ if (reason_p)
+ {
+ rinfo->got_reason = 1;
+ rinfo->reason_code = *reason_p;
+ reason_n--; reason_p++;
+ if (reason_n)
+ {
+ rinfo->reason_comment = xmalloc (reason_n);
+ memcpy (rinfo->reason_comment, reason_p, reason_n);
+ rinfo->reason_comment_len = reason_n;
+ }
+ }
}
@@ -3564,7 +3593,7 @@ merge_selfsigs (ctrl_t ctrl, kbnode_t keyblock)
{
KBNODE k;
int revoked;
- struct revoke_info rinfo;
+ struct revoke_info rinfo = { 0 };
PKT_public_key *main_pk;
prefitem_t *prefs;
unsigned int mdc_feature;
@@ -3611,8 +3640,19 @@ merge_selfsigs (ctrl_t ctrl, kbnode_t keyblock)
pk->flags.valid = 0;
if (revoked && !pk->flags.revoked)
{
+ /* Copy RINFO reason part only the first time
+ * because we don't want to propagate the reason to
+ * the subkeys. This assumes that we get the public
+ * key first. */
pk->flags.revoked = revoked;
- memcpy (&pk->revoked, &rinfo, sizeof (rinfo));
+ memcpy (&pk->revoked, &rinfo, sizeof (rinfo));
+ if (rinfo.got_reason)
+ {
+ rinfo.got_reason = 0;
+ rinfo.reason_code = 0;
+ rinfo.reason_comment = NULL; /*(owner is pk->revoked)*/
+ rinfo.reason_comment_len = 0;
+ }
}
if (main_pk->has_expired)
{
@@ -3622,7 +3662,7 @@ merge_selfsigs (ctrl_t ctrl, kbnode_t keyblock)
}
}
}
- return;
+ goto leave;
}
/* Set the preference list of all keys to those of the primary real
@@ -3660,6 +3700,9 @@ merge_selfsigs (ctrl_t ctrl, kbnode_t keyblock)
pk->flags.aead = aead_feature;
}
}
+
+ leave:
+ xfree (rinfo.reason_comment);
}
diff --git a/g10/gpgv.c b/g10/gpgv.c
index b97548d9b..6d3d25f50 100644
--- a/g10/gpgv.c
+++ b/g10/gpgv.c
@@ -831,6 +831,14 @@ tofu_notice_key_changed (ctrl_t ctrl, kbnode_t kb)
}
+const char *
+revocation_reason_code_to_str (int code, char **freeme)
+{
+ (void)code;
+ *freeme = NULL;
+ return "";
+}
+
int
get_revocation_reason (PKT_signature *sig, char **r_reason,
char **r_comment, size_t *r_commentlen)
diff --git a/g10/import.c b/g10/import.c
index 48f0d5459..5dad290ca 100644
--- a/g10/import.c
+++ b/g10/import.c
@@ -3366,6 +3366,33 @@ import_secret_one (ctrl_t ctrl, kbnode_t keyblock,
}
+/* Return a string for the revocation reason CODE. R_FREEM must be an
+ * possibly unintialized ptr which should be freed by the caller after
+ * the return value has been consumed. */
+const char *
+revocation_reason_code_to_str (int code, char **freeme)
+{
+ /* Take care: get_revocation_reason has knowledge of the internal
+ * working of this fucntion. */
+ const char *result;
+
+ *freeme = NULL;
+ switch (code)
+ {
+ case 0x00: result = _("No reason specified"); break;
+ case 0x01: result = _("Key is superseded"); break;
+ case 0x02: result = _("Key has been compromised"); break;
+ case 0x03: result = _("Key is no longer used"); break;
+ case 0x20: result = _("User ID is no longer valid"); break;
+ default:
+ *freeme = xasprintf ("code=%02x", code);
+ result = *freeme;
+ break;
+ }
+
+ return result;
+}
+
/* Return the recocation reason from signature SIG. If no revocation
* reason is available 0 is returned, in other cases the reason
@@ -3383,9 +3410,8 @@ get_revocation_reason (PKT_signature *sig, char **r_reason,
int reason_seq = 0;
size_t reason_n;
const byte *reason_p;
- char reason_code_buf[20];
- const char *reason_text = NULL;
int reason_code = 0;
+ char *freeme;
if (r_reason)
*r_reason = NULL;
@@ -3397,26 +3423,15 @@ get_revocation_reason (PKT_signature *sig, char **r_reason,
&reason_n, &reason_seq, NULL))
&& !reason_n)
;
- if (reason_p)
+ if (reason_p && reason_n)
{
reason_code = *reason_p;
reason_n--; reason_p++;
- switch (reason_code)
- {
- case 0x00: reason_text = _("No reason specified"); break;
- case 0x01: reason_text = _("Key is superseded"); break;
- case 0x02: reason_text = _("Key has been compromised"); break;
- case 0x03: reason_text = _("Key is no longer used"); break;
- case 0x20: reason_text = _("User ID is no longer valid"); break;
- default:
- snprintf (reason_code_buf, sizeof reason_code_buf,
- "code=%02x", reason_code);
- reason_text = reason_code_buf;
- break;
- }
-
+ revocation_reason_code_to_str (reason_code, &freeme);
if (r_reason)
- *r_reason = xstrdup (reason_text);
+ *r_reason = freeme;
+ else
+ xfree (freeme);
if (r_comment && reason_n)
{
@@ -3533,31 +3548,7 @@ list_standalone_revocation (ctrl_t ctrl, PKT_signature *sig, int sigrc)
{
es_fprintf (es_stdout, " %s%s\n",
_("reason for revocation: "), reason_text);
- if (reason_comment)
- {
- const byte *s, *s_lf;
- size_t n, n_lf;
-
- s = reason_comment;
- n = reason_commentlen;
- s_lf = NULL;
- do
- {
- /* We don't want any empty lines, so we skip them. */
- for (;n && *s == '\n'; s++, n--)
- ;
- if (n)
- {
- s_lf = memchr (s, '\n', n);
- n_lf = s_lf? s_lf - s : n;
- es_fprintf (es_stdout, " %s",
- _("revocation comment: "));
- es_write_sanitized (es_stdout, s, n_lf, NULL, NULL);
- es_putc ('\n', es_stdout);
- s += n_lf; n -= n_lf;
- }
- } while (s_lf);
- }
+ print_revocation_reason_comment (reason_comment, reason_commentlen);
}
}
diff --git a/g10/keylist.c b/g10/keylist.c
index d1e9a90ff..8b679987b 100644
--- a/g10/keylist.c
+++ b/g10/keylist.c
@@ -1324,6 +1324,58 @@ parse_trust_name (const char *name, size_t namelen)
}
+void
+print_revocation_reason_comment (const char *comment, size_t comment_len)
+{
+ const byte *s, *s_lf;
+ size_t n, n_lf;
+
+ if (!comment || !comment_len)
+ return;
+
+ s = comment;
+ n = comment_len;
+ s_lf = NULL;
+ do
+ {
+ /* We don't want any empty lines, so we skip them. */
+ for (;n && *s == '\n'; s++, n--)
+ ;
+ if (n)
+ {
+ s_lf = memchr (s, '\n', n);
+ n_lf = s_lf? s_lf - s : n;
+ es_fprintf (es_stdout, " %s",
+ _("revocation comment: "));
+ es_write_sanitized (es_stdout, s, n_lf, NULL, NULL);
+ es_putc ('\n', es_stdout);
+ s += n_lf; n -= n_lf;
+ }
+ } while (s_lf);
+}
+
+
+static void
+print_revocation_reason (PKT_public_key *pk)
+{
+ char *freeme;
+ const char *codestr;
+
+ if (!pk->revoked.got_reason)
+ return;
+
+ if (!pk->revoked.reason_code && !pk->revoked.reason_comment)
+ return; /* Do not print "revocation reason: No reason specified". */
+
+ codestr = revocation_reason_code_to_str (pk->revoked.reason_code, &freeme);
+ es_fprintf (es_stdout, " %s%s\n",
+ _("reason for revocation: "), codestr);
+ xfree (freeme);
+ print_revocation_reason_comment (pk->revoked.reason_comment,
+ pk->revoked.reason_comment_len);
+}
+
+
/* Helper for list_keyblock_print. The caller must have set
* NODFLG_MARK_B to indicate self-signatures. */
static void
@@ -1502,31 +1554,7 @@ list_signature_print (ctrl_t ctrl, kbnode_t keyblock, kbnode_t node,
{
es_fprintf (es_stdout, " %s%s\n",
_("reason for revocation: "), reason_text);
- if (reason_comment)
- {
- const byte *s, *s_lf;
- size_t n, n_lf;
-
- s = reason_comment;
- n = reason_commentlen;
- s_lf = NULL;
- do
- {
- /* We don't want any empty lines, so we skip them. */
- for (;n && *s == '\n'; s++, n--)
- ;
- if (n)
- {
- s_lf = memchr (s, '\n', n);
- n_lf = s_lf? s_lf - s : n;
- es_fprintf (es_stdout, " %s",
- _("revocation comment: "));
- es_write_sanitized (es_stdout, s, n_lf, NULL, NULL);
- es_putc ('\n', es_stdout);
- s += n_lf; n -= n_lf;
- }
- } while (s_lf);
- }
+ print_revocation_reason_comment (reason_comment, reason_commentlen);
}
xfree (reason_text);
@@ -2763,6 +2791,10 @@ print_key_line (ctrl_t ctrl, estream_t fp, PKT_public_key *pk, int secret)
if (pk->flags.primary &&
!opt.fingerprint && !opt.with_fingerprint)
print_fingerprint (ctrl, fp, pk, 20);
+
+ /* Print the revocation reason. */
+ if (pk->flags.revoked)
+ print_revocation_reason (pk);
}
diff --git a/g10/main.h b/g10/main.h
index 546a0b5b8..c0a3d5fa2 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -407,6 +407,7 @@ gpg_error_t transfer_secret_keys (ctrl_t ctrl, struct import_stats_s *stats,
int collapse_uids (kbnode_t *keyblock);
int collapse_subkeys (kbnode_t *keyblock);
+const char *revocation_reason_code_to_str (int code, char **r_freeme);
int get_revocation_reason (PKT_signature *sig, char **r_reason,
char **r_comment, size_t *r_commentlen);
@@ -495,6 +496,7 @@ void print_key_info_log (ctrl_t ctrl, int loglevel, int indent,
PKT_public_key *pk, int secret);
void print_card_key_info (estream_t fp, KBNODE keyblock);
void print_key_line (ctrl_t ctrl, estream_t fp, PKT_public_key *pk, int secret);
+void print_revocation_reason_comment (const char *comment, size_t comment_len);
/*-- verify.c --*/
void print_file_status( int status, const char *name, int what );
diff --git a/g10/packet.h b/g10/packet.h
index 29e58d2df..ac6df7d5c 100644
--- a/g10/packet.h
+++ b/g10/packet.h
@@ -339,12 +339,20 @@ typedef struct
struct revoke_info
{
- /* revoked at this date */
+ /* Revoked at this date */
u32 date;
- /* the keyid of the revoking key (selfsig or designated revoker) */
+ /* The keyid of the revoking key (selfsig or designated revoker) */
u32 keyid[2];
- /* the algo of the revoking key */
+ /* A malloced string of len reason_comment_len with the raw reason
+ * string or NULL if not given. */
+ char *reason_comment;
+ size_t reason_comment_len;
+ /* The algo of the revoking key */
byte algo;
+ /* The reason code. */
+ byte reason_code;
+ /* Whether the above reason fields are valid. */
+ byte got_reason;
};
diff --git a/g10/test-stubs.c b/g10/test-stubs.c
index e9685b715..c6d6cdae5 100644
--- a/g10/test-stubs.c
+++ b/g10/test-stubs.c
@@ -571,6 +571,15 @@ tofu_notice_key_changed (ctrl_t ctrl, kbnode_t kb)
return 0;
}
+
+const char *
+revocation_reason_code_to_str (int code, char **freeme)
+{
+ (void)code;
+ *freeme = NULL;
+ return "";
+}
+
int
get_revocation_reason (PKT_signature *sig, char **r_reason,
char **r_comment, size_t *r_commentlen)