mirror of
git://git.gnupg.org/gnupg.git
synced 2025-04-17 15:44:34 +02:00
gpg: Allow decryption w/o public key but with correct card inserted.
* agent/command.c (cmd_readkey): Add option --no-data and special handling for $SIGNKEYID and $AUTHKEYID. * g10/call-agent.c (agent_scd_getattr): Create shadow keys for KEY-FPR output. * g10/skclist.c (enum_secret_keys): Automagically get a missing public key for the current card. Signed-off-by: Werner Koch <wk@gnupg.org> Backported-from-master: 50293ec2ebf2a997dbad9a47166d694efcc0709a)
This commit is contained in:
parent
79e8ea100d
commit
e53f603728
@ -978,8 +978,8 @@ cmd_genkey (assuan_context_t ctx, char *line)
|
|||||||
|
|
||||||
|
|
||||||
static const char hlp_readkey[] =
|
static const char hlp_readkey[] =
|
||||||
"READKEY <hexstring_with_keygrip>\n"
|
"READKEY [--no-data] <hexstring_with_keygrip>\n"
|
||||||
" --card <keyid>\n"
|
" --card <keyid>\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Return the public key for the given keygrip or keyid.\n"
|
"Return the public key for the given keygrip or keyid.\n"
|
||||||
"With --card, private key file with card information will be created.";
|
"With --card, private key file with card information will be created.";
|
||||||
@ -992,18 +992,20 @@ cmd_readkey (assuan_context_t ctx, char *line)
|
|||||||
gcry_sexp_t s_pkey = NULL;
|
gcry_sexp_t s_pkey = NULL;
|
||||||
unsigned char *pkbuf = NULL;
|
unsigned char *pkbuf = NULL;
|
||||||
char *serialno = NULL;
|
char *serialno = NULL;
|
||||||
|
char *keyidbuf = NULL;
|
||||||
size_t pkbuflen;
|
size_t pkbuflen;
|
||||||
const char *opt_card;
|
int opt_card, opt_no_data;
|
||||||
|
|
||||||
if (ctrl->restricted)
|
if (ctrl->restricted)
|
||||||
return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
|
return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
|
||||||
|
|
||||||
opt_card = has_option_name (line, "--card");
|
opt_no_data = has_option (line, "--no-data");
|
||||||
|
opt_card = has_option (line, "--card");
|
||||||
line = skip_options (line);
|
line = skip_options (line);
|
||||||
|
|
||||||
if (opt_card)
|
if (opt_card)
|
||||||
{
|
{
|
||||||
const char *keyid = opt_card;
|
const char *keyid = line;
|
||||||
|
|
||||||
rc = agent_card_getattr (ctrl, "SERIALNO", &serialno);
|
rc = agent_card_getattr (ctrl, "SERIALNO", &serialno);
|
||||||
if (rc)
|
if (rc)
|
||||||
@ -1013,6 +1015,11 @@ cmd_readkey (assuan_context_t ctx, char *line)
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Hack to create the shadow key for the OpenPGP standard keys. */
|
||||||
|
if ((!strcmp (keyid, "$SIGNKEYID") || !strcmp (keyid, "$ENCRKEYID"))
|
||||||
|
&& !agent_card_getattr (ctrl, keyid, &keyidbuf))
|
||||||
|
keyid = keyidbuf;
|
||||||
|
|
||||||
rc = agent_card_readkey (ctrl, keyid, &pkbuf);
|
rc = agent_card_readkey (ctrl, keyid, &pkbuf);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto leave;
|
goto leave;
|
||||||
@ -1038,7 +1045,7 @@ cmd_readkey (assuan_context_t ctx, char *line)
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = assuan_send_data (ctx, pkbuf, pkbuflen);
|
rc = opt_no_data? 0 : assuan_send_data (ctx, pkbuf, pkbuflen);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1058,12 +1065,13 @@ cmd_readkey (assuan_context_t ctx, char *line)
|
|||||||
{
|
{
|
||||||
pkbuflen = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON,
|
pkbuflen = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON,
|
||||||
pkbuf, pkbuflen);
|
pkbuf, pkbuflen);
|
||||||
rc = assuan_send_data (ctx, pkbuf, pkbuflen);
|
rc = opt_no_data? 0 : assuan_send_data (ctx, pkbuf, pkbuflen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
|
xfree (keyidbuf);
|
||||||
xfree (serialno);
|
xfree (serialno);
|
||||||
xfree (pkbuf);
|
xfree (pkbuf);
|
||||||
gcry_sexp_release (s_pkey);
|
gcry_sexp_release (s_pkey);
|
||||||
|
@ -1097,6 +1097,16 @@ agent_scd_getattr (const char *name, struct agent_card_info_s *info)
|
|||||||
parm.ctx = agent_ctx;
|
parm.ctx = agent_ctx;
|
||||||
rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb, &parm,
|
rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb, &parm,
|
||||||
learn_status_cb, info);
|
learn_status_cb, info);
|
||||||
|
if (!rc && !strcmp (name, "KEY-FPR"))
|
||||||
|
{
|
||||||
|
/* Let the agent create the shadow keys if not yet done. */
|
||||||
|
if (info->fpr1valid)
|
||||||
|
assuan_transact (agent_ctx, "READKEY --card --no-data -- $SIGNKEYID",
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
|
if (info->fpr2valid)
|
||||||
|
assuan_transact (agent_ctx, "READKEY --card --no-data -- $ENCRKEYID",
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include "keydb.h"
|
#include "keydb.h"
|
||||||
#include "../common/util.h"
|
#include "../common/util.h"
|
||||||
#include "../common/i18n.h"
|
#include "../common/i18n.h"
|
||||||
|
#include "keyserver-internal.h"
|
||||||
#include "call-agent.h"
|
#include "call-agent.h"
|
||||||
|
|
||||||
|
|
||||||
@ -326,11 +327,14 @@ enum_secret_keys (ctrl_t ctrl, void **context, PKT_public_key *sk)
|
|||||||
{
|
{
|
||||||
gpg_error_t err = 0;
|
gpg_error_t err = 0;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
int cardkey; /* We got an encryption fingerprint from the card */
|
||||||
|
/* in c->info.fpr2. */
|
||||||
kbnode_t keyblock;
|
kbnode_t keyblock;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
int eof;
|
int eof;
|
||||||
int state;
|
int state;
|
||||||
|
int cardkey_done;
|
||||||
strlist_t sl;
|
strlist_t sl;
|
||||||
strlist_t card_list;
|
strlist_t card_list;
|
||||||
char *serialno;
|
char *serialno;
|
||||||
@ -389,6 +393,7 @@ enum_secret_keys (ctrl_t ctrl, void **context, PKT_public_key *sk)
|
|||||||
char *serialno;
|
char *serialno;
|
||||||
|
|
||||||
name = NULL;
|
name = NULL;
|
||||||
|
cardkey = 0;
|
||||||
keyblock = NULL;
|
keyblock = NULL;
|
||||||
switch (c->state)
|
switch (c->state)
|
||||||
{
|
{
|
||||||
@ -444,6 +449,7 @@ enum_secret_keys (ctrl_t ctrl, void **context, PKT_public_key *sk)
|
|||||||
bin2hex (c->info.fpr2, sizeof c->info.fpr2,
|
bin2hex (c->info.fpr2, sizeof c->info.fpr2,
|
||||||
c->fpr2 + 2);
|
c->fpr2 + 2);
|
||||||
name = c->fpr2;
|
name = c->fpr2;
|
||||||
|
cardkey = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (gpg_err_code (err) == GPG_ERR_INV_NAME)
|
else if (gpg_err_code (err) == GPG_ERR_INV_NAME)
|
||||||
@ -551,6 +557,39 @@ enum_secret_keys (ctrl_t ctrl, void **context, PKT_public_key *sk)
|
|||||||
it. */
|
it. */
|
||||||
release_kbnode (c->keyblock);
|
release_kbnode (c->keyblock);
|
||||||
c->keyblock = NULL;
|
c->keyblock = NULL;
|
||||||
|
/* If this was a card key we might not yet have the
|
||||||
|
* public key for it. Thus check whether the card
|
||||||
|
* can return the fingerprint of the encryption key
|
||||||
|
* and we can then find the public key via LDAP. */
|
||||||
|
if (cardkey && !c->cardkey_done
|
||||||
|
&& gpg_err_code (err) == GPG_ERR_NO_SECKEY)
|
||||||
|
{
|
||||||
|
/* Note that this code does not handle the case
|
||||||
|
* for two readers having both openpgp
|
||||||
|
* encryption keys. Only one will be tried. */
|
||||||
|
c->cardkey_done = 1;
|
||||||
|
if (opt.debug)
|
||||||
|
log_debug ("using LDAP to find public key"
|
||||||
|
" for current card\n");
|
||||||
|
if (!keyserver_import_fprint
|
||||||
|
(ctrl, c->info.fpr2, sizeof c->info.fpr2,
|
||||||
|
opt.keyserver, KEYSERVER_IMPORT_FLAG_LDAP))
|
||||||
|
{
|
||||||
|
char fpr_string[MAX_FINGERPRINT_LEN * 2 + 1];
|
||||||
|
|
||||||
|
bin2hex (c->info.fpr2, sizeof c->info.fpr2,
|
||||||
|
fpr_string);
|
||||||
|
err = getkey_byname (ctrl, NULL, NULL, fpr_string, 1,
|
||||||
|
&c->keyblock);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
release_kbnode (c->keyblock);
|
||||||
|
c->keyblock = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
c->node = c->keyblock;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
c->node = c->keyblock;
|
c->node = c->keyblock;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user