aboutsummaryrefslogtreecommitdiffstats
path: root/g10
diff options
context:
space:
mode:
Diffstat (limited to 'g10')
-rw-r--r--g10/ChangeLog19
-rw-r--r--g10/call-agent.c86
-rw-r--r--g10/call-agent.h5
-rw-r--r--g10/gpg.c2
-rw-r--r--g10/keyedit.c282
-rw-r--r--g10/main.h2
-rw-r--r--g10/passphrase.c8
7 files changed, 183 insertions, 221 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog
index 7d7b68619..65f9117c1 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,5 +1,24 @@
+2010-10-26 Werner Koch <[email protected]>
+
+ * keyedit.c (change_passphrase): Handle the passwd_nonce.
+ * call-agent.c (cache_nonce_parm_s): New.
+ (cache_nonce_status_cb): Use that new struct.
+ (agent_genkey, agent_import_key, agent_export_key, agent_passwd):
+ Adjust for that change.
+
+2010-10-25 Werner Koch <[email protected]>
+
+ * passphrase.c (gpg_format_keydesc): Fix printing of main keyid.
+
+ * keyedit.c (JNLIB_NEED_LOG_LOGV): Define.
+ * call-agent.c (agent_passwd): New.
+
2010-10-21 Werner Koch <[email protected]>
+ * keyedit.c (keyedit_passwd): Simplify.
+ (change_passphrase): Return an error code and not the change
+ flag. Remove editing of the keyring.
+
* seckey-cert.c: Remove.
* Makefile.am (gpg2_SOURCES): Remove seckey-cert.c
diff --git a/g10/call-agent.c b/g10/call-agent.c
index e611ba612..f691baf68 100644
--- a/g10/call-agent.c
+++ b/g10/call-agent.c
@@ -86,6 +86,13 @@ struct import_key_parm_s
};
+struct cache_nonce_parm_s
+{
+ char **cache_nonce_addr;
+ char **passwd_nonce_addr;
+};
+
+
static gpg_error_t learn_status_cb (void *opaque, const char *line);
@@ -1470,7 +1477,7 @@ agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip, char **r_serialno)
static gpg_error_t
cache_nonce_status_cb (void *opaque, const char *line)
{
- char **cache_nonce = opaque;
+ struct cache_nonce_parm_s *parm = opaque;
const char *keyword = line;
int keywordlen;
@@ -1481,10 +1488,18 @@ cache_nonce_status_cb (void *opaque, const char *line)
if (keywordlen == 11 && !memcmp (keyword, "CACHE_NONCE", keywordlen))
{
- if (cache_nonce)
+ if (parm->cache_nonce_addr)
+ {
+ xfree (*parm->cache_nonce_addr);
+ *parm->cache_nonce_addr = xtrystrdup (line);
+ }
+ }
+ else if (keywordlen == 12 && !memcmp (keyword, "PASSWD_NONCE", keywordlen))
+ {
+ if (parm->passwd_nonce_addr)
{
- xfree (*cache_nonce);
- *cache_nonce = xtrystrdup (line);
+ xfree (*parm->passwd_nonce_addr);
+ *parm->passwd_nonce_addr = xtrystrdup (line);
}
}
@@ -1523,6 +1538,7 @@ agent_genkey (ctrl_t ctrl, char **cache_nonce_addr,
{
gpg_error_t err;
struct genkey_parm_s gk_parm;
+ struct cache_nonce_parm_s cn_parm;
membuf_t data;
size_t len;
unsigned char *buf;
@@ -1546,10 +1562,12 @@ agent_genkey (ctrl_t ctrl, char **cache_nonce_addr,
no_protection? " --no-protection":"",
cache_nonce_addr && *cache_nonce_addr? " ":"",
cache_nonce_addr && *cache_nonce_addr? *cache_nonce_addr:"");
+ cn_parm.cache_nonce_addr = cache_nonce_addr;
+ cn_parm.passwd_nonce_addr = NULL;
err = assuan_transact (agent_ctx, line,
membuf_data_cb, &data,
inq_genkey_parms, &gk_parm,
- cache_nonce_status_cb, cache_nonce_addr);
+ cache_nonce_status_cb, &cn_parm);
if (err)
{
xfree (get_membuf (&data, &len));
@@ -1625,7 +1643,7 @@ agent_genkey (ctrl_t ctrl, char **cache_nonce_addr,
displayed if the agent needs to ask for the PIN. DIGEST and
DIGESTLEN is the hash value to sign and DIGESTALGO the algorithm id
used to compute the digest. If CACHE_NONCE is used the agent is
- advised to firts try a passphrase associated with that nonce. */
+ advised to first try a passphrase associated with that nonce. */
gpg_error_t
agent_pksign (ctrl_t ctrl, const char *cache_nonce,
const char *keygrip, const char *desc,
@@ -1890,6 +1908,7 @@ agent_import_key (ctrl_t ctrl, const char *desc, char **cache_nonce_addr,
{
gpg_error_t err;
struct import_key_parm_s parm;
+ struct cache_nonce_parm_s cn_parm;
char line[ASSUAN_LINELENGTH];
err = start_agent (ctrl, 0);
@@ -1914,9 +1933,11 @@ agent_import_key (ctrl_t ctrl, const char *desc, char **cache_nonce_addr,
snprintf (line, sizeof line, "IMPORT_KEY%s%s",
cache_nonce_addr && *cache_nonce_addr? " ":"",
cache_nonce_addr && *cache_nonce_addr? *cache_nonce_addr:"");
+ cn_parm.cache_nonce_addr = cache_nonce_addr;
+ cn_parm.passwd_nonce_addr = NULL;
err = assuan_transact (agent_ctx, line,
NULL, NULL, inq_import_key_parms, &parm,
- cache_nonce_status_cb, cache_nonce_addr);
+ cache_nonce_status_cb, &cn_parm);
return err;
}
@@ -1932,6 +1953,7 @@ agent_export_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
unsigned char **r_result, size_t *r_resultlen)
{
gpg_error_t err;
+ struct cache_nonce_parm_s cn_parm;
membuf_t data;
size_t len;
unsigned char *buf;
@@ -1958,10 +1980,12 @@ agent_export_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
hexkeygrip);
init_membuf_secure (&data, 1024);
+ cn_parm.cache_nonce_addr = cache_nonce_addr;
+ cn_parm.passwd_nonce_addr = NULL;
err = assuan_transact (agent_ctx, line,
membuf_data_cb, &data,
default_inq_cb, ctrl,
- cache_nonce_status_cb, cache_nonce_addr);
+ cache_nonce_status_cb, &cn_parm);
if (err)
{
xfree (get_membuf (&data, &len));
@@ -1974,3 +1998,49 @@ agent_export_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
*r_resultlen = len;
return 0;
}
+
+
+
+/* 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
+ agent is advised to first try a passphrase associated with that
+ nonce. If PASSWD_NONCE_ADDR is not NULL the agent will try to use
+ the passphrase associated with that nonce. */
+gpg_error_t
+agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
+ char **cache_nonce_addr, char **passwd_nonce_addr)
+{
+ gpg_error_t err;
+ struct cache_nonce_parm_s cn_parm;
+ char line[ASSUAN_LINELENGTH];
+
+ 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, "PASSWD %s%s %s%s %s",
+ cache_nonce_addr && *cache_nonce_addr? "--cache-nonce=":"",
+ cache_nonce_addr && *cache_nonce_addr? *cache_nonce_addr:"",
+ passwd_nonce_addr && *passwd_nonce_addr? "--passwd-nonce=":"",
+ passwd_nonce_addr && *passwd_nonce_addr? *passwd_nonce_addr:"",
+ hexkeygrip);
+ cn_parm.cache_nonce_addr = cache_nonce_addr;
+ cn_parm.passwd_nonce_addr = passwd_nonce_addr;
+ err = assuan_transact (agent_ctx, line, NULL, NULL,
+ default_inq_cb, ctrl,
+ cache_nonce_status_cb, &cn_parm);
+ return err;
+}
diff --git a/g10/call-agent.h b/g10/call-agent.h
index 6cba9c78c..e09c30990 100644
--- a/g10/call-agent.h
+++ b/g10/call-agent.h
@@ -184,6 +184,9 @@ 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);
+/* 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);
-#endif /*GNUPG_G10_CALL_AGENT_H*/
+#endif /*GNUPG_G10_CALL_AGENT_H*/
diff --git a/g10/gpg.c b/g10/gpg.c
index 5ee03a63b..847220afd 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -3657,7 +3657,7 @@ main (int argc, char **argv)
else
{
username = make_username (fname);
- keyedit_passwd (username);
+ keyedit_passwd (ctrl, username);
xfree (username);
}
break;
diff --git a/g10/keyedit.c b/g10/keyedit.c
index 1686fa6e0..ee411016e 100644
--- a/g10/keyedit.c
+++ b/g10/keyedit.c
@@ -30,6 +30,7 @@
# include <readline/readline.h>
#endif
+#define JNLIB_NEED_LOG_LOGV
#include "gpg.h"
#include "options.h"
#include "packet.h"
@@ -1124,44 +1125,63 @@ leave:
/*
- * Change the passphrase of the primary and all secondary keys.
- * We use only one passphrase for all keys.
+ * Change the passphrase of the primary and all secondary keys. Note
+ * that it is common to use only one passphrase for the primary and
+ * all subkeys. However, this is now (since GnuPG 2.1) all up to the
+ * gpg-agent. Returns 0 on success or an error code.
*/
-static int
-change_passphrase (KBNODE keyblock, int *r_err)
+static gpg_error_t
+change_passphrase (ctrl_t ctrl, kbnode_t keyblock)
{
- int rc = 0;
- int changed = 0;
- KBNODE node;
- PKT_public_key *pksk;
- char *passphrase = NULL;
- int no_primary_secrets = 0;
+ gpg_error_t err;
+ kbnode_t node;
+ PKT_public_key *pk;
int any;
+ u32 keyid[2], subid[2];
+ char *hexgrip = NULL;
+ char *cache_nonce = NULL;
+ char *passwd_nonce = NULL;
node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
if (!node)
{
log_error ("Oops; public key missing!\n");
+ err = gpg_error (GPG_ERR_INTERNAL);
goto leave;
}
- pksk = node->pkt->pkt.public_key;
+ pk = node->pkt->pkt.public_key;
+ keyid_from_pk (pk, keyid);
+ /* Check whether it is likely that we will be able to change the
+ passphrase for any subkey. */
for (any = 0, node = keyblock; node; node = node->next)
{
if (node->pkt->pkttype == PKT_PUBLIC_KEY
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
{
- log_debug ("FIXME\n");
- /* PKT_public_key *tmpsk = node->pkt->pkt.public_key; */
- /* if (!(tmpsk->is_protected */
- /* && (tmpsk->protect.s2k.mode == 1001 */
- /* || tmpsk->protect.s2k.mode == 1002))) */
- /* { */
- /* any = 1; */
- /* break; */
- /* } */
+ char *serialno;
+
+ pk = node->pkt->pkt.public_key;
+ keyid_from_pk (pk, subid);
+
+ xfree (hexgrip);
+ err = hexkeygrip_from_pk (pk, &hexgrip);
+ if (err)
+ goto leave;
+ err = agent_get_keyinfo (ctrl, hexgrip, &serialno);
+ if (!err && serialno)
+ ; /* Key on card. */
+ else if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
+ ; /* Maybe stub key. */
+ else if (!err)
+ any = 1; /* Key is known. */
+ else
+ log_error ("key %s: error getting keyinfo from agent: %s\n",
+ keystr_with_sub (keyid, subid), gpg_strerror (err));
+ xfree (serialno);
}
}
+ err = 0;
if (!any)
{
tty_printf (_("Key has only stub or on-card key items - "
@@ -1169,162 +1189,43 @@ change_passphrase (KBNODE keyblock, int *r_err)
goto leave;
}
- log_debug ("FIXME\n");
- /* See how to handle this key. */
- /* switch (is_secret_key_protected (pksk)) */
- /* { */
- /* case -1: */
- /* rc = G10ERR_PUBKEY_ALGO; */
- /* break; */
- /* case 0: */
- /* tty_printf (_("This key is not protected.\n")); */
- /* break; */
- /* default: */
- /* if (sk->protect.s2k.mode == 1001) */
- /* { */
- /* tty_printf (_("Secret parts of key are not available.\n")); */
- /* no_primary_secrets = 1; */
- /* } */
- /* else if (sk->protect.s2k.mode == 1002) */
- /* { */
- /* tty_printf (_("Secret parts of key are stored on-card.\n")); */
- /* no_primary_secrets = 1; */
- /* } */
- /* else */
- /* { */
- /* u32 keyid[2]; */
-
- /* tty_printf (_("Key is protected.\n")); */
-
- /* /\* Clear the passphrase cache so that the user is required */
- /* to enter the old passphrase. *\/ */
- /* keyid_from_pk (pksk, keyid); */
- /* passphrase_clear_cache (keyid, NULL, 0); */
-
- /* /\* rc = check_secret_key( sk, 0 ); *\/ */
- /* /\* if( !rc ) *\/ */
- /* /\* passphrase = get_last_passphrase(); *\/ */
- /* } */
- /* break; */
- /* } */
-
- /* Unprotect all subkeys (use the supplied passphrase or ask) */
- for (node = keyblock; !rc && node; node = node->next)
- {
- if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
- {
- log_debug ("FIXME\n");
- /* PKT_pubic_key *subsk = node->pkt->pkt.public_key; */
- /* if (!(subsk->is_protected */
- /* && (subsk->protect.s2k.mode == 1001 */
- /* || subsk->protect.s2k.mode == 1002))) */
- /* { */
- /* set_next_passphrase (passphrase); */
- /* /\* rc = check_secret_key( subsk, 0 ); *\/ */
- /* /\* if( !rc && !passphrase ) *\/ */
- /* /\* passphrase = get_last_passphrase(); *\/ */
- /* } */
- }
- }
-
- if (rc)
- tty_printf (_("Can't edit this key: %s\n"), g10_errstr (rc));
- else
+ /* Change the passphrase for all keys. */
+ for (any = 0, node = keyblock; node; node = node->next)
{
- DEK *dek = NULL;
- STRING2KEY *s2k = xmalloc_secure (sizeof *s2k);
- const char *errtext = NULL;
-
- tty_printf (_("Enter the new passphrase for this secret key.\n\n"));
-
- set_next_passphrase (NULL);
- for (;;)
- {
- int canceled;
-
- s2k->mode = opt.s2k_mode;
- s2k->hash_algo = S2K_DIGEST_ALGO;
- dek = passphrase_to_dek (NULL, 0, opt.s2k_cipher_algo,
- s2k, 2, errtext, &canceled);
- if (!dek && canceled)
- {
- rc = GPG_ERR_CANCELED;
- break;
- }
- else if (!dek)
- {
- errtext = N_("passphrase not correctly repeated; try again");
- tty_printf ("%s.\n", _(errtext));
- }
- else if (!dek->keylen)
- {
- rc = 0;
- tty_printf (_("You don't want a passphrase -"
- " this is probably a *bad* idea!\n\n"));
- if (cpr_get_answer_is_yes
- ("change_passwd.empty.okay",
- _("Do you really want to do this? (y/N) ")))
- {
- changed++;
- break;
- }
- }
- else
- { /* okay */
- rc = 0;
- if (!no_primary_secrets)
- {
- /* sk->protect.algo = dek->algo; */
- /* sk->protect.s2k = *s2k; */
- rc = 0;
- /* rc = protect_secret_key( sk, dek ); */
- }
- for (node = keyblock; !rc && node; node = node->next)
- {
- if (node->pkt->pkttype == PKT_SECRET_SUBKEY)
- {
- log_debug ("FIXME\n");
-/* PKT_secret_key *subsk = node->pkt->pkt.secret_key; */
-/* if (!(subsk->is_protected */
-/* && (subsk->protect.s2k.mode == 1001 */
-/* || subsk->protect.s2k.mode == 1002))) */
-/* { */
-/* subsk->protect.algo = dek->algo; */
-/* subsk->protect.s2k = *s2k; */
-/* #warning fixme */
-/* rc = 0; */
-/* /\* rc = protect_secret_key( subsk, dek ); *\/ */
-/* } */
- }
- }
- if (rc)
- log_error ("protect_secret_key failed: %s\n",
- g10_errstr (rc));
- else
- {
- u32 keyid[2];
+ if (node->pkt->pkttype == PKT_PUBLIC_KEY
+ || node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
+ {
+ char *desc;
- /* Clear the cahce again so that the user is
- required to enter the new passphrase at the
- next operation. */
- /* FIXME keyid_from_sk (sk, keyid); */
- passphrase_clear_cache (keyid, NULL, 0);
+ pk = node->pkt->pkt.public_key;
+ keyid_from_pk (pk, subid);
- changed++;
- }
- break;
- }
- }
- xfree (s2k);
- xfree (dek);
+ xfree (hexgrip);
+ err = hexkeygrip_from_pk (pk, &hexgrip);
+ if (err)
+ goto leave;
+
+ desc = gpg_format_keydesc (pk, 0, 1);
+ err = agent_passwd (ctrl, hexgrip, desc, &cache_nonce, &passwd_nonce);
+ xfree (desc);
+
+ if (err)
+ log_log ((gpg_err_code (err) == GPG_ERR_CANCELED
+ || gpg_err_code (err) == GPG_ERR_FULLY_CANCELED)
+ ? JNLIB_LOG_INFO : JNLIB_LOG_ERROR,
+ _("key %s: error changing passphrase: %s\n"),
+ keystr_with_sub (keyid, subid),
+ gpg_strerror (err));
+ if (gpg_err_code (err) == GPG_ERR_FULLY_CANCELED)
+ break;
+ }
}
-leave:
- xfree (passphrase);
- set_next_passphrase (NULL);
- if (r_err)
- *r_err = rc;
- return changed && !rc;
+ leave:
+ xfree (hexgrip);
+ xfree (cache_nonce);
+ xfree (passwd_nonce);
+ return err;
}
@@ -2184,7 +2085,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
break;
case cmdPASSWD:
- change_passphrase (keyblock, NULL);
+ change_passphrase (ctrl, keyblock);
break;
case cmdTRUST:
@@ -2361,13 +2262,10 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
/* Change the passphrase of the secret key identified by USERNAME. */
void
-keyedit_passwd (const char *username)
+keyedit_passwd (ctrl_t ctrl, const char *username)
{
gpg_error_t err;
PKT_public_key *pk;
- unsigned char fpr[MAX_FINGERPRINT_LEN];
- size_t fprlen;
- KEYDB_HANDLE kdh = NULL;
kbnode_t keyblock = NULL;
pk = xtrycalloc (1, sizeof *pk);
@@ -2376,44 +2274,16 @@ keyedit_passwd (const char *username)
err = gpg_error_from_syserror ();
goto leave;
}
- err = getkey_byname (NULL, pk, username, 1, NULL);
- if (err)
- goto leave;
- fingerprint_from_pk (pk, fpr, &fprlen);
- while (fprlen < MAX_FINGERPRINT_LEN)
- fpr[fprlen++] = 0;
-
- /* FIXME: Call an agent function instead. */
-
- kdh = NULL /*keydb_new (1)*/;
- if (!kdh)
- {
- err = gpg_error (GPG_ERR_GENERAL);
- goto leave;
- }
-
- err = keydb_search_fpr (kdh, fpr);
- if (err == -1 || gpg_err_code (err) == GPG_ERR_EOF)
- err = gpg_error (GPG_ERR_NO_SECKEY);
- if (err)
- goto leave;
-
- err = keydb_get_keyblock (kdh, &keyblock);
+ err = getkey_byname (NULL, pk, username, 1, &keyblock);
if (err)
goto leave;
- if (!change_passphrase (keyblock, &err))
- goto leave;
-
- err = keydb_update_keyblock (kdh, keyblock);
- if (err)
- log_error (_("update secret failed: %s\n"), gpg_strerror (err));
+ err = change_passphrase (ctrl, keyblock);
leave:
release_kbnode (keyblock);
if (pk)
free_public_key (pk);
- keydb_release (kdh);
if (err)
{
log_info ("error changing the passphrase for `%s': %s\n",
diff --git a/g10/main.h b/g10/main.h
index 3804effd3..b8ef34020 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -224,7 +224,7 @@ int delete_keys( strlist_t names, int secret, int allow_both );
/*-- keyedit.c --*/
void keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
strlist_t commands, int quiet, int seckey_check );
-void keyedit_passwd (const char *username);
+void keyedit_passwd (ctrl_t ctrl, const char *username);
void show_basic_key_info (KBNODE keyblock);
/*-- keygen.c --*/
diff --git a/g10/passphrase.c b/g10/passphrase.c
index b28477fd5..9f1218b6b 100644
--- a/g10/passphrase.c
+++ b/g10/passphrase.c
@@ -675,7 +675,7 @@ passphrase_to_dek (u32 *keyid, int pubkey_algo,
}
-/* Return an allocated utf-8 string describing the key PK. IF ESCAPED
+/* Return an allocated utf-8 string describing the key PK. If ESCAPED
is true spaces and control characters are percent or plus escaped.
MODE 0 is for the common prompt, MODE 1 for the import prompt. */
char *
@@ -696,9 +696,9 @@ gpg_format_keydesc (PKT_public_key *pk, int mode, int escaped)
orig_codeset = i18n_switchto_utf8 ();
- if (pk->main_keyid[2] && pk->main_keyid[3]
- && pk->keyid[0] != pk->main_keyid[2]
- && pk->keyid[1] != pk->main_keyid[3])
+ if (pk->main_keyid[0] && pk->main_keyid[1]
+ && pk->keyid[0] != pk->main_keyid[0]
+ && pk->keyid[1] != pk->main_keyid[1])
maink = xtryasprintf (_(" (main key ID %s)"), keystr (pk->main_keyid));
else
maink = NULL;