mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
gpg: Import stray revocation certificates.
* g10/kbnode.c (new_kbnode2): New. * g10/import.c (delete_inv_parts): New arg r_otherrevsigs to store misplaced revocations. (import_revoke_cert): Allow to pass an entire list. (import_one): Import revocations found by delete_inv_parts. -- It might be useful to distribute revocations of old keys along with new keys. This is in particicualrr useful for WKD stored keys. This patch allows to put unrelated standalone revocations into a key. For example they can simply appended to a keyblock. Right now it is a bit inaesthetic to see diagnostics about misplaced or bad revocation signatures.
This commit is contained in:
parent
ed6eb90192
commit
7aaedfb107
64
g10/import.c
64
g10/import.c
@ -126,7 +126,8 @@ static int import_revoke_cert (ctrl_t ctrl, kbnode_t node, unsigned int options,
|
|||||||
static int chk_self_sigs (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid,
|
static int chk_self_sigs (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid,
|
||||||
int *non_self);
|
int *non_self);
|
||||||
static int delete_inv_parts (ctrl_t ctrl, kbnode_t keyblock,
|
static int delete_inv_parts (ctrl_t ctrl, kbnode_t keyblock,
|
||||||
u32 *keyid, unsigned int options);
|
u32 *keyid, unsigned int options,
|
||||||
|
kbnode_t *r_otherrevsigs);
|
||||||
static int any_uid_left (kbnode_t keyblock);
|
static int any_uid_left (kbnode_t keyblock);
|
||||||
static void remove_all_non_self_sigs (kbnode_t *keyblock, u32 *keyid);
|
static void remove_all_non_self_sigs (kbnode_t *keyblock, u32 *keyid);
|
||||||
static int merge_blocks (ctrl_t ctrl, unsigned int options,
|
static int merge_blocks (ctrl_t ctrl, unsigned int options,
|
||||||
@ -438,7 +439,7 @@ read_key_from_file_or_buffer (ctrl_t ctrl, const char *fname,
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!delete_inv_parts (ctrl, keyblock, keyid, 0) )
|
if (!delete_inv_parts (ctrl, keyblock, keyid, 0, NULL) )
|
||||||
{
|
{
|
||||||
err = gpg_error (GPG_ERR_NO_USER_ID);
|
err = gpg_error (GPG_ERR_NO_USER_ID);
|
||||||
goto leave;
|
goto leave;
|
||||||
@ -1871,8 +1872,9 @@ update_key_origin (kbnode_t keyblock, u32 curtime, int origin, const char *url)
|
|||||||
* even most error messages are suppressed. ORIGIN is the origin of
|
* even most error messages are suppressed. ORIGIN is the origin of
|
||||||
* the key (0 for unknown) and URL the corresponding URL. FROM_SK
|
* the key (0 for unknown) and URL the corresponding URL. FROM_SK
|
||||||
* indicates that the key has been made from a secret key. If R_SAVED
|
* indicates that the key has been made from a secret key. If R_SAVED
|
||||||
* is not NULL a boolean will be stored indicating whether the keyblock
|
* is not NULL a boolean will be stored indicating whether the
|
||||||
* has valid parts.
|
* keyblock has valid parts. Unless OTHERREVSIGS is NULL it is
|
||||||
|
* updated with encountered new revocation signatures.
|
||||||
*/
|
*/
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
import_one_real (ctrl_t ctrl,
|
import_one_real (ctrl_t ctrl,
|
||||||
@ -1880,7 +1882,8 @@ import_one_real (ctrl_t ctrl,
|
|||||||
unsigned char **fpr, size_t *fpr_len, unsigned int options,
|
unsigned char **fpr, size_t *fpr_len, unsigned int options,
|
||||||
int from_sk, int silent,
|
int from_sk, int silent,
|
||||||
import_screener_t screener, void *screener_arg,
|
import_screener_t screener, void *screener_arg,
|
||||||
int origin, const char *url, int *r_valid)
|
int origin, const char *url, int *r_valid,
|
||||||
|
kbnode_t *otherrevsigs)
|
||||||
{
|
{
|
||||||
gpg_error_t err = 0;
|
gpg_error_t err = 0;
|
||||||
PKT_public_key *pk;
|
PKT_public_key *pk;
|
||||||
@ -2021,7 +2024,7 @@ import_one_real (ctrl_t ctrl,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Delete invalid parts and bail out if there are no user ids left. */
|
/* Delete invalid parts and bail out if there are no user ids left. */
|
||||||
if (!delete_inv_parts (ctrl, keyblock, keyid, options))
|
if (!delete_inv_parts (ctrl, keyblock, keyid, options, otherrevsigs))
|
||||||
{
|
{
|
||||||
if (!silent)
|
if (!silent)
|
||||||
{
|
{
|
||||||
@ -2413,10 +2416,12 @@ import_one (ctrl_t ctrl,
|
|||||||
int origin, const char *url, int *r_valid)
|
int origin, const char *url, int *r_valid)
|
||||||
{
|
{
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
|
kbnode_t otherrevsigs = NULL;
|
||||||
|
kbnode_t node;
|
||||||
|
|
||||||
err = import_one_real (ctrl, keyblock, stats, fpr, fpr_len, options,
|
err = import_one_real (ctrl, keyblock, stats, fpr, fpr_len, options,
|
||||||
from_sk, silent, screener, screener_arg,
|
from_sk, silent, screener, screener_arg,
|
||||||
origin, url, r_valid);
|
origin, url, r_valid, &otherrevsigs);
|
||||||
if (gpg_err_code (err) == GPG_ERR_TOO_LARGE
|
if (gpg_err_code (err) == GPG_ERR_TOO_LARGE
|
||||||
&& gpg_err_source (err) == GPG_ERR_SOURCE_KEYBOX
|
&& gpg_err_source (err) == GPG_ERR_SOURCE_KEYBOX
|
||||||
&& ((options & (IMPORT_SELF_SIGS_ONLY | IMPORT_CLEAN))
|
&& ((options & (IMPORT_SELF_SIGS_ONLY | IMPORT_CLEAN))
|
||||||
@ -2432,8 +2437,17 @@ import_one (ctrl_t ctrl,
|
|||||||
options |= IMPORT_SELF_SIGS_ONLY | IMPORT_CLEAN;
|
options |= IMPORT_SELF_SIGS_ONLY | IMPORT_CLEAN;
|
||||||
err = import_one_real (ctrl, keyblock, stats, fpr, fpr_len, options,
|
err = import_one_real (ctrl, keyblock, stats, fpr, fpr_len, options,
|
||||||
from_sk, silent, screener, screener_arg,
|
from_sk, silent, screener, screener_arg,
|
||||||
origin, url, r_valid);
|
origin, url, r_valid, &otherrevsigs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Finally try to import other revocation certificates. For example
|
||||||
|
* those of a former key appended to the current key. */
|
||||||
|
if (!err)
|
||||||
|
{
|
||||||
|
for (node = otherrevsigs; node; node = node->next)
|
||||||
|
import_revoke_cert (ctrl, node, options, stats);
|
||||||
|
}
|
||||||
|
release_kbnode (otherrevsigs);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3422,9 +3436,8 @@ list_standalone_revocation (ctrl_t ctrl, PKT_signature *sig, int sigrc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/****************
|
/* Import a revocation certificate; only the first packet in the
|
||||||
* Import a revocation certificate; this is a single signature packet.
|
* NODE-list is considered. */
|
||||||
*/
|
|
||||||
static int
|
static int
|
||||||
import_revoke_cert (ctrl_t ctrl, kbnode_t node, unsigned int options,
|
import_revoke_cert (ctrl_t ctrl, kbnode_t node, unsigned int options,
|
||||||
struct import_stats_s *stats)
|
struct import_stats_s *stats)
|
||||||
@ -3441,10 +3454,12 @@ import_revoke_cert (ctrl_t ctrl, kbnode_t node, unsigned int options,
|
|||||||
/* No error output for --show-keys. */
|
/* No error output for --show-keys. */
|
||||||
silent = (options & (IMPORT_SHOW | IMPORT_DRY_RUN));
|
silent = (options & (IMPORT_SHOW | IMPORT_DRY_RUN));
|
||||||
|
|
||||||
log_assert (!node->next );
|
|
||||||
log_assert (node->pkt->pkttype == PKT_SIGNATURE );
|
log_assert (node->pkt->pkttype == PKT_SIGNATURE );
|
||||||
log_assert (IS_KEY_REV (node->pkt->pkt.signature));
|
log_assert (IS_KEY_REV (node->pkt->pkt.signature));
|
||||||
|
|
||||||
|
/* FIXME: We can do better here by using the issuer fingerprint if
|
||||||
|
* available. We should also make use of get_keyblock_byfprint_fast. */
|
||||||
|
|
||||||
keyid[0] = node->pkt->pkt.signature->keyid[0];
|
keyid[0] = node->pkt->pkt.signature->keyid[0];
|
||||||
keyid[1] = node->pkt->pkt.signature->keyid[1];
|
keyid[1] = node->pkt->pkt.signature->keyid[1];
|
||||||
|
|
||||||
@ -3788,12 +3803,15 @@ chk_self_sigs (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid, int *non_self)
|
|||||||
/* Delete all parts which are invalid and those signatures whose
|
/* Delete all parts which are invalid and those signatures whose
|
||||||
* public key algorithm is not available in this implementation; but
|
* public key algorithm is not available in this implementation; but
|
||||||
* consider RSA as valid, because parse/build_packets knows about it.
|
* consider RSA as valid, because parse/build_packets knows about it.
|
||||||
|
* If R_OTHERREVSIGS is not NULL, it is used to return a list of
|
||||||
|
* revocation certificates which have been deleted from KEYBLOCK but
|
||||||
|
* should be handled later.
|
||||||
*
|
*
|
||||||
* Returns: True if at least one valid user-id is left over.
|
* Returns: True if at least one valid user-id is left over.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
delete_inv_parts (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid,
|
delete_inv_parts (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid,
|
||||||
unsigned int options)
|
unsigned int options, kbnode_t *r_otherrevsigs)
|
||||||
{
|
{
|
||||||
kbnode_t node;
|
kbnode_t node;
|
||||||
int nvalid=0, uid_seen=0, subkey_seen=0;
|
int nvalid=0, uid_seen=0, subkey_seen=0;
|
||||||
@ -3883,6 +3901,16 @@ delete_inv_parts (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid,
|
|||||||
if(opt.verbose)
|
if(opt.verbose)
|
||||||
log_info( _("key %s: revocation certificate"
|
log_info( _("key %s: revocation certificate"
|
||||||
" at wrong place - skipped\n"),keystr(keyid));
|
" at wrong place - skipped\n"),keystr(keyid));
|
||||||
|
if (r_otherrevsigs)
|
||||||
|
{
|
||||||
|
PACKET *pkt;
|
||||||
|
|
||||||
|
pkt = xcalloc (1, sizeof *pkt);
|
||||||
|
pkt->pkttype = PKT_SIGNATURE;
|
||||||
|
pkt->pkt.signature = copy_signature
|
||||||
|
(NULL, node->pkt->pkt.signature);
|
||||||
|
*r_otherrevsigs = new_kbnode2 (*r_otherrevsigs, pkt);
|
||||||
|
}
|
||||||
delete_kbnode( node );
|
delete_kbnode( node );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -3905,6 +3933,16 @@ delete_inv_parts (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid,
|
|||||||
delete_kbnode( node );
|
delete_kbnode( node );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (r_otherrevsigs)
|
||||||
|
{
|
||||||
|
PACKET *pkt;
|
||||||
|
|
||||||
|
pkt = xcalloc (1, sizeof *pkt);
|
||||||
|
pkt->pkttype = PKT_SIGNATURE;
|
||||||
|
pkt->pkt.signature = copy_signature
|
||||||
|
(NULL, node->pkt->pkt.signature);
|
||||||
|
*r_otherrevsigs = new_kbnode2 (*r_otherrevsigs, pkt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (node->pkt->pkttype == PKT_SIGNATURE
|
else if (node->pkt->pkttype == PKT_SIGNATURE
|
||||||
|
13
g10/kbnode.c
13
g10/kbnode.c
@ -98,6 +98,19 @@ new_kbnode( PACKET *pkt )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Same as new_kbnode but insert the new node in front of LIST. Returns
|
||||||
|
* the new list. */
|
||||||
|
kbnode_t
|
||||||
|
new_kbnode2 (kbnode_t list, PACKET *pkt)
|
||||||
|
{
|
||||||
|
kbnode_t n;
|
||||||
|
|
||||||
|
n = new_kbnode (pkt);
|
||||||
|
n->next = list;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
KBNODE
|
KBNODE
|
||||||
clone_kbnode( KBNODE node )
|
clone_kbnode( KBNODE node )
|
||||||
{
|
{
|
||||||
|
@ -569,6 +569,7 @@ gpg_error_t hexkeygrip_from_pk (PKT_public_key *pk, char **r_grip);
|
|||||||
|
|
||||||
/*-- kbnode.c --*/
|
/*-- kbnode.c --*/
|
||||||
KBNODE new_kbnode( PACKET *pkt );
|
KBNODE new_kbnode( PACKET *pkt );
|
||||||
|
kbnode_t new_kbnode2 (kbnode_t list, PACKET *pkt);
|
||||||
KBNODE clone_kbnode( KBNODE node );
|
KBNODE clone_kbnode( KBNODE node );
|
||||||
void release_kbnode( KBNODE n );
|
void release_kbnode( KBNODE n );
|
||||||
void delete_kbnode( KBNODE node );
|
void delete_kbnode( KBNODE node );
|
||||||
|
Loading…
x
Reference in New Issue
Block a user