mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-20 14:37:08 +01:00
Support the SETQUALITYBAR command of recent pinentries.
This commit is contained in:
parent
1151d4d6ae
commit
a6b11ea482
@ -1,3 +1,14 @@
|
|||||||
|
2007-09-18 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* agent.h (struct pin_entry_info_s): Add element WITH_QUALITYBAR.
|
||||||
|
* genkey.c (check_passphrase_constraints): New arg SILENT.
|
||||||
|
Changed all callers.
|
||||||
|
(agent_protect_and_store, agent_genkey): Enable qualitybar.
|
||||||
|
* call-pinentry.c (agent_askpin): Send that option.
|
||||||
|
(unescape_passphrase_string): New.
|
||||||
|
(inq_quality): New.
|
||||||
|
(estimate_passphrase_quality): New.
|
||||||
|
|
||||||
2007-09-14 Marcus Brinkmann <marcus@g10code.de>
|
2007-09-14 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
* call-pinentry.c (agent_popup_message_stop): Implement kill for
|
* call-pinentry.c (agent_popup_message_stop): Implement kill for
|
||||||
|
@ -169,6 +169,7 @@ struct pin_entry_info_s
|
|||||||
int max_digits; /* max. number of allowed digits allowed*/
|
int max_digits; /* max. number of allowed digits allowed*/
|
||||||
int max_tries;
|
int max_tries;
|
||||||
int failed_tries;
|
int failed_tries;
|
||||||
|
int with_qualitybar; /* Set if the quality bar should be displayed. */
|
||||||
int (*check_cb)(struct pin_entry_info_s *); /* CB used to check the PIN */
|
int (*check_cb)(struct pin_entry_info_s *); /* CB used to check the PIN */
|
||||||
void *check_cb_arg; /* optional argument which might be of use in the CB */
|
void *check_cb_arg; /* optional argument which might be of use in the CB */
|
||||||
const char *cb_errtext; /* used by the cb to displaye a specific error */
|
const char *cb_errtext; /* used by the cb to displaye a specific error */
|
||||||
@ -269,7 +270,7 @@ int agent_pkdecrypt (ctrl_t ctrl, const char *desc_text,
|
|||||||
membuf_t *outbuf);
|
membuf_t *outbuf);
|
||||||
|
|
||||||
/*-- genkey.c --*/
|
/*-- genkey.c --*/
|
||||||
int check_passphrase_constraints (ctrl_t ctrl, const char *pw);
|
int check_passphrase_constraints (ctrl_t ctrl, const char *pw, int silent);
|
||||||
int agent_genkey (ctrl_t ctrl,
|
int agent_genkey (ctrl_t ctrl,
|
||||||
const char *keyparam, size_t keyparmlen, membuf_t *outbuf);
|
const char *keyparam, size_t keyparmlen, membuf_t *outbuf);
|
||||||
int agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey);
|
int agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey);
|
||||||
|
@ -413,6 +413,106 @@ all_digitsp( const char *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Return a new malloced string by unescaping the string S. Escaping
|
||||||
|
is percent escaping and '+'/space mapping. A binary Nul will
|
||||||
|
silently be replaced by a 0xFF. Function returns NULL to indicate
|
||||||
|
an out of memory status. PArsing stops at the end of the string or
|
||||||
|
a white space character. */
|
||||||
|
static char *
|
||||||
|
unescape_passphrase_string (const unsigned char *s)
|
||||||
|
{
|
||||||
|
char *buffer, *d;
|
||||||
|
|
||||||
|
buffer = d = xtrymalloc_secure (strlen ((const char*)s)+1);
|
||||||
|
if (!buffer)
|
||||||
|
return NULL;
|
||||||
|
while (*s && !spacep (s))
|
||||||
|
{
|
||||||
|
if (*s == '%' && s[1] && s[2])
|
||||||
|
{
|
||||||
|
s++;
|
||||||
|
*d = xtoi_2 (s);
|
||||||
|
if (!*d)
|
||||||
|
*d = '\xff';
|
||||||
|
d++;
|
||||||
|
s += 2;
|
||||||
|
}
|
||||||
|
else if (*s == '+')
|
||||||
|
{
|
||||||
|
*d++ = ' ';
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*d++ = *s++;
|
||||||
|
}
|
||||||
|
*d = 0;
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Estimate the quality of the passphrase PW and return a value in the
|
||||||
|
range 0..100. */
|
||||||
|
static int
|
||||||
|
estimate_passphrase_quality (const char *pw)
|
||||||
|
{
|
||||||
|
int goodlength = opt.min_passphrase_len + opt.min_passphrase_len/3;
|
||||||
|
int length;
|
||||||
|
const char *s;
|
||||||
|
|
||||||
|
if (goodlength < 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (length = 0, s = pw; *s; s++)
|
||||||
|
if (!spacep (s))
|
||||||
|
length ++;
|
||||||
|
|
||||||
|
if (length > goodlength)
|
||||||
|
return 100;
|
||||||
|
return ((length*10) / goodlength)*10;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Handle the QUALITY inquiry. */
|
||||||
|
static int
|
||||||
|
inq_quality (void *opaque, const char *line)
|
||||||
|
{
|
||||||
|
assuan_context_t ctx = opaque;
|
||||||
|
char *pin;
|
||||||
|
int rc;
|
||||||
|
int percent;
|
||||||
|
char numbuf[20];
|
||||||
|
|
||||||
|
if (!strncmp (line, "QUALITY", 7) && (line[7] == ' ' || !line[7]))
|
||||||
|
{
|
||||||
|
line += 7;
|
||||||
|
while (*line == ' ')
|
||||||
|
line++;
|
||||||
|
|
||||||
|
pin = unescape_passphrase_string (line);
|
||||||
|
if (!pin)
|
||||||
|
rc = gpg_error_from_syserror ();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
percent = estimate_passphrase_quality (pin);
|
||||||
|
if (check_passphrase_constraints (NULL, pin, 1))
|
||||||
|
percent = -percent;
|
||||||
|
snprintf (numbuf, sizeof numbuf, "%d", percent);
|
||||||
|
rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
|
||||||
|
xfree (pin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log_error ("unsupported inquiry `%s' from pinentry\n", line);
|
||||||
|
rc = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Call the Entry and ask for the PIN. We do check for a valid PIN
|
/* Call the Entry and ask for the PIN. We do check for a valid PIN
|
||||||
number here and repeat it as long as we have invalid formed
|
number here and repeat it as long as we have invalid formed
|
||||||
@ -463,6 +563,16 @@ agent_askpin (ctrl_t ctrl,
|
|||||||
if (rc)
|
if (rc)
|
||||||
return unlock_pinentry (rc);
|
return unlock_pinentry (rc);
|
||||||
|
|
||||||
|
/* If a passphrase quality indicator has been requested and a
|
||||||
|
minimum passphrase length has not been disabled, send the command
|
||||||
|
to the pinentry. */
|
||||||
|
if (pininfo->with_qualitybar && opt.min_passphrase_len )
|
||||||
|
{
|
||||||
|
rc = assuan_transact (entry_ctx, "SETQUALITYBAR",
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
|
if (rc)
|
||||||
|
return unlock_pinentry (rc);
|
||||||
|
}
|
||||||
|
|
||||||
if (initial_errtext)
|
if (initial_errtext)
|
||||||
{
|
{
|
||||||
@ -497,7 +607,7 @@ agent_askpin (ctrl_t ctrl,
|
|||||||
}
|
}
|
||||||
|
|
||||||
rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
|
rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
|
||||||
NULL, NULL, NULL, NULL);
|
inq_quality, entry_ctx, NULL, NULL);
|
||||||
/* Most pinentries out in the wild return the old Assuan error code
|
/* Most pinentries out in the wild return the old Assuan error code
|
||||||
for canceled which gets translated to an assuan Cancel error and
|
for canceled which gets translated to an assuan Cancel error and
|
||||||
not to the code for a user cancel. Fix this here. */
|
not to the code for a user cancel. Fix this here. */
|
||||||
|
@ -912,7 +912,7 @@ cmd_get_passphrase (assuan_context_t ctx, char *line)
|
|||||||
}
|
}
|
||||||
while (!rc
|
while (!rc
|
||||||
&& opt_check
|
&& opt_check
|
||||||
&& check_passphrase_constraints (ctrl, response));
|
&& check_passphrase_constraints (ctrl, response, 0));
|
||||||
|
|
||||||
if (!rc)
|
if (!rc)
|
||||||
{
|
{
|
||||||
|
@ -168,9 +168,10 @@ take_this_one_anyway (ctrl_t ctrl, const char *desc)
|
|||||||
|
|
||||||
/* Check whether the passphrase PW is suitable. Returns 0 if the
|
/* 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
|
passphrase is suitable and true if it is not and the user should be
|
||||||
asked to provide a different one. */
|
asked to provide a different one. If SILENT is set, no message are
|
||||||
|
displayed. */
|
||||||
int
|
int
|
||||||
check_passphrase_constraints (ctrl_t ctrl, const char *pw)
|
check_passphrase_constraints (ctrl_t ctrl, const char *pw, int silent)
|
||||||
{
|
{
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
unsigned int minlen = opt.min_passphrase_len;
|
unsigned int minlen = opt.min_passphrase_len;
|
||||||
@ -181,7 +182,12 @@ check_passphrase_constraints (ctrl_t ctrl, const char *pw)
|
|||||||
|
|
||||||
if (utf8_charcount (pw) < minlen )
|
if (utf8_charcount (pw) < minlen )
|
||||||
{
|
{
|
||||||
char *desc = xtryasprintf
|
char *desc;
|
||||||
|
|
||||||
|
if (silent)
|
||||||
|
return gpg_error (GPG_ERR_INV_PASSPHRASE);
|
||||||
|
|
||||||
|
desc = xtryasprintf
|
||||||
( ngettext ("Warning: You have entered a passphrase that%%0A"
|
( ngettext ("Warning: You have entered a passphrase that%%0A"
|
||||||
"is obviously not secure. A passphrase should%%0A"
|
"is obviously not secure. A passphrase should%%0A"
|
||||||
"be at least %u character long.",
|
"be at least %u character long.",
|
||||||
@ -198,7 +204,12 @@ check_passphrase_constraints (ctrl_t ctrl, const char *pw)
|
|||||||
|
|
||||||
if (nonalpha_count (pw) < minnonalpha )
|
if (nonalpha_count (pw) < minnonalpha )
|
||||||
{
|
{
|
||||||
char *desc = xtryasprintf
|
char *desc;
|
||||||
|
|
||||||
|
if (silent)
|
||||||
|
return gpg_error (GPG_ERR_INV_PASSPHRASE);
|
||||||
|
|
||||||
|
desc = xtryasprintf
|
||||||
( ngettext ("Warning: You have entered a passphrase that%%0A"
|
( ngettext ("Warning: You have entered a passphrase that%%0A"
|
||||||
"is obviously not secure. A passphrase should%%0A"
|
"is obviously not secure. A passphrase should%%0A"
|
||||||
"contain at least %u digit or special character.",
|
"contain at least %u digit or special character.",
|
||||||
@ -226,6 +237,9 @@ check_passphrase_constraints (ctrl_t ctrl, const char *pw)
|
|||||||
"is obviously not secure. A passphrase may not%0A"
|
"is obviously not secure. A passphrase may not%0A"
|
||||||
"be a known term or match certain pattern.");
|
"be a known term or match certain pattern.");
|
||||||
|
|
||||||
|
if (silent)
|
||||||
|
return gpg_error (GPG_ERR_INV_PASSPHRASE);
|
||||||
|
|
||||||
err = take_this_one_anyway (ctrl, desc);
|
err = take_this_one_anyway (ctrl, desc);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
@ -242,6 +256,9 @@ check_passphrase_constraints (ctrl_t ctrl, const char *pw)
|
|||||||
"Please confirm that you do not want to "
|
"Please confirm that you do not want to "
|
||||||
"have any protection on your key."));
|
"have any protection on your key."));
|
||||||
|
|
||||||
|
if (silent)
|
||||||
|
return gpg_error (GPG_ERR_INV_PASSPHRASE);
|
||||||
|
|
||||||
err = take_this_one_anyway2 (ctrl, desc,
|
err = take_this_one_anyway2 (ctrl, desc,
|
||||||
_("Yes, protection is not needed"));
|
_("Yes, protection is not needed"));
|
||||||
if (err)
|
if (err)
|
||||||
@ -296,6 +313,7 @@ agent_genkey (ctrl_t ctrl, const char *keyparam, size_t keyparamlen,
|
|||||||
pi2 = pi + (sizeof *pi + 100);
|
pi2 = pi + (sizeof *pi + 100);
|
||||||
pi->max_length = 100;
|
pi->max_length = 100;
|
||||||
pi->max_tries = 3;
|
pi->max_tries = 3;
|
||||||
|
pi->with_qualitybar = 1;
|
||||||
pi2->max_length = 100;
|
pi2->max_length = 100;
|
||||||
pi2->max_tries = 3;
|
pi2->max_tries = 3;
|
||||||
pi2->check_cb = reenter_compare_cb;
|
pi2->check_cb = reenter_compare_cb;
|
||||||
@ -306,7 +324,7 @@ agent_genkey (ctrl_t ctrl, const char *keyparam, size_t keyparamlen,
|
|||||||
initial_errtext = NULL;
|
initial_errtext = NULL;
|
||||||
if (!rc)
|
if (!rc)
|
||||||
{
|
{
|
||||||
if (check_passphrase_constraints (ctrl, pi->pin))
|
if (check_passphrase_constraints (ctrl, pi->pin, 0))
|
||||||
{
|
{
|
||||||
pi->failed_tries = 0;
|
pi->failed_tries = 0;
|
||||||
pi2->failed_tries = 0;
|
pi2->failed_tries = 0;
|
||||||
@ -417,6 +435,7 @@ agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey)
|
|||||||
pi2 = pi + (sizeof *pi + 100);
|
pi2 = pi + (sizeof *pi + 100);
|
||||||
pi->max_length = 100;
|
pi->max_length = 100;
|
||||||
pi->max_tries = 3;
|
pi->max_tries = 3;
|
||||||
|
pi->with_qualitybar = 1;
|
||||||
pi2->max_length = 100;
|
pi2->max_length = 100;
|
||||||
pi2->max_tries = 3;
|
pi2->max_tries = 3;
|
||||||
pi2->check_cb = reenter_compare_cb;
|
pi2->check_cb = reenter_compare_cb;
|
||||||
@ -427,7 +446,7 @@ agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey)
|
|||||||
initial_errtext = NULL;
|
initial_errtext = NULL;
|
||||||
if (!rc)
|
if (!rc)
|
||||||
{
|
{
|
||||||
if (check_passphrase_constraints (ctrl, pi->pin))
|
if (check_passphrase_constraints (ctrl, pi->pin, 0))
|
||||||
{
|
{
|
||||||
pi->failed_tries = 0;
|
pi->failed_tries = 0;
|
||||||
pi2->failed_tries = 0;
|
pi2->failed_tries = 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user