Re-implemented GPG's --passwd command and improved it.

This commit is contained in:
Werner Koch 2010-10-26 09:10:29 +00:00
parent c212133918
commit 02e4c3cb7e
18 changed files with 696 additions and 571 deletions

View File

@ -1,3 +1,20 @@
2010-10-26 Werner Koch <wk@g10code.com>
* cache.c (agent_put_cache): Allow deletion even if TTL is passwd
as 0.
* genkey.c (agent_protect_and_store): Add arg PASSPHRASE_ADDR.
* command.c (cmd_passwd): Add option --passwd-nonce.
(struct server_local_s): Add LAST_CACHE_NONCE and LAST_PASSWD_NONCE.
(clear_nonce_cache): New.
(reset_notify): Clear the nonce cache.
(start_command_handler): Ditto.
2010-10-25 Werner Koch <wk@g10code.com>
* command.c (cmd_export_key): Free CACHE_NONCE.
(cmd_passwd): Add option --cache-nonce.
2010-10-18 Werner Koch <wk@g10code.com>
* call-pinentry.c (start_pinentry): Print name of pinentry on

View File

@ -295,7 +295,8 @@ gpg_error_t agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt,
int agent_genkey (ctrl_t ctrl, const char *cache_nonce,
const char *keyparam, size_t keyparmlen,
int no_protection, membuf_t *outbuf);
int agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey);
gpg_error_t agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey,
char **passphrase_addr);
/*-- protect.c --*/
unsigned long get_standard_s2k_count (void);

View File

@ -284,7 +284,7 @@ agent_put_cache (const char *key, cache_mode_t cache_mode,
default: ttl = opt.def_cache_ttl; break;
}
}
if (!ttl || cache_mode == CACHE_MODE_IGNORE)
if ((!ttl && data) || cache_mode == CACHE_MODE_IGNORE)
return 0;
for (r=thecache; r; r = r->next)

View File

@ -72,6 +72,8 @@ struct server_local_s
void *import_key; /* Malloced KEK for the import_key command. */
void *export_key; /* Malloced KEK for the export_key command. */
int allow_fully_canceled; /* Client is aware of GPG_ERR_FULLY_CANCELED. */
char *last_cache_nonce; /* Last CACHE_NOCNE sent as status (malloced). */
char *last_passwd_nonce; /* Last PASSWD_NOCNE sent as status (malloced). */
};
@ -153,6 +155,26 @@ write_and_clear_outbuf (assuan_context_t ctx, membuf_t *mb)
}
static void
clear_nonce_cache (ctrl_t ctrl)
{
if (ctrl->server_local->last_cache_nonce)
{
agent_put_cache (ctrl->server_local->last_cache_nonce,
CACHE_MODE_NONCE, NULL, 0);
xfree (ctrl->server_local->last_cache_nonce);
ctrl->server_local->last_cache_nonce = NULL;
}
if (ctrl->server_local->last_passwd_nonce)
{
agent_put_cache (ctrl->server_local->last_passwd_nonce,
CACHE_MODE_NONCE, NULL, 0);
xfree (ctrl->server_local->last_passwd_nonce);
ctrl->server_local->last_passwd_nonce = NULL;
}
}
static gpg_error_t
reset_notify (assuan_context_t ctx, char *line)
{
@ -166,6 +188,9 @@ reset_notify (assuan_context_t ctx, char *line)
xfree (ctrl->server_local->keydesc);
ctrl->server_local->keydesc = NULL;
clear_nonce_cache (ctrl);
return 0;
}
@ -1331,44 +1356,135 @@ cmd_learn (assuan_context_t ctx, char *line)
static const char hlp_passwd[] =
"PASSWD <hexstring_with_keygrip>\n"
"PASSWD [--cache-nonce=<c>] [--passwd-nonce=<s>] <hexstring_with_keygrip>\n"
"\n"
"Change the passphrase/PIN for the key identified by keygrip in LINE.";
static gpg_error_t
cmd_passwd (assuan_context_t ctx, char *line)
{
ctrl_t ctrl = assuan_get_pointer (ctx);
int rc;
gpg_error_t err;
int c;
char *cache_nonce = NULL;
char *passwd_nonce = NULL;
unsigned char grip[20];
gcry_sexp_t s_skey = NULL;
unsigned char *shadow_info = NULL;
char *passphrase = NULL;
char *pend;
rc = parse_keygrip (ctx, line, grip);
if (rc)
cache_nonce = option_value (line, "--cache-nonce");
if (cache_nonce)
{
for (pend = cache_nonce; *pend && !spacep (pend); pend++)
;
c = *pend;
*pend = '\0';
cache_nonce = xtrystrdup (cache_nonce);
*pend = c;
if (!cache_nonce)
{
err = gpg_error_from_syserror ();
goto leave;
}
}
passwd_nonce = option_value (line, "--passwd-nonce");
if (passwd_nonce)
{
for (pend = passwd_nonce; *pend && !spacep (pend); pend++)
;
c = *pend;
*pend = '\0';
passwd_nonce = xtrystrdup (passwd_nonce);
*pend = c;
if (!passwd_nonce)
{
err = gpg_error_from_syserror ();
goto leave;
}
}
line = skip_options (line);
err = parse_keygrip (ctx, line, grip);
if (err)
goto leave;
ctrl->in_passwd++;
rc = agent_key_from_file (ctrl, NULL, ctrl->server_local->keydesc,
grip, &shadow_info, CACHE_MODE_IGNORE, NULL,
&s_skey, NULL);
if (rc)
err = agent_key_from_file (ctrl, cache_nonce, ctrl->server_local->keydesc,
grip, &shadow_info, CACHE_MODE_IGNORE, NULL,
&s_skey, &passphrase);
if (err)
;
else if (!s_skey)
{
log_error ("changing a smartcard PIN is not yet supported\n");
rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
}
else
rc = agent_protect_and_store (ctrl, s_skey);
{
char *newpass = NULL;
if (passwd_nonce)
newpass = agent_get_cache (passwd_nonce, CACHE_MODE_NONCE);
err = agent_protect_and_store (ctrl, s_skey, &newpass);
if (!err && passphrase)
{
/* A passphrase existed on the old key and the change was
successful. Return a nonce for that old passphrase to
let the caller try to unprotect the other subkeys with
the same key. */
if (!cache_nonce)
{
char buf[12];
gcry_create_nonce (buf, 12);
cache_nonce = bin2hex (buf, 12, NULL);
}
if (cache_nonce
&& !agent_put_cache (cache_nonce, CACHE_MODE_NONCE,
passphrase, 120 /*seconds*/))
{
assuan_write_status (ctx, "CACHE_NONCE", cache_nonce);
xfree (ctrl->server_local->last_cache_nonce);
ctrl->server_local->last_cache_nonce = cache_nonce;
cache_nonce = NULL;
}
if (newpass)
{
/* If we have a new passphrase (which might be empty) we
store it under a passwd nonce so that the caller may
send that nonce again to use it for another key. */
if (!passwd_nonce)
{
char buf[12];
gcry_create_nonce (buf, 12);
passwd_nonce = bin2hex (buf, 12, NULL);
}
if (passwd_nonce
&& !agent_put_cache (passwd_nonce, CACHE_MODE_NONCE,
newpass, 120 /*seconds*/))
{
assuan_write_status (ctx, "PASSWD_NONCE", passwd_nonce);
xfree (ctrl->server_local->last_passwd_nonce);
ctrl->server_local->last_passwd_nonce = passwd_nonce;
passwd_nonce = NULL;
}
}
}
xfree (newpass);
}
ctrl->in_passwd--;
xfree (ctrl->server_local->keydesc);
ctrl->server_local->keydesc = NULL;
leave:
xfree (passphrase);
gcry_sexp_release (s_skey);
xfree (shadow_info);
return leave_cmd (ctx, rc);
xfree (cache_nonce);
return leave_cmd (ctx, err);
}
@ -1812,6 +1928,7 @@ cmd_export_key (assuan_context_t ctx, char *line)
leave:
xfree (cache_nonce);
xfree (passphrase);
xfree (wrappedkey);
gcry_cipher_close (cipherhd);
@ -2448,6 +2565,9 @@ start_command_handler (ctrl_t ctrl, gnupg_fd_t listen_fd, gnupg_fd_t fd)
}
}
/* Reset the nonce caches. */
clear_nonce_cache (ctrl);
/* Reset the SCD if needed. */
agent_reset_scd (ctrl);

View File

@ -405,7 +405,7 @@ unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
xfree (pi);
return rc;
}
rc = agent_protect_and_store (ctrl, s_skey);
rc = agent_protect_and_store (ctrl, s_skey, NULL);
gcry_sexp_release (s_skey);
if (rc)
{

View File

@ -468,20 +468,40 @@ agent_genkey (ctrl_t ctrl, const char *cache_nonce,
/* Apply a new passphrase to the key S_SKEY and store it. */
int
agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey)
/* Apply a new passphrase to the key S_SKEY and store it. If
PASSPHRASE_ADDR and *PASSPHRASE_ADDR are not NULL, use that
passphrase. If PASSPHRASE_ADDR is not NULL store a newly entered
passphrase at that address. */
gpg_error_t
agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey,
char **passphrase_addr)
{
int rc;
char *passphrase;
gpg_error_t err;
rc = agent_ask_new_passphrase (ctrl,
_("Please enter the new passphrase"),
&passphrase);
if (!rc)
if (passphrase_addr && *passphrase_addr)
{
rc = store_key (s_skey, passphrase, 1);
xfree (passphrase);
/* Take an empty string as request not to protect the key. */
err = store_key (s_skey, **passphrase_addr? *passphrase_addr:NULL, 1);
}
return rc;
else
{
char *pass = NULL;
if (passphrase_addr)
{
xfree (*passphrase_addr);
*passphrase_addr = NULL;
}
err = agent_ask_new_passphrase (ctrl,
_("Please enter the new passphrase"),
&pass);
if (!err)
err = store_key (s_skey, pass, 1);
if (!err && passphrase_addr)
*passphrase_addr = pass;
else
xfree (pass);
}
return err;
}

View File

@ -1,3 +1,7 @@
2010-10-25 Werner Koch <wk@g10code.com>
* logging.c (do_log): Rename to log_log and make global.
2010-10-20 Werner Koch <wk@g10code.com>
* i18n.c (i18n_init) [USE_SIMPLE_GETTEXT]: Call textdomain.

View File

@ -670,8 +670,8 @@ do_logv (int level, int ignore_arg_ptr, const char *fmt, va_list arg_ptr)
}
static void
do_log (int level, const char *fmt, ...)
void
log_log (int level, const char *fmt, ...)
{
va_list arg_ptr ;
@ -812,14 +812,14 @@ log_printhex (const char *text, const void *buffer, size_t length)
void
bug_at( const char *file, int line, const char *func )
{
do_log (JNLIB_LOG_BUG, ("... this is a bug (%s:%d:%s)\n"), file, line, func);
log_log (JNLIB_LOG_BUG, ("... this is a bug (%s:%d:%s)\n"), file, line, func);
abort (); /* Never called; just to make the compiler happy. */
}
#else
void
bug_at( const char *file, int line )
{
do_log (JNLIB_LOG_BUG, _("you found a bug ... (%s:%d)\n"), file, line);
log_log (JNLIB_LOG_BUG, _("you found a bug ... (%s:%d)\n"), file, line);
abort (); /* Never called; just to make the compiler happy. */
}
#endif

View File

@ -65,6 +65,7 @@ enum jnlib_log_levels {
JNLIB_LOG_BUG,
JNLIB_LOG_DEBUG
};
void log_log (int level, const char *fmt, ...) JNLIB_GCC_A_PRINTF(2,3);
void log_logv (int level, const char *fmt, va_list arg_ptr);
void log_string (int level, const char *string);
#endif /*JNLIB_NEED_LOG_LOGV*/

View File

@ -1,5 +1,24 @@
2010-10-26 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <wk@g10code.com>
* 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

View File

@ -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 (*cache_nonce);
*cache_nonce = xtrystrdup (line);
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 (*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;
}

View File

@ -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*/

View File

@ -3657,7 +3657,7 @@ main (int argc, char **argv)
else
{
username = make_username (fname);
keyedit_passwd (username);
keyedit_passwd (ctrl, username);
xfree (username);
}
break;

View File

@ -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)
/* Change the passphrase for all keys. */
for (any = 0, node = keyblock; 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 (node->pkt->pkttype == PKT_PUBLIC_KEY
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
{
char *desc;
pk = node->pkt->pkt.public_key;
keyid_from_pk (pk, subid);
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;
}
}
if (rc)
tty_printf (_("Can't edit this key: %s\n"), g10_errstr (rc));
else
{
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];
/* 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);
changed++;
}
break;
}
}
xfree (s2k);
xfree (dek);
}
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);
err = getkey_byname (NULL, pk, username, 1, &keyblock);
if (err)
goto leave;
err = keydb_get_keyblock (kdh, &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",

View File

@ -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 --*/

View File

@ -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;

634
po/de.po

File diff suppressed because it is too large Load Diff

View File

@ -163,7 +163,9 @@ close_message_fd (ctrl_t ctrl)
{
if (ctrl->server_local->message_fd != -1)
{
#ifdef HAVE_W32CE_SYSTEM
#warning Is this correct for W32/W32CE?
#endif
close (ctrl->server_local->message_fd);
ctrl->server_local->message_fd = -1;
}