aboutsummaryrefslogtreecommitdiffstats
path: root/g10
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2010-10-13 15:57:08 +0000
committerWerner Koch <[email protected]>2010-10-13 15:57:08 +0000
commit54591341a417ca769b2219a9b2f7683f11a74718 (patch)
treed4cd49932dec93aa9e20e1933ad16ba897965c46 /g10
parentDescribe %v and %V. (diff)
downloadgnupg-54591341a417ca769b2219a9b2f7683f11a74718.tar.gz
gnupg-54591341a417ca769b2219a9b2f7683f11a74718.zip
More agent support for gpg.
Diffstat (limited to 'g10')
-rw-r--r--g10/ChangeLog30
-rw-r--r--g10/call-agent.c6
-rw-r--r--g10/card-util.c1
-rw-r--r--g10/getkey.c156
-rw-r--r--g10/gpg.c10
-rw-r--r--g10/gpgv.c18
-rw-r--r--g10/import.c16
-rw-r--r--g10/keydb.h5
-rw-r--r--g10/keyedit.c2
-rw-r--r--g10/keygen.c45
-rw-r--r--g10/keylist.c213
-rw-r--r--g10/misc.c7
-rw-r--r--g10/options.h2
-rw-r--r--g10/passphrase.c14
-rw-r--r--g10/pubkey-enc.c35
15 files changed, 308 insertions, 252 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog
index a4873fe53..43ba53604 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,3 +1,33 @@
+2010-10-13 Werner Koch <[email protected]>
+
+ * call-agent.c (start_agent): Send option agent-awareness.
+ (status_sc_op_failure): Take care of GPG_ERR_FULLY_CANCELED.
+ * passphrase.c (passphrase_get): Ditto.
+ * import.c (transfer_secret_keys): Ditto.
+ * card-util.c (write_sc_op_status): Ditto.
+
+ * getkey.c (enum_secret_keys): Rewrite.
+
+ * pubkey-enc.c (get_session_key): Skip keys without an encryption
+ capability. Handle GPG_ERR_FULLY_CANCELED.
+ * gpg.c: Add option --try-secret-key.
+ * options.h (struct opt): Add field secret_keys_to_try.
+
+ * passphrase.c (next_to_last_passphrase): Remove.
+
+2010-10-12 Werner Koch <[email protected]>
+
+ * keygen.c (generate_subkeypair): Check availibility of secret parts.
+
+ * keylist.c (print_card_serialno): Change to take a hexified serialno.
+ (list_keyblock_print): Print serialno and stub key indicators.
+ (list_keyblock_colon): Ditto.
+
+ * getkey.c (have_any_secret_key): Remove. Replace all calls by
+ agent_probe_any_secret_key.
+ * gpgv.c (agent_probe_any_secret_key): New.
+ (agent_get_keyinfo): New.
+
2010-10-08 Werner Koch <[email protected]>
* gpg.c: Add option --with-keygrip.
diff --git a/g10/call-agent.c b/g10/call-agent.c
index bdf4c9589..afbd9d6db 100644
--- a/g10/call-agent.c
+++ b/g10/call-agent.c
@@ -99,6 +99,7 @@ status_sc_op_failure (int rc)
case 0:
break;
case GPG_ERR_CANCELED:
+ case GPG_ERR_FULLY_CANCELED:
write_status_text (STATUS_SC_OP_FAILURE, "1");
break;
case GPG_ERR_BAD_PIN:
@@ -142,6 +143,11 @@ start_agent (ctrl_t ctrl, int for_card)
agents. */
assuan_transact (agent_ctx, "OPTION allow-pinentry-notify",
NULL, NULL, NULL, NULL, NULL, NULL);
+ /* Tell the agent about what version we are aware. This is
+ here used to indirectly enable GPG_ERR_FULLY_CANCELED. */
+ assuan_transact (agent_ctx, "OPTION agent-awareness=2.1.0",
+ NULL, NULL, NULL, NULL, NULL, NULL);
+
}
}
diff --git a/g10/card-util.c b/g10/card-util.c
index 1abcde894..12b229341 100644
--- a/g10/card-util.c
+++ b/g10/card-util.c
@@ -58,6 +58,7 @@ write_sc_op_status (gpg_error_t err)
break;
#if GNUPG_MAJOR_VERSION != 1
case GPG_ERR_CANCELED:
+ case GPG_ERR_FULLY_CANCELED:
write_status_text (STATUS_SC_OP_FAILURE, "1");
break;
case GPG_ERR_BAD_PIN:
diff --git a/g10/getkey.c b/g10/getkey.c
index 8d983487b..ad7e71cf7 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -568,8 +568,9 @@ leave:
* first pubkey certificate which has the given name in a user_id. If
* PK has the pubkey algo set, the function will only return a pubkey
* with that algo. If NAMELIST is NULL, the first key is returned.
- * The caller should provide storage for the PK. If RET_KB is not
- * NULL the function will return the keyblock there. */
+ * The caller should provide storage for the PK or pass NULL if it is
+ * not needed. If RET_KB is not NULL the function stores the entire
+ * keyblock at that address. */
static int
key_byname (GETKEY_CTX *retctx, strlist_t namelist,
PKT_public_key *pk,
@@ -1146,12 +1147,13 @@ getkey_bynames (getkey_ctx_t *retctx, PKT_public_key *pk,
}
-/* Get a key by name and store it into PK. If RETCTX is not NULL
- * return the search context which needs to be released by the caller
- * using getkey_end. If NAME is NULL use the default key (see below).
- * On success and if RET_KEYBLOCK is not NULL the found keyblock is
- * stored at this address. WANT_SECRET passed as true requires that a
- * secret key is available for the selected key.
+/* Get a key by name and store it into PK if that is not NULL. If
+ * RETCTX is not NULL return the search context which needs to be
+ * released by the caller using getkey_end. If NAME is NULL use the
+ * default key (see below). On success and if RET_KEYBLOCK is not
+ * NULL the found keyblock is stored at this address. WANT_SECRET
+ * passed as true requires that a secret key is available for the
+ * selected key.
*
* If WANT_SECRET is true and NAME is NULL and a default key has been
* defined that defined key is used. In all other cases the first
@@ -2459,7 +2461,7 @@ lookup (getkey_ctx_t ctx, kbnode_t *ret_keyblock, int want_secret)
goto skip;
}
- if (want_secret && !have_any_secret_key (NULL, ctx->keyblock))
+ if (want_secret && agent_probe_any_secret_key (NULL, ctx->keyblock))
goto skip; /* No secret key available. */
/* Warning: node flag bits 0 and 1 should be preserved by
@@ -2504,57 +2506,42 @@ found:
-/****************
- * FIXME: Replace by the generic function
- * It does not work as it is right now - it is used at
- * one place: to get the key for an anonymous recipient.
- *
- * set with_subkeys true to include subkeys
- * set with_spm true to include secret-parts-missing keys
- *
- * Enumerate all primary secret keys. Caller must use these procedure:
+/*
+ * Enumerate certain secret keys. Caller must use these procedure:
* 1) create a void pointer and initialize it to NULL
* 2) pass this void pointer by reference to this function
* and provide space for the secret key (pass a buffer for sk)
- * 3) call this function as long as it does not return -1
- * to indicate EOF.
+ * 3) call this function as long as it does not return an error.
+ * The error code GPG_ERR_EOF indicates the end of the listing.
* 4) Always call this function a last time with SK set to NULL,
* so that can free it's context.
*/
-int
-enum_secret_keys (void **context, PKT_public_key * sk,
- int with_subkeys, int with_spm)
+gpg_error_t
+enum_secret_keys (void **context, PKT_public_key *sk)
{
- log_debug ("FIXME: Anonymous recipient does not yet work\n");
- return -1;
-#if 0
-
- int rc = 0;
+ gpg_error_t err = 0;
+ const char *name;
struct
{
int eof;
- int first;
- KEYDB_HANDLE hd;
- KBNODE keyblock;
- KBNODE node;
+ int state;
+ strlist_t sl;
+ kbnode_t keyblock;
+ kbnode_t node;
} *c = *context;
-
if (!c)
{
/* Make a new context. */
- c = xmalloc_clear (sizeof *c);
+ c = xtrycalloc (1, sizeof *c);
+ if (!c)
+ return gpg_error_from_syserror ();
*context = c;
- c->hd = keydb_new (1); /*FIXME*/
- c->first = 1;
- c->keyblock = NULL;
- c->node = NULL;
}
if (!sk)
{
/* Free the context. */
- keydb_release (c->hd);
release_kbnode (c->keyblock);
xfree (c);
*context = NULL;
@@ -2562,48 +2549,79 @@ enum_secret_keys (void **context, PKT_public_key * sk,
}
if (c->eof)
- return -1;
+ return gpg_error (GPG_ERR_EOF);
- do
+ for (;;)
{
- /* Get the next secret key from the current keyblock. */
+ /* Loop until we have a keyblock. */
+ while (!c->keyblock)
+ {
+ /* Loop over the list of secret keys. */
+ do
+ {
+ name = NULL;
+ switch (c->state)
+ {
+ case 0: /* First try to use the --default-key. */
+ if (opt.def_secret_key && *opt.def_secret_key)
+ name = opt.def_secret_key;
+ c->state = 1;
+ break;
+
+ case 1: /* Init list of keys to try. */
+ c->sl = opt.secret_keys_to_try;
+ c->state++;
+ break;
+
+ case 2: /* Get next item from list. */
+ if (c->sl)
+ {
+ name = c->sl->d;
+ c->sl = c->sl->next;
+ }
+ else
+ c->state++;
+ break;
+
+ default: /* No more names to check - stop. */
+ c->eof = 1;
+ return gpg_error (GPG_ERR_EOF);
+ }
+ }
+ while (!name || !*name);
+
+ err = getkey_byname (NULL, NULL, name, 1, &c->keyblock);
+ if (err)
+ {
+ /* 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;
+ }
+ else
+ c->node = c->keyblock;
+ }
+
+ /* Get the next key from the current keyblock. */
for (; c->node; c->node = c->node->next)
{
- if ((c->node->pkt->pkttype == PKT_SECRET_KEY
- || (with_subkeys
- && c->node->pkt->pkttype == PKT_SECRET_SUBKEY))
- && !(c->node->pkt->pkt.secret_key->protect.s2k.mode == 1001
- && !with_spm))
+ if (c->node->pkt->pkttype == PKT_PUBLIC_KEY
+ || c->node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
{
- copy_secret_key (sk, c->node->pkt->pkt.secret_key);
+ copy_public_key (sk, c->node->pkt->pkt.public_key);
c->node = c->node->next;
return 0; /* Found. */
}
- }
- release_kbnode (c->keyblock);
- c->keyblock = c->node = NULL;
-
- rc = c->first ? keydb_search_first (c->hd) : keydb_search_next (c->hd);
- c->first = 0;
- if (rc)
- {
- keydb_release (c->hd);
- c->hd = NULL;
- c->eof = 1;
- return -1; /* eof */
- }
+ }
- rc = keydb_get_keyblock (c->hd, &c->keyblock);
- c->node = c->keyblock;
+ /* Dispose the keyblock and continue. */
+ release_kbnode (c->keyblock);
+ c->keyblock = NULL;
}
- while (!rc);
-
- return rc; /* Error. */
-#endif
}
-
-
+
/*********************************************
*********** User ID printing helpers *******
*********************************************/
diff --git a/g10/gpg.c b/g10/gpg.c
index c25c3ba18..5ee03a63b 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -177,6 +177,7 @@ enum cmd_and_opt_values
oDefRecipient,
oDefRecipientSelf,
oNoDefRecipient,
+ oTrySecretKey,
oOptions,
oDebug,
oDebugLevel,
@@ -460,6 +461,8 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_s_s (oLocalUser, "local-user",
N_("|USER-ID|use USER-ID to sign or decrypt")),
+ ARGPARSE_s_s (oTrySecretKey, "try-secret-key", "@"),
+
ARGPARSE_s_i (oCompress, NULL,
N_("|N|set compress level to N (0 disables)")),
ARGPARSE_s_i (oCompressLevel, "compress-level", "@"),
@@ -1622,6 +1625,7 @@ gpgconf_list (const char *configfile)
es_printf ("reader-port:%lu:\n", GC_OPT_FLAG_NONE);
es_printf ("default-key:%lu:\n", GC_OPT_FLAG_NONE);
es_printf ("encrypt-to:%lu:\n", GC_OPT_FLAG_NONE);
+ es_printf ("try-secret-key:%lu:\n", GC_OPT_FLAG_NONE);
es_printf ("auto-key-locate:%lu:\n", GC_OPT_FLAG_NONE);
es_printf ("log-file:%lu:\n", GC_OPT_FLAG_NONE);
es_printf ("debug-level:%lu:\"none:\n", GC_OPT_FLAG_DEFAULT);
@@ -2526,6 +2530,12 @@ main (int argc, char **argv)
sl->flags = 2;
any_explicit_recipient = 1;
break;
+
+ case oTrySecretKey:
+ add_to_strlist2 (&opt.secret_keys_to_try,
+ pargs.r.ret_str, utf8_strings);
+ break;
+
case oTextmodeShort: opt.textmode = 2; break;
case oTextmode: opt.textmode=1; break;
case oNoTextmode: opt.textmode=0; break;
diff --git a/g10/gpgv.c b/g10/gpgv.c
index b342d2481..569601e89 100644
--- a/g10/gpgv.c
+++ b/g10/gpgv.c
@@ -546,3 +546,21 @@ agent_probe_secret_key (ctrl_t ctrl, PKT_public_key *pk)
(void)pk;
return gpg_error (GPG_ERR_NO_SECKEY);
}
+
+gpg_error_t
+agent_probe_any_secret_key (ctrl_t ctrl, kbnode_t keyblock)
+{
+ (void)ctrl;
+ (void)keyblock;
+ return gpg_error (GPG_ERR_NO_SECKEY);
+}
+
+gpg_error_t
+agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip, char **r_serialno)
+{
+ (void)ctrl;
+ (void)hexkeygrip;
+ *r_serialno = NULL;
+ return gpg_error (GPG_ERR_NO_SECKEY);
+}
+
diff --git a/g10/import.c b/g10/import.c
index b3969770f..31160c33e 100644
--- a/g10/import.c
+++ b/g10/import.c
@@ -362,7 +362,7 @@ import_print_stats (void *hd)
* Read the next keyblock from stream A.
* PENDING_PKT should be initialzed to NULL
* and not chnaged form the caller.
- * Retunr: 0 = okay, -1 no more blocks or another errorcode.
+ * Return: 0 = okay, -1 no more blocks or another errorcode.
*/
static int
read_block( IOBUF a, PACKET **pending_pkt, KBNODE *ret_root )
@@ -1142,8 +1142,15 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock)
stats->count++;
stats->secret_read++;
- /* For now we ignore the stub keys becuase we don't have real
- support for them in gpg-agent. */
+ /* We ignore stub keys. The way we handle them in other parts
+ of the code is by asking the agent whether any secret key is
+ available for a given keyblock and then concluding that we
+ have a secret key; all secret (sub)keys of the keyblock the
+ agent does not know of are then stub keys. This works also
+ for card stub keys. The learn command or the card-status
+ command may be used to check with the agent whether a card
+ has been inserted and a stub key is in turn generated by the
+ agent. */
if (ski->s2k.mode == 1001 || ski->s2k.mode == 1002)
continue;
@@ -1288,7 +1295,8 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock)
write_status (STATUS_RSA_OR_IDEA);
idea_cipher_warn (0);
}
- if (gpg_err_code (err) == GPG_ERR_CANCELED)
+ if (gpg_err_code (err) == GPG_ERR_CANCELED
+ || gpg_err_code (err) == GPG_ERR_FULLY_CANCELED)
break; /* Don't try the other subkeys. */
}
}
diff --git a/g10/keydb.h b/g10/keydb.h
index eab59e0a5..9ec2496c5 100644
--- a/g10/keydb.h
+++ b/g10/keydb.h
@@ -241,11 +241,8 @@ gpg_error_t getkey_next (getkey_ctx_t ctx, PKT_public_key *pk,
kbnode_t *ret_keyblock);
void getkey_end (getkey_ctx_t ctx);
-int have_any_secret_key (ctrl_t ctrl, kbnode_t keyblock);
+gpg_error_t enum_secret_keys (void **context, PKT_public_key *pk);
-
-//int enum_secret_keys( void **context, PKT_secret_key *sk,
-// int with_subkeys, int with_spm );
void merge_keys_and_selfsig( KBNODE keyblock );
char*get_user_id_string( u32 *keyid );
char*get_user_id_string_native( u32 *keyid );
diff --git a/g10/keyedit.c b/g10/keyedit.c
index d1cacaf39..5b4c60a0d 100644
--- a/g10/keyedit.c
+++ b/g10/keyedit.c
@@ -1638,7 +1638,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
/* See whether we have a matching secret key. */
if (seckey_check)
{
- have_seckey = have_any_secret_key (ctrl, keyblock);
+ have_seckey = !agent_probe_any_secret_key (ctrl, keyblock);
if (have_seckey && !quiet)
tty_printf (_("Secret key is available.\n"));
}
diff --git a/g10/keygen.c b/g10/keygen.c
index 00ad26ecb..16a7f0b8d 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -3441,6 +3441,8 @@ generate_subkeypair (KBNODE keyblock)
u32 expire;
unsigned int nbits;
u32 cur_time;
+ char *hexgrip = NULL;
+ char *serialno = NULL;
/* Break out the primary key. */
node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
@@ -3476,37 +3478,16 @@ generate_subkeypair (KBNODE keyblock)
goto leave;
}
-#warning ask gpg-agent on the availibility of the secret key
- /* if (pri_sk->is_protected && pri_sk->protect.s2k.mode == 1001) */
- /* { */
- /* tty_printf (_("Secret parts of primary key are not available.\n")); */
- /* err = G10ERR_NO_SECKEY; */
- /* goto leave; */
- /* } */
-
-
- /* /\* Unprotect to get the passphrase. *\/ */
- /* switch (is_secret_key_protected (pri_sk) ) */
- /* { */
- /* case -1: */
- /* err = G10ERR_PUBKEY_ALGO; */
- /* break; */
- /* case 0: */
- /* tty_printf (_("This key is not protected.\n")); */
- /* break; */
- /* case -2: */
- /* tty_printf (_("Secret parts of primary key are stored on-card.\n")); */
- /* ask_pass = 1; */
- /* break; */
- /* default: */
- /* tty_printf (_("Key is protected.\n")); */
- /* err = check_secret_key ( pri_sk, 0 ); */
- /* if (!err) */
- /* passphrase = get_last_passphrase(); */
- /* break; */
- /* } */
- /* if (err) */
- /* goto leave; */
+ err = hexkeygrip_from_pk (pri_psk, &hexgrip);
+ if (err)
+ goto leave;
+ if (agent_get_keyinfo (NULL, hexgrip, &serialno))
+ {
+ tty_printf (_("Secret parts of primary key are not available.\n"));
+ goto leave;
+ }
+ if (serialno)
+ tty_printf (_("Secret parts of primary key are stored on-card.\n"));
algo = ask_algo (1, NULL, &use);
assert (algo);
@@ -3536,6 +3517,8 @@ generate_subkeypair (KBNODE keyblock)
write_status_text (STATUS_KEY_CREATED, "S");
leave:
+ xfree (hexgrip);
+ xfree (serialno);
if (err)
log_error (_("Key generation failed: %s\n"), g10_errstr (err) );
return err;
diff --git a/g10/keylist.c b/g10/keylist.c
index d144afc39..e8440f77b 100644
--- a/g10/keylist.c
+++ b/g10/keylist.c
@@ -40,11 +40,12 @@
#include "main.h"
#include "i18n.h"
#include "status.h"
+#include "call-agent.h"
static void list_all (int);
static void list_one (strlist_t names, int secret);
static void locate_one (ctrl_t ctrl, strlist_t names);
-static void print_card_serialno (PKT_public_key *sk);
+static void print_card_serialno (const char *serialno);
struct sig_stats
{
@@ -175,6 +176,7 @@ print_pubkey_info (estream_t fp, PKT_public_key * pk)
/* Print basic information of a secret key including the card serial
number information. */
+#ifdef ENABLE_CARD_SUPPORT
void
print_card_key_info (estream_t fp, kbnode_t keyblock)
{
@@ -224,7 +226,7 @@ print_card_key_info (estream_t fp, kbnode_t keyblock)
/* } */
/* } */
}
-
+#endif /*ENABLE_CARD_SUPPORT*/
/* Flags = 0x01 hashed 0x02 critical. */
@@ -444,7 +446,7 @@ list_all (int secret)
log_error ("keydb_get_keyblock failed: %s\n", g10_errstr (rc));
goto leave;
}
- if (secret && !have_any_secret_key (NULL, keyblock))
+ if (secret && agent_probe_any_secret_key (NULL, keyblock))
; /* Secret key listing requested but this isn't one. */
else
{
@@ -757,13 +759,15 @@ dump_attribs (const PKT_user_id *uid, PKT_public_key *pk)
static void
list_keyblock_print (KBNODE keyblock, int secret, int fpr, void *opaque)
{
- int rc = 0;
+ int rc;
KBNODE kbctx;
KBNODE node;
PKT_public_key *pk;
struct sig_stats *stats = opaque;
int skip_sigs = 0;
int s2k_char;
+ char *hexgrip = NULL;
+ char *serialno = NULL;
/* Get the keyid from the keyblock. */
node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
@@ -775,10 +779,23 @@ list_keyblock_print (KBNODE keyblock, int secret, int fpr, void *opaque)
}
pk = node->pkt->pkt.public_key;
-
- /* Fixme: Get s2k mode from the agent. */
- s2k_char = (/*(sk->protect.s2k.mode == 1001)? '#' :
- (sk->protect.s2k.mode == 1002)? '>' : */' ');
+
+ if (secret || opt.with_keygrip)
+ {
+ rc = hexkeygrip_from_pk (pk, &hexgrip);
+ if (rc)
+ log_error ("error computing a keygrip: %s\n", gpg_strerror (rc));
+ }
+
+ if (secret)
+ {
+ if (!agent_get_keyinfo (NULL, hexgrip, &serialno))
+ s2k_char = serialno? '>':' ';
+ else
+ s2k_char = '#'; /* Key not found. */
+ }
+ else
+ s2k_char = ' ';
check_trustdb_stale ();
@@ -822,19 +839,11 @@ list_keyblock_print (KBNODE keyblock, int secret, int fpr, void *opaque)
if (fpr)
print_fingerprint (pk, 0);
- if (opt.with_keygrip)
- {
- char *p;
+ if (opt.with_keygrip && hexgrip)
+ es_fprintf (es_stdout, " Keygrip = %s\n", hexgrip);
- if (!hexkeygrip_from_pk (pk, &p))
- {
- es_fprintf (es_stdout, " Keygrip = %s\n", p);
- xfree (p);
- }
- }
-
- /* FIXME: Change this function to take a PK and ask the agent: */
- /* if (secret) print_card_serialno (sk); */
+ if (serialno)
+ print_card_serialno (serialno);
if (opt.with_key_data)
print_key_data (pk);
@@ -895,10 +904,25 @@ list_keyblock_print (KBNODE keyblock, int secret, int fpr, void *opaque)
else
skip_sigs = 0;
- /* Fixme: Get s2k mode from the agent. */
- s2k_char = (/*(sk->protect.s2k.mode == 1001)? '#' :
- (sk->protect.s2k.mode == 1002)? '>' : */' ');
-
+ xfree (serialno); serialno = NULL;
+ xfree (hexgrip); hexgrip = NULL;
+ if (secret || opt.with_keygrip)
+ {
+ rc = hexkeygrip_from_pk (pk2, &hexgrip);
+ if (rc)
+ log_error ("error computing a keygrip: %s\n",
+ gpg_strerror (rc));
+ }
+ if (secret)
+ {
+ if (!agent_get_keyinfo (NULL, hexgrip, &serialno))
+ s2k_char = serialno? '>':' ';
+ else
+ s2k_char = '#'; /* Key not found. */
+ }
+ else
+ s2k_char = ' ';
+
es_fprintf (es_stdout, "%s%c %4u%c/%s %s",
secret? "ssb":"sub",
s2k_char,
@@ -926,20 +950,11 @@ list_keyblock_print (KBNODE keyblock, int secret, int fpr, void *opaque)
if (fpr > 1)
{
print_fingerprint (pk2, 0);
- /* FIXME: (see above) */
- /* if (secret) */
- /* print_card_serialno (sk2); */
- }
- if (opt.with_keygrip)
- {
- char *p;
-
- if (!hexkeygrip_from_pk (pk2, &p))
- {
- es_fprintf (es_stdout, " Keygrip = %s\n", p);
- xfree (p);
- }
+ if (serialno)
+ print_card_serialno (serialno);
}
+ if (opt.with_keygrip && hexgrip)
+ es_fprintf (es_stdout, " Keygrip = %s\n", hexgrip);
if (opt.with_key_data)
print_key_data (pk2);
}
@@ -1050,6 +1065,8 @@ list_keyblock_print (KBNODE keyblock, int secret, int fpr, void *opaque)
}
}
es_putc ('\n', es_stdout);
+ xfree (serialno);
+ xfree (hexgrip);
}
void
@@ -1079,7 +1096,7 @@ print_revokers (PKT_public_key * pk)
static void
list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
{
- int rc = 0;
+ int rc;
KBNODE kbctx;
KBNODE node;
PKT_public_key *pk;
@@ -1088,6 +1105,9 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
int ulti_hack = 0;
int i;
char *p;
+ char *hexgrip = NULL;
+ char *serialno = NULL;
+ int stubkey;
/* Get the keyid from the keyblock. */
node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
@@ -1099,6 +1119,15 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
}
pk = node->pkt->pkt.public_key;
+ if (secret || opt.with_keygrip || opt.with_key_data)
+ {
+ rc = hexkeygrip_from_pk (pk, &hexgrip);
+ if (rc)
+ log_error ("error computing a keygrip: %s\n", gpg_strerror (rc));
+ }
+ stubkey = 0;
+ if (secret && agent_get_keyinfo (NULL, hexgrip, &serialno))
+ stubkey = 1; /* Key not found. */
keyid_from_pk (pk, keyid);
es_fputs (secret? "sec:":"pub:", es_stdout);
@@ -1135,16 +1164,10 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
{
es_putc (':', es_stdout); /* End of field 13. */
es_putc (':', es_stdout); /* End of field 14. */
- if (/*FIXME sk->protect.s2k.mode*/1 == 1001)
- es_putc ('#', es_stdout); /* Key is just a stub. */
- else if (/*FIXME sk->protect.s2k.mode*/1 == 1002)
- {
- /* Key is stored on an external token (card) or handled by
- the gpg-agent. Print the serial number of that token
- here. */
- /* FIXME: for (i = 0; i < sk->protect.ivlen; i++) */
- /* es_fprintf (es_stdout, "%02X", sk->protect.iv[i]); */
- }
+ if (stubkey)
+ es_putc ('#', es_stdout);
+ else if (serialno)
+ es_fputs(serialno, es_stdout);
es_putc (':', es_stdout); /* End of field 15. */
}
es_putc ('\n', es_stdout);
@@ -1154,11 +1177,8 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
print_fingerprint (pk, 0);
if (opt.with_key_data || opt.with_keygrip)
{
- if (!hexkeygrip_from_pk (pk, &p))
- {
- es_fprintf (es_stdout, "grp:::::::::%s:\n", p);
- xfree (p);
- }
+ if (hexgrip)
+ es_fprintf (es_stdout, "grp:::::::::%s:\n", hexgrip);
if (opt.with_key_data)
print_key_data (pk);
}
@@ -1213,7 +1233,21 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
else if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
{
u32 keyid2[2];
- PKT_public_key *pk2 = node->pkt->pkt.public_key;
+ PKT_public_key *pk2;
+
+ pk2 = node->pkt->pkt.public_key;
+ xfree (hexgrip); hexgrip = NULL;
+ xfree (serialno); serialno = NULL;
+ if (secret || opt.with_keygrip || opt.with_key_data)
+ {
+ rc = hexkeygrip_from_pk (pk2, &hexgrip);
+ if (rc)
+ log_error ("error computing a keygrip: %s\n",
+ gpg_strerror (rc));
+ }
+ stubkey = 0;
+ if (secret && agent_get_keyinfo (NULL, hexgrip, &serialno))
+ stubkey = 1; /* Key not found. */
keyid_from_pk (pk2, keyid2);
es_fputs (secret? "ssb:":"sub:", es_stdout);
@@ -1243,16 +1277,10 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
{
es_putc (':', es_stdout); /* End of field 13. */
es_putc (':', es_stdout); /* End of field 14. */
- if (/*FIXME:sk2->protect.s2k.mode*/1 == 1001)
- es_putc ('#', es_stdout); /* Key is just a stub. */
- else if (/*FIXME: sk2->protect.s2k.mode*/1 == 1002)
- {
- /* Key is stored on an external token (card) or
- handled by the gpg-agent. Print the serial
- number of that token here. */
- /* FIXME: for (i = 0; i < sk2->protect.ivlen; i++)
- es_fprintf (es_stdout, "%02X", sk2->protect.iv[i]); */
- }
+ if (stubkey)
+ es_putc ('#', es_stdout);
+ else if (serialno)
+ es_fputs (serialno, es_stdout);
es_putc (':', es_stdout); /* End of field 15. */
}
es_putc ('\n', es_stdout);
@@ -1260,11 +1288,8 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
print_fingerprint (pk2, 0);
if (opt.with_key_data || opt.with_keygrip)
{
- if (!hexkeygrip_from_pk (pk2, &p))
- {
- es_fprintf (es_stdout, "grp:::::::::%s:\n", p);
- xfree (p);
- }
+ if (hexgrip)
+ es_fprintf (es_stdout, "grp:::::::::%s:\n", hexgrip);
if (opt.with_key_data)
print_key_data (pk2);
}
@@ -1385,6 +1410,9 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
/* fixme: check or list other sigs here */
}
}
+
+ xfree (hexgrip);
+ xfree (serialno);
}
/*
@@ -1550,38 +1578,25 @@ print_fingerprint (PKT_public_key *pk, int mode)
/* Print the serial number of an OpenPGP card if available. */
static void
-print_card_serialno (PKT_public_key *pk)
+print_card_serialno (const char *serialno)
{
- log_debug ("Fixme: Needs to be adjusted to gpg-agent\n");
- /* int i; */
+ if (!serialno)
+ return;
+ if (opt.with_colons)
+ return; /* Handled elsewhere. */
- /* if (!sk) */
- /* return; */
- /* if (!sk->is_protected || sk->protect.s2k.mode != 1002) */
- /* return; /\* Not a card. *\/ */
- /* if (opt.with_colons) */
- /* return; /\* Handled elsewhere. *\/ */
-
- /* es_fputs (_(" Card serial no. ="), es_stdout); */
- /* es_putc (' ', es_stdout); */
- /* if (sk->protect.ivlen == 16 */
- /* && !memcmp (sk->protect.iv, "\xD2\x76\x00\x01\x24\x01", 6)) */
- /* { */
- /* /\* This is an OpenPGP card. Just print the relevant part. *\/ */
- /* for (i = 8; i < 14; i++) */
- /* { */
- /* if (i == 10) */
- /* es_putc (' ', es_stdout); */
- /* es_fprintf (es_stdout, "%02X", sk->protect.iv[i]); */
- /* } */
- /* } */
- /* else */
- /* { */
- /* /\* Something is wrong: Print all. *\/ */
- /* for (i = 0; i < sk->protect.ivlen; i++) */
- /* es_fprintf (es_stdout, "%02X", sk->protect.iv[i]); */
- /* } */
- /* es_putc ('\n', es_stdout); */
+ es_fputs (_(" Card serial no. ="), es_stdout);
+ es_putc (' ', es_stdout);
+ if (strlen (serialno) == 32 && !strncmp (serialno, "D27600012401", 12))
+ {
+ /* This is an OpenPGP card. Print the relevant part. */
+ /* Example: D2760001240101010001000003470000 */
+ /* xxxxyyyyyyyy */
+ es_fprintf (es_stdout, "%.*s %.*s", 4, serialno+16, 8, serialno+20);
+ }
+ else
+ es_fputs (serialno, es_stdout);
+ es_putc ('\n', es_stdout);
}
diff --git a/g10/misc.c b/g10/misc.c
index 91d1c310a..e3bebdd20 100644
--- a/g10/misc.c
+++ b/g10/misc.c
@@ -555,11 +555,10 @@ get_signature_count (PKT_public_key *pk)
/* if(agent_scd_getattr("SIG-COUNTER",&info)==0) */
/* return info.sig_counter; */
/* } */
-#endif
-
- /* How to do this without a card? */
-
+#else
+ (void)pk;
return 0;
+#endif
}
/* Expand %-strings. Returns a string which must be xfreed. Returns
diff --git a/g10/options.h b/g10/options.h
index 499428e92..b71271da6 100644
--- a/g10/options.h
+++ b/g10/options.h
@@ -79,6 +79,8 @@ struct
const char *def_secret_key;
char *def_recipient;
int def_recipient_self;
+ strlist_t secret_keys_to_try;
+
int def_cert_level;
int min_cert_level;
int ask_cert_level;
diff --git a/g10/passphrase.c b/g10/passphrase.c
index 60560123f..b28477fd5 100644
--- a/g10/passphrase.c
+++ b/g10/passphrase.c
@@ -211,17 +211,6 @@ get_last_passphrase()
return p;
}
-/* As if we had used the passphrase - make it the last_pw. */
-void
-next_to_last_passphrase(void)
-{
- if (next_pw)
- {
- last_pw=next_pw;
- next_pw=NULL;
- }
-}
-
/* Here's an interesting question: since this passphrase was passed in
on the command line, is there really any point in using secure
memory for it? I'm going with 'yes', since it doesn't hurt, and
@@ -407,7 +396,8 @@ passphrase_get ( u32 *keyid, int mode, const char *cacheid, int repeat,
if (!rc)
;
- else if ( gpg_err_code (rc) == GPG_ERR_CANCELED )
+ else if (gpg_err_code (rc) == GPG_ERR_CANCELED
+ || gpg_err_code (rc) == GPG_ERR_FULLY_CANCELED)
{
log_info (_("cancelled by user\n") );
if (canceled)
diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c
index 74bdc7655..770e4fb67 100644
--- a/g10/pubkey-enc.c
+++ b/g10/pubkey-enc.c
@@ -94,14 +94,13 @@ get_session_key (PKT_pubkey_enc * k, DEK * dek)
{
void *enum_context = NULL;
u32 keyid[2];
- char *p;
for (;;)
{
if (sk)
free_public_key (sk);
sk = xmalloc_clear (sizeof *sk);
- rc = -1; /* FIXME:enum_secret_keys (&enum_context, sk, 1, 0);*/
+ rc = enum_secret_keys (&enum_context, sk);
if (rc)
{
rc = G10ERR_NO_SECKEY;
@@ -109,42 +108,22 @@ get_session_key (PKT_pubkey_enc * k, DEK * dek)
}
if (sk->pubkey_algo != k->pubkey_algo)
continue;
+ if (!(sk->pubkey_usage & PUBKEY_USAGE_ENC))
+ continue;
keyid_from_pk (sk, keyid);
log_info (_("anonymous recipient; trying secret key %s ...\n"),
keystr (keyid));
- if (!opt.try_all_secrets && !is_status_enabled ())
- {
- p = get_last_passphrase ();
- set_next_passphrase (p);
- xfree (p);
- }
-
- /* rc = check_secret_key( sk, opt.try_all_secrets?1:-1 ); /\* ask */
- /* only */
- /* once *\/ */
- /* if( !rc ) */
- {
- rc = get_it (k, dek, sk, keyid);
- /* Successfully checked the secret key (either it was a
- card, had no passphrase, or had the right passphrase)
- but couldn't decrypt the session key, so thus that key
- is not the anonymous recipient. Move the next
- passphrase into last for the next round. We only do
- this if the secret key was successfully checked as in
- the normal case, check_secret_key handles this for us
- via passphrase_to_dek. */
- if (rc)
- next_to_last_passphrase ();
- }
-
+ rc = get_it (k, dek, sk, keyid);
if (!rc)
{
log_info (_("okay, we are the anonymous recipient.\n"));
break;
}
+ else if (gpg_err_code (rc) == GPG_ERR_FULLY_CANCELED)
+ break; /* Don't try any more secret keys. */
}
- enum_secret_keys (&enum_context, NULL, 0, 0); /* free context */
+ enum_secret_keys (&enum_context, NULL); /* free context */
}
leave: