diff options
author | Werner Koch <wk@gnupg.org> | 2021-04-23 08:47:06 +0200 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2021-04-23 08:50:39 +0200 |
commit | 50293ec2ebf2a997dbad9a47166d694efcc0709a (patch) | |
tree | 46e5a428c73cea0a3b44bd9dab06a74fb69bb458 /g10/skclist.c | |
parent | agent: Require verbose level 2 for handler started/terminated notices. (diff) | |
download | gnupg2-50293ec2ebf2a997dbad9a47166d694efcc0709a.tar.xz gnupg2-50293ec2ebf2a997dbad9a47166d694efcc0709a.zip |
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>
Diffstat (limited to 'g10/skclist.c')
-rw-r--r-- | g10/skclist.c | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/g10/skclist.c b/g10/skclist.c index c9f7d126a..f9647cc1d 100644 --- a/g10/skclist.c +++ b/g10/skclist.c @@ -31,6 +31,7 @@ #include "keydb.h" #include "../common/util.h" #include "../common/i18n.h" +#include "keyserver-internal.h" #include "call-agent.h" @@ -322,11 +323,13 @@ enum_secret_keys (ctrl_t ctrl, void **context, PKT_public_key *sk) { gpg_error_t err = 0; const char *name; + int cardkey; kbnode_t keyblock; struct { int eof; int state; + int cardkey_done; strlist_t sl; keypair_info_t card_keyinfo; keypair_info_t card_keyinfo_list; @@ -381,6 +384,7 @@ enum_secret_keys (ctrl_t ctrl, void **context, PKT_public_key *sk) do { name = NULL; + cardkey = 0; keyblock = NULL; switch (c->state) { @@ -431,6 +435,7 @@ enum_secret_keys (ctrl_t ctrl, void **context, PKT_public_key *sk) c->fpr2[i] = *s; c->fpr2[i] = 0; name = c->fpr2; + cardkey = 1; c->card_keyinfo = c->card_keyinfo->next; } @@ -482,11 +487,47 @@ enum_secret_keys (ctrl_t ctrl, void **context, PKT_public_key *sk) err = getkey_byname (ctrl, NULL, NULL, name, 1, &c->keyblock); if (err) { + struct agent_card_info_s cinfo = { 0 }; + /* getkey_byname might return a keyblock even in the error case - I have not checked. Thus better release it. */ release_kbnode (c->keyblock); 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 + && !agent_scd_getattr ("KEY-FPR", &cinfo) + && cinfo.fpr2len) + { + /* 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, cinfo.fpr2, cinfo.fpr2len, opt.keyserver, + KEYSERVER_IMPORT_FLAG_LDAP)) + { + char fpr_string[MAX_FINGERPRINT_LEN * 2 + 1]; + + bin2hex (cinfo.fpr2, cinfo.fpr2len, 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 c->node = c->keyblock; |