summaryrefslogtreecommitdiffstats
path: root/agent
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2007-01-25 09:30:47 +0100
committerWerner Koch <wk@gnupg.org>2007-01-25 09:30:47 +0100
commit6cee3e66c25871a8d94bf0fd22be3579a4d1b775 (patch)
treed1f9bf251aa5ff3c6f0daad99613051f637af809 /agent
parent* gpg.texi, specify-user-id.texi: Only some of the mentions of (diff)
downloadgnupg2-6cee3e66c25871a8d94bf0fd22be3579a4d1b775.tar.xz
gnupg2-6cee3e66c25871a8d94bf0fd22be3579a4d1b775.zip
agent/
* 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.
Diffstat (limited to 'agent')
-rw-r--r--agent/ChangeLog22
-rw-r--r--agent/agent.h7
-rw-r--r--agent/call-pinentry.c24
-rw-r--r--agent/command.c31
-rw-r--r--agent/divert-scd.c2
-rw-r--r--agent/genkey.c62
-rw-r--r--agent/gpg-agent.c6
-rw-r--r--agent/protect-tool.c25
8 files changed, 142 insertions, 37 deletions
diff --git a/agent/ChangeLog b/agent/ChangeLog
index 2a14bda64..110b604ab 100644
--- a/agent/ChangeLog
+++ b/agent/ChangeLog
@@ -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.
diff --git a/agent/agent.h b/agent/agent.h
index 883924cd9..c86ec1e5f 100644
--- a/agent/agent.h
+++ b/agent/agent.h
@@ -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);
diff --git a/agent/call-pinentry.c b/agent/call-pinentry.c
index f22136fd4..bb3b5deb5 100644
--- a/agent/call-pinentry.c
+++ b/agent/call-pinentry.c
@@ -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);
diff --git a/agent/command.c b/agent/command.c
index 63f41c369..8f1f126ed 100644
--- a/agent/command.c
+++ b/agent/command.c
@@ -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)
diff --git a/agent/divert-scd.c b/agent/divert-scd.c
index 49768feed..81b4d7c4b 100644
--- a/agent/divert-scd.c
+++ b/agent/divert-scd.c
@@ -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);
diff --git a/agent/genkey.c b/agent/genkey.c
index a1f9f38f4..1ac7c6624 100644
--- a/agent/genkey.c
+++ b/agent/genkey.c
@@ -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);
diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c
index 75ffb70da..72a4013d6 100644
--- a/agent/gpg-agent.c
+++ b/agent/gpg-agent.c
@@ -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;
diff --git a/agent/protect-tool.c b/agent/protect-tool.c
index 4a0e53d3f..8f974e2da 100644
--- a/agent/protect-tool.c
+++ b/agent/protect-tool.c
@@ -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);