diff options
author | Werner Koch <[email protected]> | 2010-10-13 15:57:08 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2010-10-13 15:57:08 +0000 |
commit | 54591341a417ca769b2219a9b2f7683f11a74718 (patch) | |
tree | d4cd49932dec93aa9e20e1933ad16ba897965c46 /g10 | |
parent | Describe %v and %V. (diff) | |
download | gnupg-54591341a417ca769b2219a9b2f7683f11a74718.tar.gz gnupg-54591341a417ca769b2219a9b2f7683f11a74718.zip |
More agent support for gpg.
Diffstat (limited to 'g10')
-rw-r--r-- | g10/ChangeLog | 30 | ||||
-rw-r--r-- | g10/call-agent.c | 6 | ||||
-rw-r--r-- | g10/card-util.c | 1 | ||||
-rw-r--r-- | g10/getkey.c | 156 | ||||
-rw-r--r-- | g10/gpg.c | 10 | ||||
-rw-r--r-- | g10/gpgv.c | 18 | ||||
-rw-r--r-- | g10/import.c | 16 | ||||
-rw-r--r-- | g10/keydb.h | 5 | ||||
-rw-r--r-- | g10/keyedit.c | 2 | ||||
-rw-r--r-- | g10/keygen.c | 45 | ||||
-rw-r--r-- | g10/keylist.c | 213 | ||||
-rw-r--r-- | g10/misc.c | 7 | ||||
-rw-r--r-- | g10/options.h | 2 | ||||
-rw-r--r-- | g10/passphrase.c | 14 | ||||
-rw-r--r-- | g10/pubkey-enc.c | 35 |
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 ******* *********************************************/ @@ -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: |