mirror of
git://git.gnupg.org/gnupg.git
synced 2024-06-03 22:48:03 +02:00
agent: Add command DELETE_KEY.
* agent/command.c (cmd_delete_key): New. * agent/findkey.c (modify_description): Add '%C' feature. (remove_key_file): New. (agent_delete_key): New. * agent/command-ssh.c (search_control_file): Make arg R_DISABLE optional. * configure.ac: Require libgpg-error 1.13.
This commit is contained in:
parent
3132bd90dc
commit
e3a4ff89a0
|
@ -334,6 +334,8 @@ int agent_key_available (const unsigned char *grip);
|
||||||
gpg_error_t agent_key_info_from_file (ctrl_t ctrl, const unsigned char *grip,
|
gpg_error_t agent_key_info_from_file (ctrl_t ctrl, const unsigned char *grip,
|
||||||
int *r_keytype,
|
int *r_keytype,
|
||||||
unsigned char **r_shadow_info);
|
unsigned char **r_shadow_info);
|
||||||
|
gpg_error_t agent_delete_key (ctrl_t ctrl, const char *desc_text,
|
||||||
|
const unsigned char *grip);
|
||||||
|
|
||||||
/*-- call-pinentry.c --*/
|
/*-- call-pinentry.c --*/
|
||||||
void initialize_module_call_pinentry (void);
|
void initialize_module_call_pinentry (void);
|
||||||
|
|
|
@ -1031,7 +1031,8 @@ search_control_file (ssh_control_file_t cf, const char *hexgrip,
|
||||||
|
|
||||||
assert (strlen (hexgrip) == 40 );
|
assert (strlen (hexgrip) == 40 );
|
||||||
|
|
||||||
*r_disabled = 0;
|
if (r_disabled)
|
||||||
|
*r_disabled = 0;
|
||||||
if (r_ttl)
|
if (r_ttl)
|
||||||
*r_ttl = 0;
|
*r_ttl = 0;
|
||||||
if (r_confirm)
|
if (r_confirm)
|
||||||
|
@ -1047,7 +1048,8 @@ search_control_file (ssh_control_file_t cf, const char *hexgrip,
|
||||||
}
|
}
|
||||||
if (!err)
|
if (!err)
|
||||||
{
|
{
|
||||||
*r_disabled = cf->item.disabled;
|
if (r_disabled)
|
||||||
|
*r_disabled = cf->item.disabled;
|
||||||
if (r_ttl)
|
if (r_ttl)
|
||||||
*r_ttl = cf->item.ttl;
|
*r_ttl = cf->item.ttl;
|
||||||
if (r_confirm)
|
if (r_confirm)
|
||||||
|
|
|
@ -695,7 +695,7 @@ static const char hlp_setkeydesc[] =
|
||||||
"blanks unless they are percent or '+' escaped.\n"
|
"blanks unless they are percent or '+' escaped.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"The description is only valid for the next PKSIGN, PKDECRYPT,\n"
|
"The description is only valid for the next PKSIGN, PKDECRYPT,\n"
|
||||||
"IMPORT_KEY or EXPORT_KEY operation.";
|
"IMPORT_KEY, EXPORT_KEY, or DELETE_KEY operation.";
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
cmd_setkeydesc (assuan_context_t ctx, char *line)
|
cmd_setkeydesc (assuan_context_t ctx, char *line)
|
||||||
{
|
{
|
||||||
|
@ -2244,6 +2244,39 @@ cmd_export_key (assuan_context_t ctx, char *line)
|
||||||
|
|
||||||
return leave_cmd (ctx, err);
|
return leave_cmd (ctx, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static const char hlp_delete_key[] =
|
||||||
|
"DELETE_KEY <hexstring_with_keygrip>\n"
|
||||||
|
"\n"
|
||||||
|
"Delete a secret key from the key store.\n"
|
||||||
|
"As safeguard the agent asks the user for confirmation.\n";
|
||||||
|
static gpg_error_t
|
||||||
|
cmd_delete_key (assuan_context_t ctx, char *line)
|
||||||
|
{
|
||||||
|
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||||
|
gpg_error_t err;
|
||||||
|
unsigned char grip[20];
|
||||||
|
|
||||||
|
line = skip_options (line);
|
||||||
|
|
||||||
|
err = parse_keygrip (ctx, line, grip);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
err = agent_delete_key (ctrl, ctrl->server_local->keydesc, grip);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
leave:
|
||||||
|
xfree (ctrl->server_local->keydesc);
|
||||||
|
ctrl->server_local->keydesc = NULL;
|
||||||
|
|
||||||
|
return leave_cmd (ctx, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static const char hlp_keytocard[] =
|
static const char hlp_keytocard[] =
|
||||||
"KEYTOCARD [--force] <hexstring_with_keygrip> <serialno> <id> <timestamp>\n"
|
"KEYTOCARD [--force] <hexstring_with_keygrip> <serialno> <id> <timestamp>\n"
|
||||||
|
@ -2926,6 +2959,7 @@ register_commands (assuan_context_t ctx)
|
||||||
{ "KEYWRAP_KEY", cmd_keywrap_key, hlp_keywrap_key },
|
{ "KEYWRAP_KEY", cmd_keywrap_key, hlp_keywrap_key },
|
||||||
{ "IMPORT_KEY", cmd_import_key, hlp_import_key },
|
{ "IMPORT_KEY", cmd_import_key, hlp_import_key },
|
||||||
{ "EXPORT_KEY", cmd_export_key, hlp_export_key },
|
{ "EXPORT_KEY", cmd_export_key, hlp_export_key },
|
||||||
|
{ "DELETE_KEY", cmd_delete_key, hlp_delete_key },
|
||||||
{ "GETVAL", cmd_getval, hlp_getval },
|
{ "GETVAL", cmd_getval, hlp_getval },
|
||||||
{ "PUTVAL", cmd_putval, hlp_putval },
|
{ "PUTVAL", cmd_putval, hlp_putval },
|
||||||
{ "UPDATESTARTUPTTY", cmd_updatestartuptty, hlp_updatestartuptty },
|
{ "UPDATESTARTUPTTY", cmd_updatestartuptty, hlp_updatestartuptty },
|
||||||
|
|
143
agent/findkey.c
143
agent/findkey.c
|
@ -1,6 +1,7 @@
|
||||||
/* findkey.c - Locate the secret key
|
/* findkey.c - Locate the secret key
|
||||||
* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007,
|
* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007,
|
||||||
* 2010, 2011 Free Software Foundation, Inc.
|
* 2010, 2011 Free Software Foundation, Inc.
|
||||||
|
* Copyright (C) 2014 Werner Koch
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
|
@ -189,6 +190,7 @@ try_unprotect_cb (struct pin_entry_info_s *pi)
|
||||||
|
|
||||||
%% - Replaced by a single %
|
%% - Replaced by a single %
|
||||||
%c - Replaced by the content of COMMENT.
|
%c - Replaced by the content of COMMENT.
|
||||||
|
%C - Same as %c but put into parentheses.
|
||||||
%F - Replaced by an ssh style fingerprint computed from KEY.
|
%F - Replaced by an ssh style fingerprint computed from KEY.
|
||||||
|
|
||||||
The functions returns 0 on success or an error code. On success a
|
The functions returns 0 on success or an error code. On success a
|
||||||
|
@ -240,6 +242,20 @@ modify_description (const char *in, const char *comment, const gcry_sexp_t key,
|
||||||
out_len += comment_length;
|
out_len += comment_length;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'C': /* Comment. */
|
||||||
|
if (!comment_length)
|
||||||
|
;
|
||||||
|
else if (out)
|
||||||
|
{
|
||||||
|
*out++ = '(';
|
||||||
|
memcpy (out, comment, comment_length);
|
||||||
|
out += comment_length;
|
||||||
|
*out++ = ')';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
out_len += comment_length + 2;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'F': /* SSH style fingerprint. */
|
case 'F': /* SSH style fingerprint. */
|
||||||
if (!ssh_fpr && key)
|
if (!ssh_fpr && key)
|
||||||
ssh_get_fingerprint_string (key, &ssh_fpr);
|
ssh_get_fingerprint_string (key, &ssh_fpr);
|
||||||
|
@ -536,6 +552,24 @@ read_key_file (const unsigned char *grip, gcry_sexp_t *result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Remove the key identified by GRIP from the private key directory. */
|
||||||
|
static gpg_error_t
|
||||||
|
remove_key_file (const unsigned char *grip)
|
||||||
|
{
|
||||||
|
gpg_error_t err = 0;
|
||||||
|
char *fname;
|
||||||
|
char hexgrip[40+4+1];
|
||||||
|
|
||||||
|
bin2hex (grip, 20, hexgrip);
|
||||||
|
strcpy (hexgrip+40, ".key");
|
||||||
|
fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL);
|
||||||
|
if (gnupg_remove (fname))
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
xfree (fname);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Return the secret key as an S-Exp in RESULT after locating it using
|
/* Return the secret key as an S-Exp in RESULT after locating it using
|
||||||
the GRIP. If the operation shall be diverted to a token, an
|
the GRIP. If the operation shall be diverted to a token, an
|
||||||
allocated S-expression with the shadow_info part from the file is
|
allocated S-expression with the shadow_info part from the file is
|
||||||
|
@ -1145,3 +1179,112 @@ agent_key_info_from_file (ctrl_t ctrl, const unsigned char *grip,
|
||||||
xfree (buf);
|
xfree (buf);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Delete the key with GRIP from the disk after having asked for
|
||||||
|
confirmation using DESC_TEXT. Common error codes are:
|
||||||
|
GPG_ERR_NO_SECKEY
|
||||||
|
GPG_ERR_KEY_ON_CARD
|
||||||
|
GPG_ERR_NOT_CONFIRMED
|
||||||
|
*/
|
||||||
|
gpg_error_t
|
||||||
|
agent_delete_key (ctrl_t ctrl, const char *desc_text,
|
||||||
|
const unsigned char *grip)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
gcry_sexp_t s_skey = NULL;
|
||||||
|
unsigned char *buf = NULL;
|
||||||
|
size_t len;
|
||||||
|
char *desc_text_final = NULL;
|
||||||
|
char *comment = NULL;
|
||||||
|
ssh_control_file_t cf = NULL;
|
||||||
|
char hexgrip[40+4+1];
|
||||||
|
char *default_desc = NULL;
|
||||||
|
|
||||||
|
err = read_key_file (grip, &s_skey);
|
||||||
|
if (gpg_err_code (err) == GPG_ERR_ENOENT)
|
||||||
|
err = gpg_error (GPG_ERR_NO_SECKEY);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
err = make_canon_sexp (s_skey, &buf, &len);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
switch (agent_private_key_type (buf))
|
||||||
|
{
|
||||||
|
case PRIVATE_KEY_CLEAR:
|
||||||
|
case PRIVATE_KEY_PROTECTED:
|
||||||
|
{
|
||||||
|
bin2hex (grip, 20, hexgrip);
|
||||||
|
if (!desc_text)
|
||||||
|
{
|
||||||
|
default_desc = xtryasprintf
|
||||||
|
("Do you really want to delete the key identified by keygrip%%0A"
|
||||||
|
" %s%%0A %%C%%0A?", hexgrip);
|
||||||
|
desc_text = default_desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Note, that we will take the comment as a C string for
|
||||||
|
display purposes; i.e. all stuff beyond a Nul character is
|
||||||
|
ignored. */
|
||||||
|
{
|
||||||
|
gcry_sexp_t comment_sexp;
|
||||||
|
|
||||||
|
comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
|
||||||
|
if (comment_sexp)
|
||||||
|
comment = gcry_sexp_nth_string (comment_sexp, 1);
|
||||||
|
gcry_sexp_release (comment_sexp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (desc_text)
|
||||||
|
err = modify_description (desc_text, comment? comment:"", s_skey,
|
||||||
|
&desc_text_final);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
err = agent_get_confirmation (ctrl, desc_text_final,
|
||||||
|
_("Delete key"), _("No"), 0);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
cf = ssh_open_control_file ();
|
||||||
|
if (cf)
|
||||||
|
{
|
||||||
|
if (!ssh_search_control_file (cf, hexgrip, NULL, NULL, NULL))
|
||||||
|
{
|
||||||
|
err = agent_get_confirmation
|
||||||
|
(ctrl,
|
||||||
|
_("Warning: This key is also listed for use with SSH!\n"
|
||||||
|
"Deleting the key will may remove your ability to"
|
||||||
|
"access remote machines."),
|
||||||
|
_("Delete key"), _("No"), 0);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = remove_key_file (grip);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRIVATE_KEY_SHADOWED:
|
||||||
|
err = gpg_error (GPG_ERR_KEY_ON_CARD);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
log_error ("invalid private key format\n");
|
||||||
|
err = gpg_error (GPG_ERR_BAD_SECKEY);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
leave:
|
||||||
|
ssh_close_control_file (cf);
|
||||||
|
gcry_free (comment);
|
||||||
|
xfree (desc_text_final);
|
||||||
|
xfree (default_desc);
|
||||||
|
xfree (buf);
|
||||||
|
gcry_sexp_release (s_skey);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ m4_define([mym4_full_version],[mym4_version[]mym4_betastring])
|
||||||
|
|
||||||
AC_INIT([gnupg],[mym4_full_version], [http://bugs.gnupg.org])
|
AC_INIT([gnupg],[mym4_full_version], [http://bugs.gnupg.org])
|
||||||
|
|
||||||
NEED_GPG_ERROR_VERSION=1.11
|
NEED_GPG_ERROR_VERSION=1.13
|
||||||
|
|
||||||
NEED_LIBGCRYPT_API=1
|
NEED_LIBGCRYPT_API=1
|
||||||
NEED_LIBGCRYPT_VERSION=1.6.0
|
NEED_LIBGCRYPT_VERSION=1.6.0
|
||||||
|
|
Loading…
Reference in New Issue
Block a user