diff options
-rw-r--r-- | doc/DETAILS | 1 | ||||
-rw-r--r-- | g10/call-agent.c | 38 | ||||
-rw-r--r-- | g10/call-agent.h | 4 | ||||
-rw-r--r-- | g10/delkey.c | 47 | ||||
-rw-r--r-- | g10/getkey.c | 32 | ||||
-rw-r--r-- | g10/keydb.h | 3 | ||||
-rw-r--r-- | g10/passphrase.c | 2 |
7 files changed, 121 insertions, 6 deletions
diff --git a/doc/DETAILS b/doc/DETAILS index 3f9e747d5..03c200e71 100644 --- a/doc/DETAILS +++ b/doc/DETAILS @@ -818,6 +818,7 @@ pkd:0:1024:B665B1435F4C2 .... FF26ABB: - 1 :: No such key - 2 :: Must delete secret key first - 3 :: Ambigious specification + - 4 :: Key is stored on a smartcard. *** PROGRESS <what> <char> <cur> <total> Used by the primegen and Public key functions to indicate diff --git a/g10/call-agent.c b/g10/call-agent.c index 4ce6a06ab..5ad0983b9 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -2127,6 +2127,44 @@ agent_export_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc, +/* Ask the agent to delete the key identified by HEXKEYGRIP. If DESC + is not NULL, display DESC instead of the default description + message. */ +gpg_error_t +agent_delete_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc) +{ + gpg_error_t err; + char line[ASSUAN_LINELENGTH]; + struct default_inq_parm_s dfltparm; + + memset (&dfltparm, 0, sizeof dfltparm); + dfltparm.ctrl = ctrl; + + err = start_agent (ctrl, 0); + if (err) + return err; + + if (!hexkeygrip || strlen (hexkeygrip) != 40) + return gpg_error (GPG_ERR_INV_VALUE); + + if (desc) + { + snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc); + err = assuan_transact (agent_ctx, line, + NULL, NULL, NULL, NULL, NULL, NULL); + if (err) + return err; + } + + snprintf (line, DIM(line)-1, "DELETE_KEY %s", hexkeygrip); + err = assuan_transact (agent_ctx, line, NULL, NULL, + default_inq_cb, &dfltparm, + NULL, NULL); + return err; +} + + + /* Ask the agent to change the passphrase of the key identified by HEXKEYGRIP. If DESC is not NULL, display DESC instead of the default description message. If CACHE_NONCE_ADDR is not NULL the diff --git a/g10/call-agent.h b/g10/call-agent.h index 2b944d21b..1deb8548a 100644 --- a/g10/call-agent.h +++ b/g10/call-agent.h @@ -185,6 +185,10 @@ gpg_error_t agent_export_key (ctrl_t ctrl, const char *keygrip, const char *desc, char **cache_nonce_addr, unsigned char **r_result, size_t *r_resultlen); +/* Delete a key from the agent. */ +gpg_error_t agent_delete_key (ctrl_t ctrl, const char *hexkeygrip, + const char *desc); + /* Change the passphrase of a key. */ gpg_error_t agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc, char **cache_nonce_addr, char **passwd_nonce_addr); diff --git a/g10/delkey.c b/g10/delkey.c index 2e4477be9..3de705dfa 100644 --- a/g10/delkey.c +++ b/g10/delkey.c @@ -40,6 +40,7 @@ #include "ttyio.h" #include "status.h" #include "i18n.h" +#include "call-agent.h" /**************** @@ -52,7 +53,7 @@ do_delete_key( const char *username, int secret, int force, int *r_sec_avail ) { gpg_error_t err; kbnode_t keyblock = NULL; - kbnode_t node; + kbnode_t node, kbctx; KEYDB_HANDLE hd; PKT_public_key *pk = NULL; u32 keyid[2]; @@ -156,9 +157,47 @@ do_delete_key( const char *username, int secret, int force, int *r_sec_avail ) { if (secret) { - log_error (_("deleting secret key not implemented\n")); - err = gpg_error (GPG_ERR_NOT_IMPLEMENTED); /* FIXME */ - goto leave; + char *prompt; + gpg_error_t firsterr = 0; + char *hexgrip; + + setup_main_keyids (keyblock); + for (kbctx=NULL; (node = walk_kbnode (keyblock, &kbctx, 0)); ) + { + if (!(node->pkt->pkttype == PKT_PUBLIC_KEY + || node->pkt->pkttype == PKT_PUBLIC_SUBKEY)) + continue; + + if (agent_probe_secret_key (NULL, node->pkt->pkt.public_key)) + continue; /* No secret key for that public (sub)key. */ + + prompt = gpg_format_keydesc (node->pkt->pkt.public_key, + FORMAT_KEYDESC_DELKEY, 1); + err = hexkeygrip_from_pk (node->pkt->pkt.public_key, &hexgrip); + if (!err) + err = agent_delete_key (NULL, hexgrip, prompt); + xfree (prompt); + xfree (hexgrip); + if (err) + { + if (gpg_err_code (err) == GPG_ERR_KEY_ON_CARD) + write_status_text (STATUS_DELETE_PROBLEM, "1"); + log_error (_("deleting secret %s failed: %s\n"), + (node->pkt->pkttype == PKT_PUBLIC_KEY + ? _("key"):_("subkey")), + gpg_strerror (err)); + if (!firsterr) + firsterr = err; + if (gpg_err_code (err) == GPG_ERR_CANCELED + || gpg_err_code (err) == GPG_ERR_FULLY_CANCELED) + break; + } + + } + + err = firsterr; + if (firsterr) + goto leave; } else { diff --git a/g10/getkey.c b/g10/getkey.c index 777f3833f..458672a09 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -1237,6 +1237,38 @@ getkey_end (getkey_ctx_t ctx) ************* Merging stuff ******************** ************************************************/ +/* Set the mainkey_id fields for all keys in KEYBLOCK. This is + usually done by merge_selfsigs but at some places we only need the + main_kid but the the full merging. The function also guarantees + that all pk->keyids are computed. */ +void +setup_main_keyids (kbnode_t keyblock) +{ + u32 kid[2], mainkid[2]; + kbnode_t kbctx, node; + PKT_public_key *pk; + + if (keyblock->pkt->pkttype != PKT_PUBLIC_KEY) + BUG (); + pk = keyblock->pkt->pkt.public_key; + + keyid_from_pk (pk, mainkid); + for (kbctx=NULL; (node = walk_kbnode (keyblock, &kbctx, 0)); ) + { + if (!(node->pkt->pkttype == PKT_PUBLIC_KEY + || node->pkt->pkttype == PKT_PUBLIC_SUBKEY)) + continue; + pk = node->pkt->pkt.public_key; + keyid_from_pk (pk, kid); /* Make sure pk->keyid is set. */ + if (!pk->main_keyid[0] && !pk->main_keyid[1]) + { + pk->main_keyid[0] = mainkid[0]; + pk->main_keyid[1] = mainkid[1]; + } + } +} + + /* Merge all self-signatures with the keys. */ void merge_keys_and_selfsig (KBNODE keyblock) diff --git a/g10/keydb.h b/g10/keydb.h index 492cde37f..b21d9550d 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -201,7 +201,7 @@ void emit_status_need_passphrase (u32 *keyid, u32 *mainkeyid, int pubkey_algo); #define FORMAT_KEYDESC_NORMAL 0 #define FORMAT_KEYDESC_IMPORT 1 #define FORMAT_KEYDESC_EXPORT 2 - +#define FORMAT_KEYDESC_DELKEY 3 char *gpg_format_keydesc (PKT_public_key *pk, int mode, int escaped); @@ -248,6 +248,7 @@ void getkey_end (getkey_ctx_t ctx); gpg_error_t enum_secret_keys (void **context, PKT_public_key *pk); +void setup_main_keyids (kbnode_t keyblock); 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/passphrase.c b/g10/passphrase.c index 7c1d6aa08..280d8a9b5 100644 --- a/g10/passphrase.c +++ b/g10/passphrase.c @@ -702,7 +702,7 @@ gpg_format_keydesc (PKT_public_key *pk, int mode, int escaped) (int)uidlen, uid, nbits_from_pk (pk), algo_name, keystr (pk->keyid), timestr, - maink?maink:"", trailer ); + maink?maink:"", trailer); xfree (maink); xfree (uid); |