mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
gpg: Look up user ID to revoke by UID hash
* g10/keyedit.c (find_userid_by_namehash, find_userid): New. (keyedit_quick_revuid): Use find_userid() instead of iterating over the nodes of the keyblock. * tests/openpgp/quick-key-manipulation.scm: Add test for revoking a user ID specified by its hash. -- This makes it possible to specify the user ID to revoke as UID hash when calling --quick-revoke-uid. GnuPG-bug-id: 5936
This commit is contained in:
parent
f27a70ecc2
commit
35b1755070
120
g10/keyedit.c
120
g10/keyedit.c
@ -2447,6 +2447,68 @@ keyedit_quick_adduid (ctrl_t ctrl, const char *username, const char *newuid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Helper to find the UID node for namehash. On success, returns the UID node.
|
||||||
|
Otherwise, return NULL. */
|
||||||
|
kbnode_t
|
||||||
|
find_userid_by_namehash (kbnode_t keyblock, const char *namehash)
|
||||||
|
{
|
||||||
|
byte hash[NAMEHASH_LEN];
|
||||||
|
kbnode_t node = NULL;
|
||||||
|
|
||||||
|
if (!namehash)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
if (strlen (namehash) != NAMEHASH_LEN * 2)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
if (hex2bin (namehash, hash, NAMEHASH_LEN) < 0)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
for (node = keyblock; node; node = node->next)
|
||||||
|
{
|
||||||
|
if (node->pkt->pkttype == PKT_USER_ID)
|
||||||
|
{
|
||||||
|
namehash_from_uid (node->pkt->pkt.user_id);
|
||||||
|
if (!memcmp (node->pkt->pkt.user_id->namehash, hash, NAMEHASH_LEN))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
leave:
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Helper to find the UID node for uid. On success, returns the UID node.
|
||||||
|
Otherwise, return NULL. */
|
||||||
|
kbnode_t
|
||||||
|
find_userid (kbnode_t keyblock, const char *uid)
|
||||||
|
{
|
||||||
|
kbnode_t node = NULL;
|
||||||
|
size_t uidlen;
|
||||||
|
|
||||||
|
if (!keyblock || !uid)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
/* First try to find UID by namehash. */
|
||||||
|
node = find_userid_by_namehash (keyblock, uid);
|
||||||
|
if (node)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
uidlen = strlen (uid);
|
||||||
|
for (node = keyblock; node; node = node->next)
|
||||||
|
{
|
||||||
|
if (node->pkt->pkttype == PKT_USER_ID
|
||||||
|
&& uidlen == node->pkt->pkt.user_id->len
|
||||||
|
&& !memcmp (node->pkt->pkt.user_id->name, uid, uidlen))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
leave:
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Unattended revocation of a keyid. USERNAME specifies the
|
/* Unattended revocation of a keyid. USERNAME specifies the
|
||||||
key. UIDTOREV is the user id revoke from the key. */
|
key. UIDTOREV is the user id revoke from the key. */
|
||||||
void
|
void
|
||||||
@ -2457,7 +2519,6 @@ keyedit_quick_revuid (ctrl_t ctrl, const char *username, const char *uidtorev)
|
|||||||
kbnode_t keyblock = NULL;
|
kbnode_t keyblock = NULL;
|
||||||
kbnode_t node;
|
kbnode_t node;
|
||||||
int modified = 0;
|
int modified = 0;
|
||||||
size_t revlen;
|
|
||||||
size_t valid_uids;
|
size_t valid_uids;
|
||||||
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
#ifdef HAVE_W32_SYSTEM
|
||||||
@ -2470,7 +2531,7 @@ keyedit_quick_revuid (ctrl_t ctrl, const char *username, const char *uidtorev)
|
|||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
/* Too make sure that we do not revoke the last valid UID, we first
|
/* To make sure that we do not revoke the last valid UID, we first
|
||||||
count how many valid UIDs there are. */
|
count how many valid UIDs there are. */
|
||||||
valid_uids = 0;
|
valid_uids = 0;
|
||||||
for (node = keyblock; node; node = node->next)
|
for (node = keyblock; node; node = node->next)
|
||||||
@ -2479,40 +2540,35 @@ keyedit_quick_revuid (ctrl_t ctrl, const char *username, const char *uidtorev)
|
|||||||
&& !node->pkt->pkt.user_id->flags.expired);
|
&& !node->pkt->pkt.user_id->flags.expired);
|
||||||
|
|
||||||
/* Find the right UID. */
|
/* Find the right UID. */
|
||||||
revlen = strlen (uidtorev);
|
node = find_userid (keyblock, uidtorev);
|
||||||
for (node = keyblock; node; node = node->next)
|
if (node)
|
||||||
{
|
{
|
||||||
if (node->pkt->pkttype == PKT_USER_ID
|
struct revocation_reason_info *reason;
|
||||||
&& revlen == node->pkt->pkt.user_id->len
|
|
||||||
&& !memcmp (node->pkt->pkt.user_id->name, uidtorev, revlen))
|
/* Make sure that we do not revoke the last valid UID. */
|
||||||
|
if (valid_uids == 1
|
||||||
|
&& ! node->pkt->pkt.user_id->flags.revoked
|
||||||
|
&& ! node->pkt->pkt.user_id->flags.expired)
|
||||||
{
|
{
|
||||||
struct revocation_reason_info *reason;
|
log_error (_("cannot revoke the last valid user ID.\n"));
|
||||||
|
err = gpg_error (GPG_ERR_INV_USER_ID);
|
||||||
/* Make sure that we do not revoke the last valid UID. */
|
|
||||||
if (valid_uids == 1
|
|
||||||
&& ! node->pkt->pkt.user_id->flags.revoked
|
|
||||||
&& ! node->pkt->pkt.user_id->flags.expired)
|
|
||||||
{
|
|
||||||
log_error (_("cannot revoke the last valid user ID.\n"));
|
|
||||||
err = gpg_error (GPG_ERR_INV_USER_ID);
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
reason = get_default_uid_revocation_reason ();
|
|
||||||
err = core_revuid (ctrl, keyblock, node, reason, &modified);
|
|
||||||
release_revocation_reason_info (reason);
|
|
||||||
if (err)
|
|
||||||
goto leave;
|
|
||||||
err = keydb_update_keyblock (ctrl, kdbhd, keyblock);
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
log_error (_("update failed: %s\n"), gpg_strerror (err));
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
revalidation_mark (ctrl);
|
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reason = get_default_uid_revocation_reason ();
|
||||||
|
err = core_revuid (ctrl, keyblock, node, reason, &modified);
|
||||||
|
release_revocation_reason_info (reason);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
err = keydb_update_keyblock (ctrl, kdbhd, keyblock);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
log_error (_("update failed: %s\n"), gpg_strerror (err));
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
revalidation_mark (ctrl);
|
||||||
|
goto leave;
|
||||||
}
|
}
|
||||||
err = gpg_error (GPG_ERR_NO_USER_ID);
|
err = gpg_error (GPG_ERR_NO_USER_ID);
|
||||||
|
|
||||||
|
@ -34,6 +34,8 @@
|
|||||||
(define alpha "Alpha <alpha@invalid.example.net>")
|
(define alpha "Alpha <alpha@invalid.example.net>")
|
||||||
(define bravo "Bravo <bravo@invalid.example.net>")
|
(define bravo "Bravo <bravo@invalid.example.net>")
|
||||||
(define charlie "Charlie <charlie@invalid.example.net>")
|
(define charlie "Charlie <charlie@invalid.example.net>")
|
||||||
|
(define delta "Delta <delta@invalid.example.net>")
|
||||||
|
(define deltahash "359DC5EFF98B14A58AAA615C638E8BD0CEDA537B")
|
||||||
|
|
||||||
(define (key-data key)
|
(define (key-data key)
|
||||||
(filter (lambda (x) (or (string=? (car x) "pub")
|
(filter (lambda (x) (or (string=? (car x) "pub")
|
||||||
@ -87,6 +89,10 @@
|
|||||||
(info "Checking that we can revoke a user ID...")
|
(info "Checking that we can revoke a user ID...")
|
||||||
(call-check `(,@GPG --quick-revoke-uid ,(exact bravo) ,alpha))
|
(call-check `(,@GPG --quick-revoke-uid ,(exact bravo) ,alpha))
|
||||||
|
|
||||||
|
(info "Checking that we can revoke a user ID by its hash...")
|
||||||
|
(call-check `(,@GPG --quick-add-uid ,(exact bravo) ,delta))
|
||||||
|
(call-check `(,@GPG --quick-revoke-uid ,(exact bravo) ,deltahash))
|
||||||
|
|
||||||
(info "Checking that we get an error revoking a non-existent user ID.")
|
(info "Checking that we get an error revoking a non-existent user ID.")
|
||||||
(catch '()
|
(catch '()
|
||||||
(call-check `(,@GPG --quick-revoke-uid ,(exact bravo) ,charlie))
|
(call-check `(,@GPG --quick-revoke-uid ,(exact bravo) ,charlie))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user