Show passphrase constraints errors as password prompt errors
authorNeal H. Walfield <neal@gnu.org>
Thu, 18 Jun 2015 03:10:47 +0000 (00:10 -0300)
committerNeal H. Walfield <neal@g10code.com>
Mon, 29 Jun 2015 13:53:49 +0000 (15:53 +0200)
* agent/agent.h (check_passphrase_constraints): Add parameter
failed_constraint and remove parameter silent.  Update callers.
* agent/genkey.c (check_passphrase_constraints): Add parameter
failed_constraint and remove parameter silent.  If FAILED_CONSTRAINT
is not NULL and OPT.ENFORCE_PASSPHRASE_CONSTRAINTS is FALSE, save the
error text in *FAILED_CONSTRAINT and don't call take_this_one_anyway
or take_this_one_anyway2.  If FAILED_CONSTRAINT is NULL, act as if
SILENT was set.
(agent_ask_new_passphrase): Change initial_errtext's type from a const
char * to a char *.  Pass it to check_passphrase_constraints.  If it
contains malloc's memory, free it.

--
Signed-off-by: Neal H. Walfield <neal@g10code.com>
Based on a patch provided by Watson Yuuma Sato <yuuma.sato@gmail.com>
in issue 2018.

agent/agent.h
agent/call-pinentry.c
agent/command.c
agent/genkey.c

index fabe99b..407a2bd 100644 (file)
@@ -1,5 +1,6 @@
 /* agent.h - Global definitions for the agent
  * Copyright (C) 2001, 2002, 2003, 2005, 2011 Free Software Foundation, Inc.
+ * Copyright (C) 2015 g10 Code GmbH.
  *
  * This file is part of GnuPG.
  *
@@ -412,7 +413,8 @@ int agent_pkdecrypt (ctrl_t ctrl, const char *desc_text,
                      membuf_t *outbuf, int *r_padding);
 
 /*-- genkey.c --*/
-int check_passphrase_constraints (ctrl_t ctrl, const char *pw, int silent);
+int check_passphrase_constraints (ctrl_t ctrl, const char *pw,
+                                 char **failed_constraint);
 gpg_error_t agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt,
                                       char **r_passphrase);
 int agent_genkey (ctrl_t ctrl, const char *cache_nonce,
index ba40f4d..6f4c95b 100644 (file)
@@ -675,7 +675,7 @@ inq_quality (void *opaque, const char *line)
       else
         {
           percent = estimate_passphrase_quality (pin);
-          if (check_passphrase_constraints (NULL, pin, 1))
+          if (check_passphrase_constraints (NULL, pin, NULL))
             percent = -percent;
           snprintf (numbuf, sizeof numbuf, "%d", percent);
           rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
index a4932ef..a69abc5 100644 (file)
@@ -1,6 +1,7 @@
 /* command.c - gpg-agent command handler
  * Copyright (C) 2001-2011 Free Software Foundation, Inc.
  * Copyright (C) 2001-2013 Werner Koch
+ * Copyright (C) 2015 g10 Code GmbH.
  *
  * This file is part of GnuPG.
  *
@@ -1438,7 +1439,7 @@ cmd_get_passphrase (assuan_context_t ctx, char *line)
   char *p;
   int opt_data, opt_check, opt_no_ask, opt_qualbar;
   int opt_repeat = 0;
-  char *repeat_errtext = NULL;
+  char *entry_errtext = NULL;
 
   if (ctrl->restricted)
     return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
@@ -1522,15 +1523,16 @@ cmd_get_passphrase (assuan_context_t ctx, char *line)
 
     next_try:
       rc = agent_get_passphrase (ctrl, &response, desc, prompt,
-                                 repeat_errtext? repeat_errtext:errtext,
+                                 entry_errtext? entry_errtext:errtext,
                                  opt_qualbar, cacheid, CACHE_MODE_USER);
-      xfree (repeat_errtext);
-      repeat_errtext = NULL;
+      xfree (entry_errtext);
+      entry_errtext = NULL;
       if (!rc)
         {
           int i;
 
-          if (opt_check && check_passphrase_constraints (ctrl, response, 0))
+          if (opt_check
+             && check_passphrase_constraints (ctrl, response, &entry_errtext))
             {
               xfree (response);
               goto next_try;
@@ -1548,9 +1550,9 @@ cmd_get_passphrase (assuan_context_t ctx, char *line)
                 {
                   xfree (response2);
                   xfree (response);
-                  repeat_errtext = try_percent_escape
+                  entry_errtext = try_percent_escape
                     (_("does not match - try again"), NULL);
-                  if (!repeat_errtext)
+                  if (!entry_errtext)
                     {
                       rc = gpg_error_from_syserror ();
                       break;
index 30fc44d..85b8aba 100644 (file)
@@ -1,5 +1,6 @@
 /* genkey.c - Generate a keypair
  * Copyright (C) 2002, 2003, 2004, 2007, 2010 Free Software Foundation, Inc.
+ * Copyright (C) 2015 g10 Code GmbH.
  *
  * This file is part of GnuPG.
  *
@@ -174,10 +175,12 @@ take_this_one_anyway (ctrl_t ctrl, const char *desc)
 
 /* 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.  If SILENT is set, no message are
-   displayed.  */
+   asked to provide a different one.  If FAILED_CONSTRAINT is set, a
+   message describing the problem is returned in
+   *FAILED_CONSTRAINT.  */
 int
-check_passphrase_constraints (ctrl_t ctrl, const char *pw, int silent)
+check_passphrase_constraints (ctrl_t ctrl, const char *pw,
+                             char **failed_constraint)
 {
   gpg_error_t err = 0;
   unsigned int minlen = opt.min_passphrase_len;
@@ -200,11 +203,16 @@ check_passphrase_constraints (ctrl_t ctrl, const char *pw, int silent)
                             "Please confirm that you do not want to "
                             "have any protection on your key."));
 
-      if (silent)
-        return gpg_error (GPG_ERR_INV_PASSPHRASE);
+      err = 1;
+      if (failed_constraint)
+       {
+         if (opt.enforce_passphrase_constraints)
+           *failed_constraint = xstrdup (desc);
+         else
+           err = take_this_one_anyway2 (ctrl, desc,
+                                        _("Yes, protection is not needed"));
+       }
 
-      err = take_this_one_anyway2 (ctrl, desc,
-                                   _("Yes, protection is not needed"));
       goto leave;
     }
 
@@ -212,7 +220,7 @@ check_passphrase_constraints (ctrl_t ctrl, const char *pw, int silent)
      in in silent mode which returns immediately.  */
   if (utf8_charcount (pw) < minlen )
     {
-      if (silent)
+      if (!failed_constraint)
         {
           err = gpg_error (GPG_ERR_INV_PASSPHRASE);
           goto leave;
@@ -231,7 +239,7 @@ check_passphrase_constraints (ctrl_t ctrl, const char *pw, int silent)
 
   if (nonalpha_count (pw) < minnonalpha )
     {
-      if (silent)
+      if (!failed_constraint)
         {
           err = gpg_error (GPG_ERR_INV_PASSPHRASE);
           goto leave;
@@ -257,7 +265,7 @@ check_passphrase_constraints (ctrl_t ctrl, const char *pw, int silent)
   if (*pw && opt.check_passphrase_pattern &&
       check_passphrase_pattern (ctrl, pw))
     {
-      if (silent)
+      if (!failed_constraint)
         {
           err = gpg_error (GPG_ERR_INV_PASSPHRASE);
           goto leave;
@@ -273,7 +281,7 @@ check_passphrase_constraints (ctrl_t ctrl, const char *pw, int silent)
         }
     }
 
-  if (msg1 || msg2 || msg3)
+  if (failed_constraint && (msg1 || msg2 || msg3))
     {
       char *msg;
       size_t n;
@@ -295,9 +303,14 @@ check_passphrase_constraints (ctrl_t ctrl, const char *pw, int silent)
       if (n > 3 && !strcmp (msg + n - 3, "%0A"))
         msg[n-3] = 0;
 
-      /* Show error messages.  */
-      err = take_this_one_anyway (ctrl, msg);
-      xfree (msg);
+      err = 1;
+      if (opt.enforce_passphrase_constraints)
+       *failed_constraint = msg;
+      else
+       {
+         err = take_this_one_anyway (ctrl, msg);
+         xfree (msg);
+       }
     }
 
  leave:
@@ -333,7 +346,8 @@ agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt,
   gpg_error_t err;
   const char *text1 = prompt;
   const char *text2 = _("Please re-enter this passphrase");
-  const char *initial_errtext = NULL;
+  char *initial_errtext = NULL;
+  int initial_errtext_do_free = 0;
   struct pin_entry_info_s *pi, *pi2;
 
   *r_passphrase = NULL;
@@ -371,11 +385,17 @@ agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt,
 
  next_try:
   err = agent_askpin (ctrl, text1, NULL, initial_errtext, pi, NULL, 0);
+  if (initial_errtext_do_free)
+    {
+      xfree (initial_errtext);
+      initial_errtext_do_free = 0;
+    }
   initial_errtext = NULL;
   if (!err)
     {
-      if (check_passphrase_constraints (ctrl, pi->pin, 0))
+      if (check_passphrase_constraints (ctrl, pi->pin, &initial_errtext))
         {
+         initial_errtext_do_free = 1;
           pi->failed_tries = 0;
           pi2->failed_tries = 0;
           goto next_try;