mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-21 10:09:57 +01:00
card: Improve openpgp key writing in "writecert".
* tools/card-keys.c (struct export_key_status_parm_s): New. (export_key_status_cb): New. (get_minimal_openpgp_key): New. * tools/gpg-card.c (cmd_writecert): Allow writing a keyblock directly from an existing gpg key. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
48251cf9a7
commit
4f6e0e12cb
@ -557,3 +557,96 @@ test_get_matching_keys (const char *hexgrip)
|
||||
release_keyblock (keyblock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
struct export_key_status_parm_s
|
||||
{
|
||||
const char *fpr;
|
||||
int found;
|
||||
int count;
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
export_key_status_cb (void *opaque, const char *keyword, char *args)
|
||||
{
|
||||
struct export_key_status_parm_s *parm = opaque;
|
||||
|
||||
if (!strcmp (keyword, "EXPORTED"))
|
||||
{
|
||||
parm->count++;
|
||||
if (!ascii_strcasecmp (args, parm->fpr))
|
||||
parm->found = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Get a key by fingerprint from gpg's keyring. The binary key is
|
||||
* returned as a new memory stream at R_KEY. */
|
||||
gpg_error_t
|
||||
get_minimal_openpgp_key (estream_t *r_key, const char *fingerprint)
|
||||
{
|
||||
gpg_error_t err;
|
||||
ccparray_t ccp;
|
||||
const char **argv = NULL;
|
||||
estream_t key = NULL;
|
||||
struct export_key_status_parm_s parm = { NULL };
|
||||
|
||||
*r_key = NULL;
|
||||
|
||||
key = es_fopenmem (0, "w+b");
|
||||
if (!key)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
ccparray_init (&ccp, 0);
|
||||
|
||||
ccparray_put (&ccp, "--no-options");
|
||||
if (!opt.verbose)
|
||||
ccparray_put (&ccp, "--quiet");
|
||||
else if (opt.verbose > 1)
|
||||
ccparray_put (&ccp, "--verbose");
|
||||
ccparray_put (&ccp, "--batch");
|
||||
ccparray_put (&ccp, "--status-fd=2");
|
||||
ccparray_put (&ccp, "--always-trust");
|
||||
ccparray_put (&ccp, "--no-armor");
|
||||
ccparray_put (&ccp, "--export-options=export-minimal");
|
||||
ccparray_put (&ccp, "--export");
|
||||
ccparray_put (&ccp, "--");
|
||||
ccparray_put (&ccp, fingerprint);
|
||||
|
||||
ccparray_put (&ccp, NULL);
|
||||
argv = ccparray_get (&ccp, NULL);
|
||||
if (!argv)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
parm.fpr = fingerprint;
|
||||
err = gnupg_exec_tool_stream (opt.gpg_program, argv, NULL,
|
||||
NULL, key,
|
||||
export_key_status_cb, &parm);
|
||||
if (!err && parm.count > 1)
|
||||
err = gpg_error (GPG_ERR_TOO_MANY);
|
||||
else if (!err && !parm.found)
|
||||
err = gpg_error (GPG_ERR_NOT_FOUND);
|
||||
if (err)
|
||||
{
|
||||
log_error ("export failed: %s\n", gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
es_rewind (key);
|
||||
*r_key = key;
|
||||
key = NULL;
|
||||
|
||||
leave:
|
||||
es_fclose (key);
|
||||
xfree (argv);
|
||||
return err;
|
||||
}
|
||||
|
@ -1853,15 +1853,18 @@ cmd_writecert (card_info_t info, char *argstr)
|
||||
char *certref;
|
||||
char *data = NULL;
|
||||
size_t datalen;
|
||||
estream_t key = NULL;
|
||||
|
||||
|
||||
if (!info)
|
||||
return print_help
|
||||
("WRITECERT [--clear] [--openpgp] CERTREF < FILE\n\n"
|
||||
"Write a certificate for key 3. Unless --clear is given\n"
|
||||
"the file argument is mandatory. The option --clear removes\n"
|
||||
("WRITECERT CERTREF '<' FILE\n"
|
||||
"WRITECERT --openpgp CERTREF ['<' FILE|FPR]\n"
|
||||
"WRITECERT --clear CERTREF\n\n"
|
||||
"Write a certificate for key 3. The option --clear removes\n"
|
||||
"the certificate from the card. The option --openpgp expects\n"
|
||||
"a keyblock and stores it encapsulated in a CMS container.",
|
||||
"a keyblock and stores it encapsulated in a CMS container; the\n"
|
||||
"keyblock is taken from FILE or directly from the key with FPR",
|
||||
APP_TYPE_OPENPGP, APP_TYPE_PIV, 0);
|
||||
|
||||
opt_clear = has_leading_option (argstr, "--clear");
|
||||
@ -1926,6 +1929,18 @@ cmd_writecert (card_info_t info, char *argstr)
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
else if (opt_openpgp && *argstr)
|
||||
{
|
||||
err = get_minimal_openpgp_key (&key, argstr);
|
||||
if (err)
|
||||
goto leave;
|
||||
if (es_fclose_snatch (key, (void*)&data, &datalen))
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
key = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
err = gpg_error (GPG_ERR_INV_ARG);
|
||||
@ -1965,6 +1980,7 @@ cmd_writecert (card_info_t info, char *argstr)
|
||||
err = scd_writecert (certref, data, datalen);
|
||||
|
||||
leave:
|
||||
es_fclose (key);
|
||||
xfree (data);
|
||||
xfree (certref_buffer);
|
||||
return err;
|
||||
|
@ -195,6 +195,7 @@ void flush_keyblock_cache (void);
|
||||
gpg_error_t get_matching_keys (const unsigned char *keygrip, int protocol,
|
||||
keyblock_t *r_keyblock);
|
||||
gpg_error_t test_get_matching_keys (const char *hexgrip);
|
||||
gpg_error_t get_minimal_openpgp_key (estream_t *r_key, const char *fingerprint);
|
||||
|
||||
|
||||
/*-- card-misc.c --*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user