gnupg/g10/delkey.c

296 lines
8.5 KiB
C
Raw Normal View History

/* delkey.c - delete keys
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004,
* 2005, 2006 Free Software Foundation, Inc.
* Copyright (C) 2014 Werner Koch
*
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
2007-07-04 21:49:40 +02:00
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GnuPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include "gpg.h"
#include "options.h"
#include "packet.h"
#include "../common/status.h"
#include "../common/iobuf.h"
#include "keydb.h"
#include "../common/util.h"
#include "main.h"
#include "trustdb.h"
#include "filter.h"
#include "../common/ttyio.h"
#include "../common/i18n.h"
#include "call-agent.h"
/****************
* Delete a public or secret key from a keyring.
* r_sec_avail will be set if a secret key is available and the public
* key can't be deleted for that reason.
*/
static gpg_error_t
do_delete_key (ctrl_t ctrl, const char *username, int secret, int force,
int *r_sec_avail)
{
gpg_error_t err;
kbnode_t keyblock = NULL;
kbnode_t node, kbctx;
KEYDB_HANDLE hd;
PKT_public_key *pk = NULL;
u32 keyid[2];
int okay=0;
int yes;
KEYDB_SEARCH_DESC desc;
int exactmatch;
*r_sec_avail = 0;
hd = keydb_new ();
gpg: Take care of keydb_new returning NULL. * g10/keydb.c (keydb_new): Print an error message if needed. Also use xtrycalloc because we return an error anyway. * g10/delkey.c (do_delete_key): Handle error retruned by keydb_new. * g10/export.c (do_export_stream): Ditto. * g10/getkey.c (get_pubkey): Ditto. (get_pubkey_fast): Ditto. (get_pubkeyblock): Ditto. (get_seckey): Ditto. (key_byname): Ditto. (get_pubkey_byfprint): Ditto. (get_pubkey_byfprint_fast): Ditto. (parse_def_secret_key): Ditto. (have_secret_key_with_kid): Ditto. * g10/import.c (import_one): Ditto. (import_revoke_cert): Ditto. * g10/keyedit.c (keyedit_quick_adduid): Ditto. * g10/keygen.c (quick_generate_keypair): Ditto. (do_generate_keypair): Ditto. * g10/trustdb.c (validate_keys): Ditto. * g10/keyserver.c (keyidlist): Ditto. * g10/revoke.c (gen_desig_revoke): Ditto. (gen_revoke): Ditto. * g10/gpg.c (check_user_ids): Ditto. (main): Do not print an error message for keydb_new error. * g10/keylist.c (list_all): Use actual error code returned by keydb_new. * g10/t-keydb-get-keyblock.c (do_test): Abort on keydb_new error. * g10/t-keydb.c (do_test): Ditto. * g10/keyring.c (keyring_new): Actually return an error so that the existing keydb_new error checking makes sense for a keyring resource. (keyring_rebuild_cache): Take care of keyring_new returning an error. -- Commit 04a6b903 changed keydb_new to return an error. However the error was not checked at most places which we fix with this patch. To make things easier keydb_new prints an error message itself. Signed-off-by: Werner Koch <wk@gnupg.org>
2015-12-03 12:18:32 +01:00
if (!hd)
return gpg_error_from_syserror ();
/* Search the userid. */
err = classify_user_id (username, &desc, 1);
exactmatch = (desc.mode == KEYDB_SEARCH_MODE_FPR
|| desc.mode == KEYDB_SEARCH_MODE_FPR16
kbx: Add support for 32 byte fingerprints. * common/userids.c (classify_user_id): Support 32 byte fingerprints. * kbx/keybox-search-desc.h (KEYDB_SEARCH_MODE_FPR32): New. (struct keydb_search_desc): Add field fprlen. * kbx/keybox-defs.h (struct _keybox_openpgp_key_info): Add field version and increase size of fpr to 32. * kbx/keybox-blob.c: Define new version 2 for PGP and X509 blobs. (struct keyboxblob_key): Add field fprlen and increase size of fpr. (pgp_create_key_part_single): Allow larger fingerprints. (create_blob_header): Implement blob version 2 and add arg want_fpr32. (_keybox_create_openpgp_blob): Detect the need for blob version 2. * kbx/keybox-search.c (blob_get_first_keyid): Support 32 byte fingerprints. (blob_cmp_fpr): Ditto. (blob_cmp_fpr_part): Ditto. (has_fingerprint): Add arg fprlen and pass on. (keybox_search): Support KEYDB_SEARCH_MODE_FPR32 and adjust for changed has_fingerprint. * kbx/keybox-openpgp.c (parse_key): Support version 5 keys. * kbx/keybox-dump.c (_keybox_dump_blob): Support blob version 2. * g10/delkey.c (do_delete_key): Support KEYDB_SEARCH_MODE_FPR32. * g10/export.c (exact_subkey_match_p): Ditto. * g10/gpg.c (main): Ditto. * g10/getkey.c (get_pubkey_byfprint): Adjust for changed KEYDB_SEARCH_MODE_FPR. * g10/keydb.c (keydb_search_desc_dump): Support KEYDB_SEARCH_MODE_FPR32 and adjust for changed KEYDB_SEARCH_MODE_FPR. (keydb_search): Add new arg fprlen and change all callers. * g10/keyedit.c (find_by_primary_fpr): Ditto. * g10/keyid.c (keystr_from_desc): Ditto. * g10/keyring.c (keyring_search): Ditto. * g10/keyserver.c (print_keyrec): Ditto. (parse_keyrec): Ditto. (keyserver_export): Ditto. (keyserver_retrieval_screener): Ditto. (keyserver_import): Ditto. (keyserver_import_fprint): Ditto. (keyidlist): Ditto. (keyserver_get_chunk): Ditto. * g10/keydb.c (keydb_search): Add new arg fprlen and change all callers. * sm/keydb.c (keydb_search_fpr): Adjust for changed KEYDB_SEARCH_MODE_FPR. -- This prepares the support for OpenPGP v5 keys. The new version 2 blob format is needed for the longer fingerprints and we also use this opportunity to prepare for storing the keygrip in the blob for faster lookup by keygrip. Right now this is not yet functional. Signed-off-by: Werner Koch <wk@gnupg.org>
2019-03-14 08:54:59 +01:00
|| desc.mode == KEYDB_SEARCH_MODE_FPR20
|| desc.mode == KEYDB_SEARCH_MODE_FPR32);
if (!err)
err = keydb_search (hd, &desc, 1, NULL);
if (err)
{
log_error (_("key \"%s\" not found: %s\n"), username, gpg_strerror (err));
write_status_text (STATUS_DELETE_PROBLEM, "1");
goto leave;
}
/* Read the keyblock. */
err = keydb_get_keyblock (hd, &keyblock);
if (err)
{
log_error (_("error reading keyblock: %s\n"), gpg_strerror (err) );
goto leave;
}
/* Get the keyid from the keyblock. */
node = find_kbnode( keyblock, PKT_PUBLIC_KEY );
if (!node)
{
log_error ("Oops; key not found anymore!\n");
err = gpg_error (GPG_ERR_GENERAL);
goto leave;
}
pk = node->pkt->pkt.public_key;
keyid_from_pk (pk, keyid);
if (!secret && !force)
{
if (have_secret_key_with_kid (keyid))
{
*r_sec_avail = 1;
err = gpg_error (GPG_ERR_EOF);
goto leave;
}
else
err = 0;
}
if (secret && !have_secret_key_with_kid (keyid))
{
err = gpg_error (GPG_ERR_NOT_FOUND);
log_error (_("key \"%s\" not found\n"), username);
write_status_text (STATUS_DELETE_PROBLEM, "1");
goto leave;
}
if (opt.batch && exactmatch)
okay++;
else if (opt.batch && secret)
{
log_error(_("can't do this in batch mode\n"));
log_info (_("(unless you specify the key by fingerprint)\n"));
}
else if (opt.batch && opt.answer_yes)
okay++;
else if (opt.batch)
{
log_error(_("can't do this in batch mode without \"--yes\"\n"));
log_info (_("(unless you specify the key by fingerprint)\n"));
}
else
{
if (secret)
print_seckey_info (ctrl, pk);
else
print_pubkey_info (ctrl, NULL, pk );
tty_printf( "\n" );
yes = cpr_get_answer_is_yes
(secret? "delete_key.secret.okay": "delete_key.okay",
_("Delete this key from the keyring? (y/N) "));
if (!cpr_enabled() && secret && yes)
{
/* I think it is not required to check a passphrase; if the
* user is so stupid as to let others access his secret
* keyring (and has no backup) - it is up him to read some
* very basic texts about security. */
yes = cpr_get_answer_is_yes
("delete_key.secret.okay",
_("This is a secret key! - really delete? (y/N) "));
}
if (yes)
okay++;
}
if (okay)
{
if (secret)
{
char *prompt;
gpg_error_t firsterr = 0;
char *hexgrip;
setup_main_keyids (keyblock);
for (kbctx=NULL; (node = walk_kbnode (keyblock, &kbctx, 0)); )
{
if (!(node->pkt->pkttype == PKT_PUBLIC_KEY
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY))
continue;
if (agent_probe_secret_key (NULL, node->pkt->pkt.public_key))
continue; /* No secret key for that public (sub)key. */
prompt = gpg_format_keydesc (ctrl,
node->pkt->pkt.public_key,
FORMAT_KEYDESC_DELKEY, 1);
err = hexkeygrip_from_pk (node->pkt->pkt.public_key, &hexgrip);
/* NB: We require --yes to advise the agent not to
* request a confirmation. The rationale for this extra
* pre-caution is that since 2.1 the secret key may also
* be used for other protocols and thus deleting it from
* the gpg would also delete the key for other tools. */
if (!err)
err = agent_delete_key (NULL, hexgrip, prompt,
opt.answer_yes);
xfree (prompt);
xfree (hexgrip);
if (err)
{
if (gpg_err_code (err) == GPG_ERR_KEY_ON_CARD)
write_status_text (STATUS_DELETE_PROBLEM, "1");
log_error (_("deleting secret %s failed: %s\n"),
(node->pkt->pkttype == PKT_PUBLIC_KEY
? _("key"):_("subkey")),
gpg_strerror (err));
if (!firsterr)
firsterr = err;
if (gpg_err_code (err) == GPG_ERR_CANCELED
|| gpg_err_code (err) == GPG_ERR_FULLY_CANCELED)
{
write_status_error ("delete_key.secret", err);
break;
}
}
}
err = firsterr;
if (firsterr)
goto leave;
}
else
{
err = keydb_delete_keyblock (hd);
if (err)
{
log_error (_("deleting keyblock failed: %s\n"),
gpg_strerror (err));
goto leave;
}
}
/* Note that the ownertrust being cleared will trigger a
revalidation_mark(). This makes sense - only deleting keys
that have ownertrust set should trigger this. */
if (!secret && pk && clear_ownertrusts (ctrl, pk))
{
if (opt.verbose)
log_info (_("ownertrust information cleared\n"));
}
}
leave:
keydb_release (hd);
release_kbnode (keyblock);
return err;
}
/****************
* Delete a public or secret key from a keyring.
*/
gpg_error_t
delete_keys (ctrl_t ctrl, strlist_t names, int secret, int allow_both)
{
gpg_error_t err;
int avail;
int force = (!allow_both && !secret && opt.expert);
/* Force allows us to delete a public key even if a secret key
exists. */
for ( ;names ; names=names->next )
{
err = do_delete_key (ctrl, names->d, secret, force, &avail);
if (err && avail)
{
if (allow_both)
{
err = do_delete_key (ctrl, names->d, 1, 0, &avail);
if (!err)
err = do_delete_key (ctrl, names->d, 0, 0, &avail);
}
else
{
log_error (_("there is a secret key for public key \"%s\"!\n"),
names->d);
log_info(_("use option \"--delete-secret-keys\" to delete"
" it first.\n"));
write_status_text (STATUS_DELETE_PROBLEM, "2");
return err;
}
}
if (err)
{
log_error ("%s: delete key failed: %s\n",
names->d, gpg_strerror (err));
return err;
}
}
return 0;
}