mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
agent: Add KEYATTR command.
* agent/agent.h (agent_raw_key_from_file): Add R_KEYMETA argument. (agent_update_private_key): New. * agent/command-ssh.c (data_sign): Follow the change of the function agent_raw_key_from_file. * agent/command.c (do_one_keyinfo): Likewise. (cmd_keyattr): New. (register_commands): Add an entry of cmd_keyattr. * agent/findkey.c (agent_update_private_key): New. (agent_raw_key_from_file): Add R_KEYMETA argument. -- GnuPG-bug-id: 5988 Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
parent
fe535cf265
commit
30b54a0ebb
@ -37,6 +37,7 @@
|
||||
#include "../common/sysutils.h" /* (gnupg_fd_t) */
|
||||
#include "../common/session-env.h"
|
||||
#include "../common/shareddefs.h"
|
||||
#include "../common/name-value.h"
|
||||
|
||||
/* To convey some special hash algorithms we use algorithm numbers
|
||||
reserved for application use. */
|
||||
@ -471,7 +472,7 @@ gpg_error_t agent_key_from_file (ctrl_t ctrl,
|
||||
gcry_sexp_t *result,
|
||||
char **r_passphrase, time_t *r_timestamp);
|
||||
gpg_error_t agent_raw_key_from_file (ctrl_t ctrl, const unsigned char *grip,
|
||||
gcry_sexp_t *result);
|
||||
gcry_sexp_t *result, nvc_t *r_keymeta);
|
||||
gpg_error_t agent_public_key_from_file (ctrl_t ctrl,
|
||||
const unsigned char *grip,
|
||||
gcry_sexp_t *result);
|
||||
@ -488,6 +489,7 @@ gpg_error_t agent_key_info_from_file (ctrl_t ctrl, const unsigned char *grip,
|
||||
gpg_error_t agent_delete_key (ctrl_t ctrl, const char *desc_text,
|
||||
const unsigned char *grip,
|
||||
int force, int only_stubs);
|
||||
gpg_error_t agent_update_private_key (const unsigned char *grip, nvc_t pk);
|
||||
|
||||
/*-- call-pinentry.c --*/
|
||||
void initialize_module_call_pinentry (void);
|
||||
|
@ -2760,7 +2760,7 @@ data_sign (ctrl_t ctrl, ssh_key_type_spec_t *spec,
|
||||
char *fpr, *prompt;
|
||||
char *comment = NULL;
|
||||
|
||||
err = agent_raw_key_from_file (ctrl, ctrl->keygrip, &key);
|
||||
err = agent_raw_key_from_file (ctrl, ctrl->keygrip, &key, NULL);
|
||||
if (err)
|
||||
goto out;
|
||||
err = ssh_get_fingerprint_string (key, opt.ssh_fingerprint_digest, &fpr);
|
||||
|
@ -1200,7 +1200,84 @@ cmd_genkey (assuan_context_t ctx, char *line)
|
||||
}
|
||||
|
||||
|
||||
static const char hlp_keyattr[] =
|
||||
"KEYATTR [--delete] <hexstring_with_keygrip> <ATTRNAME> [<VALUE>]\n"
|
||||
"\n"
|
||||
"For the secret key, show the attribute of ATTRNAME. With VALUE,\n"
|
||||
"put the value to the attribute. Use --delete option to delete.";
|
||||
static gpg_error_t
|
||||
cmd_keyattr (assuan_context_t ctx, char *line)
|
||||
{
|
||||
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||
gpg_error_t err;
|
||||
const char *argv[3];
|
||||
int argc;
|
||||
unsigned char grip[20];
|
||||
int opt_delete;
|
||||
|
||||
if (ctrl->restricted)
|
||||
return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
|
||||
|
||||
opt_delete = has_option (line, "--delete");
|
||||
|
||||
line = skip_options (line);
|
||||
|
||||
argc = split_fields (line, argv, DIM (argv));
|
||||
if (argc < 2)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_MISSING_VALUE);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
err = parse_keygrip (ctx, argv[0], grip);
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
if (!err)
|
||||
{
|
||||
gcry_sexp_t s_key = NULL;
|
||||
nvc_t keymeta = NULL;
|
||||
const char *p;
|
||||
|
||||
err = agent_raw_key_from_file (ctrl, grip, &s_key, &keymeta);
|
||||
if (keymeta == NULL) /* Not extended format? */
|
||||
{
|
||||
err = gpg_error (GPG_ERR_INV_DATA);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (argc == 2)
|
||||
{
|
||||
nve_t e = nvc_lookup (keymeta, argv[1]);
|
||||
|
||||
if (opt_delete)
|
||||
{
|
||||
if (e)
|
||||
nvc_delete (keymeta, e);
|
||||
}
|
||||
else if (e)
|
||||
{
|
||||
p = nve_value (e);
|
||||
if (p)
|
||||
err = assuan_send_data (ctx, p, strlen (p));
|
||||
}
|
||||
}
|
||||
else if (argc == 3)
|
||||
{
|
||||
err = nvc_set (keymeta, argv[1], argv[2]);
|
||||
if (!err)
|
||||
err = nvc_set_private_key (keymeta, s_key);
|
||||
if (!err)
|
||||
err = agent_update_private_key (grip, keymeta);
|
||||
}
|
||||
|
||||
nvc_release (keymeta);
|
||||
gcry_sexp_release (s_key);
|
||||
}
|
||||
|
||||
leave:
|
||||
return leave_cmd (ctx, err);
|
||||
}
|
||||
|
||||
static const char hlp_readkey[] =
|
||||
"READKEY [--no-data] [--format=ssh] <hexstring_with_keygrip>\n"
|
||||
@ -1461,7 +1538,7 @@ do_one_keyinfo (ctrl_t ctrl, const unsigned char *grip, assuan_context_t ctx,
|
||||
{
|
||||
gcry_sexp_t key;
|
||||
|
||||
if (!agent_raw_key_from_file (ctrl, grip, &key))
|
||||
if (!agent_raw_key_from_file (ctrl, grip, &key, NULL))
|
||||
{
|
||||
ssh_get_fingerprint_string (key, with_ssh_fpr, &fpr);
|
||||
gcry_sexp_release (key);
|
||||
@ -4044,7 +4121,8 @@ register_commands (assuan_context_t ctx)
|
||||
{ "RELOADAGENT", cmd_reloadagent,hlp_reloadagent },
|
||||
{ "GETINFO", cmd_getinfo, hlp_getinfo },
|
||||
{ "KEYTOCARD", cmd_keytocard, hlp_keytocard },
|
||||
{ "KEYTOTPM", cmd_keytotpm, hlp_keytotpm },
|
||||
{ "KEYTOTPM", cmd_keytotpm, hlp_keytotpm },
|
||||
{ "KEYATTR", cmd_keyattr, hlp_keyattr },
|
||||
{ NULL }
|
||||
};
|
||||
int i, rc;
|
||||
|
@ -33,7 +33,6 @@
|
||||
#include "agent.h"
|
||||
#include "../common/i18n.h"
|
||||
#include "../common/ssh-utils.h"
|
||||
#include "../common/name-value.h"
|
||||
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
@ -339,6 +338,59 @@ agent_write_private_key (const unsigned char *grip,
|
||||
}
|
||||
|
||||
|
||||
gpg_error_t
|
||||
agent_update_private_key (const unsigned char *grip, nvc_t pk)
|
||||
{
|
||||
char *fname, *fname0;
|
||||
estream_t fp;
|
||||
char hexgrip[40+8+1];
|
||||
gpg_error_t err;
|
||||
|
||||
bin2hex (grip, 20, hexgrip);
|
||||
strcpy (hexgrip+40, ".key.tmp");
|
||||
|
||||
fname = make_filename (gnupg_homedir (), GNUPG_PRIVATE_KEYS_DIR,
|
||||
hexgrip, NULL);
|
||||
fname0 = xstrdup (fname);
|
||||
if (!fname0)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
xfree (fname);
|
||||
return err;
|
||||
}
|
||||
fname0[strlen (fname)-4] = 0;
|
||||
|
||||
fp = es_fopen (fname, "wbx,mode=-rw");
|
||||
if (!fp)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
|
||||
log_error ("can't create '%s': %s\n", fname, gpg_strerror (err));
|
||||
xfree (fname);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = nvc_write (pk, fp);
|
||||
if (err)
|
||||
log_error ("error writing '%s': %s\n", fname, gpg_strerror (err));
|
||||
|
||||
es_fclose (fp);
|
||||
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
/* No atomic mv on W32 systems. */
|
||||
gnupg_remove (fname0);
|
||||
#endif
|
||||
if (rename (fname, fname0))
|
||||
{
|
||||
err = gpg_error_from_errno (errno);
|
||||
log_error (_("error renaming '%s' to '%s': %s\n"),
|
||||
fname, fname0, strerror (errno));
|
||||
}
|
||||
|
||||
xfree (fname);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Callback function to try the unprotection from the passphrase query
|
||||
code. */
|
||||
static gpg_error_t
|
||||
@ -1349,7 +1401,7 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
|
||||
failure an error code is returned and NULL stored at RESULT. */
|
||||
gpg_error_t
|
||||
agent_raw_key_from_file (ctrl_t ctrl, const unsigned char *grip,
|
||||
gcry_sexp_t *result)
|
||||
gcry_sexp_t *result, nvc_t *r_keymeta)
|
||||
{
|
||||
gpg_error_t err;
|
||||
gcry_sexp_t s_skey;
|
||||
@ -1358,7 +1410,7 @@ agent_raw_key_from_file (ctrl_t ctrl, const unsigned char *grip,
|
||||
|
||||
*result = NULL;
|
||||
|
||||
err = read_key_file (grip, &s_skey, NULL);
|
||||
err = read_key_file (grip, &s_skey, r_keymeta);
|
||||
if (!err)
|
||||
*result = s_skey;
|
||||
return err;
|
||||
|
Loading…
x
Reference in New Issue
Block a user