gpg: Do not allow the user to revoke the last valid UID.

* g10/keyedit.c (keyedit_quick_revuid): Merge self signatures, then
make sure that we do not revoke the last valid UID.
(menu_revuid): Make sure that we do not revoke the last valid UID.
* tests/openpgp/quick-key-manipulation.scm: Demonstrate that
'--quick-revoke-uid' can not be used to revoke the last valid UID.

GnuPG-bug-id: 2960
Signed-off-by: Justus Winter <justus@g10code.com>
This commit is contained in:
Justus Winter 2017-03-02 14:14:55 +01:00
parent 80fb1a8a05
commit 591b6a9d87
No known key found for this signature in database
GPG Key ID: DD1A52F9DA8C9020
2 changed files with 45 additions and 1 deletions

View File

@ -2966,6 +2966,7 @@ keyedit_quick_revuid (ctrl_t ctrl, const char *username, const char *uidtorev)
kbnode_t node; kbnode_t node;
int modified = 0; int modified = 0;
size_t revlen; size_t revlen;
size_t valid_uids;
#ifdef HAVE_W32_SYSTEM #ifdef HAVE_W32_SYSTEM
/* See keyedit_menu for why we need this. */ /* See keyedit_menu for why we need this. */
@ -3019,7 +3020,16 @@ keyedit_quick_revuid (ctrl_t ctrl, const char *username, const char *uidtorev)
} }
fix_keyblock (&keyblock); fix_keyblock (&keyblock);
setup_main_keyids (keyblock); merge_keys_and_selfsig (keyblock);
/* Too make sure that we do not revoke the last valid UID, we first
count how many valid UIDs there are. */
valid_uids = 0;
for (node = keyblock; node; node = node->next)
valid_uids +=
node->pkt->pkttype == PKT_USER_ID
&& ! node->pkt->pkt.user_id->is_revoked
&& ! node->pkt->pkt.user_id->is_expired;
revlen = strlen (uidtorev); revlen = strlen (uidtorev);
/* find the right UID */ /* find the right UID */
@ -3031,6 +3041,15 @@ keyedit_quick_revuid (ctrl_t ctrl, const char *username, const char *uidtorev)
{ {
struct revocation_reason_info *reason; struct revocation_reason_info *reason;
/* Make sure that we do not revoke the last valid UID. */
if (valid_uids == 1
&& ! node->pkt->pkt.user_id->is_revoked
&& ! node->pkt->pkt.user_id->is_expired)
{
log_error (_("Cannot revoke the last valid user ID.\n"));
goto leave;
}
reason = get_default_uid_revocation_reason (); reason = get_default_uid_revocation_reason ();
err = core_revuid (ctrl, keyblock, node, reason, &modified); err = core_revuid (ctrl, keyblock, node, reason, &modified);
release_revocation_reason_info (reason); release_revocation_reason_info (reason);
@ -6429,6 +6448,7 @@ menu_revuid (ctrl_t ctrl, kbnode_t pub_keyblock)
int changed = 0; int changed = 0;
int rc; int rc;
struct revocation_reason_info *reason = NULL; struct revocation_reason_info *reason = NULL;
size_t valid_uids;
/* Note that this is correct as per the RFCs, but nevertheless /* Note that this is correct as per the RFCs, but nevertheless
somewhat meaningless in the real world. 1991 did define the 0x30 somewhat meaningless in the real world. 1991 did define the 0x30
@ -6445,11 +6465,30 @@ menu_revuid (ctrl_t ctrl, kbnode_t pub_keyblock)
goto leave; goto leave;
} }
/* Too make sure that we do not revoke the last valid UID, we first
count how many valid UIDs there are. */
valid_uids = 0;
for (node = pub_keyblock; node; node = node->next)
valid_uids +=
node->pkt->pkttype == PKT_USER_ID
&& ! node->pkt->pkt.user_id->is_revoked
&& ! node->pkt->pkt.user_id->is_expired;
reloop: /* (better this way because we are modifying the keyring) */ reloop: /* (better this way because we are modifying the keyring) */
for (node = pub_keyblock; node; node = node->next) for (node = pub_keyblock; node; node = node->next)
if (node->pkt->pkttype == PKT_USER_ID && (node->flag & NODFLG_SELUID)) if (node->pkt->pkttype == PKT_USER_ID && (node->flag & NODFLG_SELUID))
{ {
int modified = 0; int modified = 0;
/* Make sure that we do not revoke the last valid UID. */
if (valid_uids == 1
&& ! node->pkt->pkt.user_id->is_revoked
&& ! node->pkt->pkt.user_id->is_expired)
{
log_error (_("Cannot revoke the last valid user ID.\n"));
goto leave;
}
rc = core_revuid (ctrl, pub_keyblock, node, reason, &modified); rc = core_revuid (ctrl, pub_keyblock, node, reason, &modified);
if (rc) if (rc)
goto leave; goto leave;

View File

@ -81,6 +81,11 @@
(call-check `(,@GPG --quick-revoke-uid ,(exact bravo) ,charlie)) (call-check `(,@GPG --quick-revoke-uid ,(exact bravo) ,charlie))
(error "Expected an error, but get none.")) (error "Expected an error, but get none."))
(info "Checking that we get an error revoking the last valid user ID.")
(catch '()
(call-check `(,@GPG --quick-revoke-uid ,(exact bravo) ,bravo))
(error "Expected an error, but get none."))
(assert (= 1 (count-uids-of-secret-key bravo))) (assert (= 1 (count-uids-of-secret-key bravo)))
(info "Checking that we can change the expiration time.") (info "Checking that we can change the expiration time.")