* protect-tool.c (get_passphrase): New arg OPT_CHECK.
	(get_new_passphrase): Enable OTP_CHECK on the first call.
	* command.c (cmd_get_passphrase): Implement option --check.

	* gpg-agent.c (MIN_PASSPHRASE_LEN): New
	(parse_rereadable_options): New option 	--min-passphrase-len.
	* genkey.c (check_passphrase_constraints): New.
	(agent_genkey, agent_protect_and_store): Call new function.  Fix
	memory leak.

	* call-pinentry.c (agent_askpin): Allow translation of the displayed
	error message.
	(agent_popup_message_start): Remove arg CANCEL_BTN.
	(popup_message_thread): Use --one-button option.

	* command.c (cmd_passwd): Now that we don't distinguish between
	assuan and regular error codes we can jump to the end on error.

common/
	* simple-pwquery.c (simple_pwquery): New arg OPT_CHECK.
This commit is contained in:
Werner Koch 2007-01-25 08:30:47 +00:00
parent 09bc5abc92
commit 6cee3e66c2
16 changed files with 996 additions and 803 deletions

5
NEWS
View File

@ -8,6 +8,11 @@ Noteworthy changes in version 2.0.2 (unreleased)
prompt for a new passphrase to be repeated. This is useful to help
memorize a new passphrase. The default is 1 repetition.
* Using a PIN pad does now also for for the signing key.
* A warning is displayed if a new passphrase is too short. New
option --min-passphrase-len defaults to 8.
Noteworthy changes in version 2.0.1 (2006-11-28)
------------------------------------------------

5
TODO
View File

@ -118,3 +118,8 @@
* Cleanup m4/ on next gettext update
There is at least one couple of duplicate files: inttype[_-]h.m4.
* UTF-8
** we need a function to count characters.
Something like utf8_strlen. This is needed to correclty count the
lengtgh of a passphrase.

View File

@ -1,3 +1,25 @@
2007-01-25 Werner Koch <wk@g10code.com>
* protect-tool.c (get_passphrase): New arg OPT_CHECK.
(get_new_passphrase): Enable OTP_CHECK on the first call.
* command.c (cmd_get_passphrase): Implement option --check.
2007-01-24 Werner Koch <wk@g10code.com>
* gpg-agent.c (MIN_PASSPHRASE_LEN): New
(parse_rereadable_options): New option --min-passphrase-len.
* genkey.c (check_passphrase_constraints): New.
(agent_genkey, agent_protect_and_store): Call new function. Fix
memory leak.
* call-pinentry.c (agent_askpin): Allow translation of the displayed
error message.
(agent_popup_message_start): Remove arg CANCEL_BTN.
(popup_message_thread): Use --one-button option.
* command.c (cmd_passwd): Now that we don't distinguish between
assuan and regular error codes we can jump to the end on error.
2006-12-07 David Shaw <dshaw@jabberwocky.com>
* Makefile.am: Link to iconv for jnlib dependency.

View File

@ -78,6 +78,8 @@ struct
unsigned long max_cache_ttl; /* Default. */
unsigned long max_cache_ttl_ssh; /* for SSH. */
/* The require minmum length of a passphrase. */
unsigned int min_passphrase_len;
int running_detached; /* We are running detached from the tty. */
@ -222,8 +224,8 @@ int agent_get_passphrase (ctrl_t ctrl, char **retpass,
const char *errtext);
int agent_get_confirmation (ctrl_t ctrl, const char *desc, const char *ok,
const char *cancel);
int agent_popup_message_start (ctrl_t ctrl, const char *desc,
const char *ok_btn, const char *cancel_btn);
int agent_popup_message_start (ctrl_t ctrl,
const char *desc, const char *ok_btn);
void agent_popup_message_stop (ctrl_t ctrl);
@ -249,6 +251,7 @@ int agent_pkdecrypt (ctrl_t ctrl, const char *desc_text,
membuf_t *outbuf);
/*-- genkey.c --*/
int check_passphrase_constraints (ctrl_t ctrl, const char *pw);
int agent_genkey (ctrl_t ctrl,
const char *keyparam, size_t keyparmlen, membuf_t *outbuf);
int agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey);

View File

@ -434,8 +434,10 @@ agent_askpin (ctrl_t ctrl,
if (errtext)
{
/* fixme: should we show the try count? It must be translated */
snprintf (line, DIM(line)-1, "SETERROR %s (try %d of %d)",
/* TRANLATORS: The string is appended to an error message in
the pinentry. The %s is the actual error message, the
two %d give the current and maximum number of tries. */
snprintf (line, DIM(line)-1, _("SETERROR %s (try %d of %d)"),
errtext, pininfo->failed_tries+1, pininfo->max_tries);
line[DIM(line)-1] = 0;
rc = assuan_transact (entry_ctx, line,
@ -627,7 +629,12 @@ agent_get_confirmation (ctrl_t ctrl,
static void *
popup_message_thread (void *arg)
{
assuan_transact (entry_ctx, "CONFIRM", NULL, NULL, NULL, NULL, NULL, NULL);
/* We use the --one-button hack instead of the MESSAGE command to
allow the use of old Pinentries. Those old Pinentries will then
show an additional Cancel button but that is mostly a visual
annoyance. */
assuan_transact (entry_ctx, "CONFIRM --one-button",
NULL, NULL, NULL, NULL, NULL, NULL);
popup_finished = 1;
return NULL;
}
@ -640,8 +647,7 @@ popup_message_thread (void *arg)
system modal and all other attempts to use the pinentry will fail
(after a timeout). */
int
agent_popup_message_start (ctrl_t ctrl, const char *desc,
const char *ok_btn, const char *cancel_btn)
agent_popup_message_start (ctrl_t ctrl, const char *desc, const char *ok_btn)
{
int rc;
char line[ASSUAN_LINELENGTH];
@ -668,14 +674,6 @@ agent_popup_message_start (ctrl_t ctrl, const char *desc,
if (rc)
return unlock_pinentry (rc);
}
if (cancel_btn)
{
snprintf (line, DIM(line)-1, "SETCANCEL %s", cancel_btn);
line[DIM(line)-1] = 0;
rc = assuan_transact (entry_ctx, line, NULL,NULL,NULL,NULL,NULL,NULL);
if (rc)
return unlock_pinentry (rc);
}
tattr = pth_attr_new();
pth_attr_set (tattr, PTH_ATTR_JOINABLE, 1);

View File

@ -1,5 +1,6 @@
/* command.c - gpg-agent command handler
* Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
* Copyright (C) 2001, 2002, 2003, 2004, 2005,
* 2006 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -804,7 +805,8 @@ send_back_passphrase (assuan_context_t ctx, int via_data, const char *pw)
}
/* GET_PASSPHRASE [--data] <cache_id> [<error_message> <prompt> <description>]
/* GET_PASSPHRASE [--data] [--check] <cache_id>
[<error_message> <prompt> <description>]
This function is usually used to ask for a passphrase to be used
for conventional encryption, but may also be used by programs which
@ -816,6 +818,10 @@ send_back_passphrase (assuan_context_t ctx, int via_data, const char *pw)
If the option "--data" is used the passphrase is returned by usual
data lines and not on the okay line.
If the option "--check" is used the passphrase constraints checks as
implemented by gpg-agent are applied. A check is not done if the
passphrase has been found in the cache.
*/
static int
@ -828,9 +834,10 @@ cmd_get_passphrase (assuan_context_t ctx, char *line)
char *cacheid = NULL, *desc = NULL, *prompt = NULL, *errtext = NULL;
char *p;
void *cache_marker;
int opt_data;
int opt_data, opt_check;
opt_data = has_option (line, "--data");
opt_check = has_option (line, "--check");
line = skip_options (line);
cacheid = line;
@ -857,7 +864,7 @@ cmd_get_passphrase (assuan_context_t ctx, char *line)
desc = p;
p = strchr (desc, ' ');
if (p)
*p = 0; /* ignore garbage */
*p = 0; /* Ignore trailing garbage. */
}
}
}
@ -895,7 +902,16 @@ cmd_get_passphrase (assuan_context_t ctx, char *line)
if (desc)
plus_to_blank (desc);
rc = agent_get_passphrase (ctrl, &response, desc, prompt, errtext);
response = NULL;
do
{
xfree (response);
rc = agent_get_passphrase (ctrl, &response, desc, prompt, errtext);
}
while (!rc
&& opt_check
&& check_passphrase_constraints (ctrl, response));
if (!rc)
{
if (cacheid)
@ -1019,8 +1035,7 @@ cmd_passwd (assuan_context_t ctx, char *line)
rc = parse_keygrip (ctx, line, grip);
if (rc)
return rc; /* we can't jump to leave because this is already an
Assuan error code. */
goto leave;
rc = agent_key_from_file (ctrl, ctrl->server_local->keydesc,
grip, &shadow_info, CACHE_MODE_IGNORE, &s_skey);
@ -1036,6 +1051,8 @@ cmd_passwd (assuan_context_t ctx, char *line)
xfree (ctrl->server_local->keydesc);
ctrl->server_local->keydesc = NULL;
leave:
gcry_sexp_release (s_skey);
xfree (shadow_info);
if (rc)

View File

@ -237,7 +237,7 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
}
else if (maxbuf == 1) /* Open the pinentry. */
{
rc = agent_popup_message_start (ctrl, info, NULL, NULL);
rc = agent_popup_message_start (ctrl, info, NULL);
}
else
rc = gpg_error (GPG_ERR_INV_VALUE);

View File

@ -71,6 +71,43 @@ store_key (gcry_sexp_t private, const char *passphrase, int force)
return rc;
}
/* Check whether the passphrase PW is suitable. Returns 0 if the
passphrase is suitable and true if it is not and the user should be
asked to provide a different one. */
int
check_passphrase_constraints (ctrl_t ctrl, const char *pw)
{
gpg_error_t err;
unsigned int minlen = opt.min_passphrase_len;
if (!pw)
pw = "";
if (strlen (pw) < minlen ) /* FIXME: should be an utf-8 length. */
{
char *desc = xtryasprintf
( ngettext (_("Warning: You have entered a passphrase that%%0A"
"is obviously not secure. A passphrase should%%0A"
"be at least %u character long."),
_("Warning: You have entered a passphrase that%%0A"
"is obviously not secure. A passphrase should%%0A"
"be at least %u characters long."), minlen), minlen );
if (!desc)
return gpg_error_from_syserror ();
err = agent_get_confirmation (ctrl, desc,
_("Take this one anyway"),
_("Enter new passphrase"));
xfree (desc);
if (err)
return err;
}
return 0;
}
/* Callback function to compare the first entered PIN with the one
currently being entered. */
static int
@ -125,6 +162,12 @@ agent_genkey (ctrl_t ctrl, const char *keyparam, size_t keyparamlen,
initial_errtext = NULL;
if (!rc)
{
if (check_passphrase_constraints (ctrl, pi->pin))
{
pi->failed_tries = 0;
pi2->failed_tries = 0;
goto next_try;
}
rc = agent_askpin (ctrl, text2, NULL, NULL, pi2);
if (rc == -1)
{ /* The re-entered one did not match and the user did not
@ -134,7 +177,11 @@ agent_genkey (ctrl_t ctrl, const char *keyparam, size_t keyparamlen,
}
}
if (rc)
return rc;
{
xfree (pi);
return rc;
}
if (!*pi->pin)
{
xfree (pi);
@ -230,8 +277,15 @@ agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey)
next_try:
rc = agent_askpin (ctrl, text1, NULL, initial_errtext, pi);
initial_errtext = NULL;
if (!rc)
{
if (check_passphrase_constraints (ctrl, pi->pin))
{
pi->failed_tries = 0;
pi2->failed_tries = 0;
goto next_try;
}
rc = agent_askpin (ctrl, text2, NULL, NULL, pi2);
if (rc == -1)
{ /* The re-entered one did not match and the user did not
@ -241,7 +295,11 @@ agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey)
}
}
if (rc)
return rc;
{
xfree (pi);
return rc;
}
if (!*pi->pin)
{
xfree (pi);

View File

@ -88,6 +88,7 @@ enum cmd_and_opt_values
oDefCacheTTLSSH,
oMaxCacheTTL,
oMaxCacheTTLSSH,
oMinPassphraseLen,
oUseStandardSocket,
oNoUseStandardSocket,
@ -148,6 +149,7 @@ static ARGPARSE_OPTS opts[] = {
{ oDefCacheTTLSSH, "default-cache-ttl-ssh", 4, "@" },
{ oMaxCacheTTL, "max-cache-ttl", 4, "@" },
{ oMaxCacheTTLSSH, "max-cache-ttl-ssh", 4, "@" },
{ oMinPassphraseLen, "min-passphrase-len", 4, "@" },
{ oIgnoreCacheForSigning, "ignore-cache-for-signing", 0,
N_("do not use the PIN cache when signing")},
{ oAllowMarkTrusted, "allow-mark-trusted", 0,
@ -164,6 +166,7 @@ static ARGPARSE_OPTS opts[] = {
#define DEFAULT_CACHE_TTL (10*60) /* 10 minutes */
#define DEFAULT_CACHE_TTL_SSH (30*60) /* 30 minutes */
#define MAX_CACHE_TTL (120*60) /* 2 hours */
#define MIN_PASSPHRASE_LEN (8)
/* flag to indicate that a shutdown was requested */
@ -403,6 +406,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
opt.def_cache_ttl_ssh = DEFAULT_CACHE_TTL_SSH;
opt.max_cache_ttl = MAX_CACHE_TTL;
opt.max_cache_ttl_ssh = MAX_CACHE_TTL;
opt.min_passphrase_len = MIN_PASSPHRASE_LEN;
opt.ignore_cache_for_signing = 0;
opt.allow_mark_trusted = 0;
opt.disable_scdaemon = 0;
@ -441,6 +445,8 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
case oMaxCacheTTL: opt.max_cache_ttl = pargs->r.ret_ulong; break;
case oMaxCacheTTLSSH: opt.max_cache_ttl_ssh = pargs->r.ret_ulong; break;
case oMinPassphraseLen: opt.min_passphrase_len = pargs->r.ret_ulong; break;
case oIgnoreCacheForSigning: opt.ignore_cache_for_signing = 1; break;
case oAllowMarkTrusted: opt.allow_mark_trusted = 1; break;

View File

@ -1,5 +1,5 @@
/* protect-tool.c - A tool to test the secret key protection
* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -97,7 +97,7 @@ static const char *opt_passphrase;
static char *opt_prompt;
static int opt_status_msg;
static char *get_passphrase (int promptno);
static char *get_passphrase (int promptno, int opt_check);
static char *get_new_passphrase (int promptno);
static void release_passphrase (char *pw);
static int store_private_key (const unsigned char *grip,
@ -363,7 +363,7 @@ read_and_protect (const char *fname)
if (!key)
return;
pw = get_passphrase (1);
pw = get_passphrase (1, 0);
rc = agent_protect (key, pw, &result, &resultlen);
release_passphrase (pw);
xfree (key);
@ -401,7 +401,7 @@ read_and_unprotect (const char *fname)
if (!key)
return;
rc = agent_unprotect (key, (pw=get_passphrase (1)), &result, &resultlen);
rc = agent_unprotect (key, (pw=get_passphrase (1, 0)), &result, &resultlen);
release_passphrase (pw);
xfree (key);
if (rc)
@ -684,7 +684,7 @@ import_p12_file (const char *fname)
if (!buf)
return;
kparms = p12_parse ((unsigned char*)buf, buflen, (pw=get_passphrase (2)),
kparms = p12_parse ((unsigned char*)buf, buflen, (pw=get_passphrase (2, 0)),
import_p12_cert_cb, NULL);
release_passphrase (pw);
xfree (buf);
@ -898,7 +898,7 @@ export_p12_file (const char *fname)
unsigned char *tmpkey;
size_t tmplen;
rc = agent_unprotect (key, (pw=get_passphrase (1)), &tmpkey, &tmplen);
rc = agent_unprotect (key, (pw=get_passphrase (1, 0)), &tmpkey, &tmplen);
release_passphrase (pw);
if (rc)
{
@ -1162,10 +1162,11 @@ agent_exit (int rc)
3 = for protecting a new pkcs#12 object
4 = for protecting an imported pkcs#12 in our system
5 = reenter the passphrase
When adding 100 to the values, a "does not match - try again" errro message is shown.
When adding 100 to the values, a "does not match - try again" error
message is shown.
*/
static char *
get_passphrase (int promptno)
get_passphrase (int promptno, int opt_check)
{
char *pw;
int err;
@ -1219,7 +1220,7 @@ get_passphrase (int promptno)
pw = simple_pwquery (NULL,
error_msgno == 1? _("does not match - try again"):NULL,
_("Passphrase:"), desc, &err);
_("Passphrase:"), desc, opt_check, &err);
#ifdef ENABLE_NLS
if (orig_codeset)
@ -1251,16 +1252,16 @@ get_new_passphrase (int promptno)
char *pw;
int i, secondpromptno;
pw = get_passphrase (promptno);
pw = get_passphrase (promptno, 1);
if (!pw)
return NULL; /* Canceled. */
if (!*pw)
return pw; /* Empty passphrase - no need to as for repeating it. */
return pw; /* Empty passphrase - no need to ask for repeating it. */
secondpromptno = 5;
for (i=0; i < 3; i++)
{
char *pw2 = get_passphrase (secondpromptno);
char *pw2 = get_passphrase (secondpromptno, 0);
if (!pw2)
{
xfree (pw);

View File

@ -1,3 +1,7 @@
2007-01-25 Werner Koch <wk@g10code.com>
* simple-pwquery.c (simple_pwquery): New arg OPT_CHECK.
2006-12-13 David Shaw <dshaw@jabberwocky.com>
* Makefile.am (AM_CPPFLAGS): Include intl/ so we can reference the

View File

@ -334,6 +334,11 @@ Set the maximum time a cache entry used for SSH keys is valid to @var{n}
seconds. After this time a cache entry will get expired even if it has
been accessed recently. The default are 2 hours (7200 seconds).
@item --min-passphrase-len @var{n}
@opindex min-passphrase-len
Set the minimal length of a passphrase. When entereing a new passphrase
shorter than this value a warning will be displayed. Defaults to 8.
@item --pinentry-program @var{filename}
@opindex pinentry-program
Use program @var{filename} as the PIN entry. The default is installation
@ -972,7 +977,7 @@ special handling of passphrases. This command uses a syntax which helps
clients to use the agent with minimum effort.
@example
GET_PASSPHRASE [--data] @var{cache_id} [@var{error_message} @var{prompt} @var{description}]
GET_PASSPHRASE [--data] [--check] @var{cache_id} [@var{error_message} @var{prompt} @var{description}]
@end example
@var{cache_id} is expected to be a string used to identify a cached
@ -999,6 +1004,10 @@ limited by the maximum length of a command. If the option
@option{--data} is used, the passphrase is not returned on the OK line
but by regular data lines; this is the preferred method.
If the option @option{--check} is used, the standard passphrase
constraints checks are applied. A check is not done if the passphrase
has been found in the cache.
@example
CLEAR_PASSPHRASE @var{cache_id}
@end example

1589
po/de.po

File diff suppressed because it is too large Load Diff

View File

@ -491,7 +491,7 @@ pincb (void *arg, const char *prompt, char **pinvalue)
/* pin = simple_pwquery (NULL, NULL, prompt, */
/* "We need the admin's PIN to store the key on the card", */
/* NULL); */
/* 0, NULL); */
/* if (!pin) */
/* return gpg_error (GPG_ERR_CANCELED); */

View File

@ -449,7 +449,7 @@ main (int argc, char **argv)
" entire line to it as arguments.\n"
"/showdef Print all definitions.\n"
"/cleardef Delete all definitions.\n"
"/sendfd FILE MODE Open FILE and pass descripor to server.\n"
"/sendfd FILE MODE Open FILE and pass descriptor to server.\n"
"/recvfd Receive FD from server and print. \n"
"/help Print this help.");
}

View File

@ -485,7 +485,7 @@ confucius_get_pass (const char *cacheid, int again, int *canceled)
pw = simple_pwquery (cacheid,
again ? _("does not match - try again"):NULL,
_("Passphrase:"), NULL, &err);
_("Passphrase:"), NULL, 0, &err);
#ifdef ENABLE_NLS
if (orig_codeset)