Add option --qualitybar to command GET_PASSPHRASE.
This commit is contained in:
Werner Koch 2009-05-15 11:16:28 +00:00
parent 5e208460a1
commit 002f51031a
9 changed files with 178 additions and 80 deletions

View File

@ -1,3 +1,22 @@
2009-05-15 Werner Koch <wk@g10code.com>
Fix bug #1053.
* agent.h (lookup_ttl_t): New.
* findkey.c (unprotect): Add arg LOOKUP_TTL.
(agent_key_from_file): Ditto.
* pksign.c (agent_pksign_do): Ditto.
* command-ssh.c (ttl_from_sshcontrol): New.
(data_sign): Pass new function to agent_pksign_do.
(search_control_file): Add new arg R_TTL.
2009-05-14 Werner Koch <wk@g10code.com>
* command.c (cmd_get_passphrase): Add option --qualitybar.
* call-pinentry.c (agent_askpin): Factor some code out to ...
(setup_qualitybar): .. new.
(agent_get_passphrase): Add arg WITH_QUALITYBAR and implement it.
2009-04-14 Marcus Brinkmann <marcus@g10code.de>
* call-pinentry.c (agent_get_confirmation): Try SETNOTOK command

View File

@ -201,6 +201,10 @@ typedef enum
cache_mode_t;
/* The type of a function to lookup a TTL by a keygrip. */
typedef int (*lookup_ttl_t)(const char *hexgrip);
/*-- gpg-agent.c --*/
void agent_exit (int rc) JNLIB_GCC_A_NR; /* Also implemented in other tools */
const char *get_agent_socket_name (void);
@ -229,6 +233,7 @@ gpg_error_t agent_key_from_file (ctrl_t ctrl,
const unsigned char *grip,
unsigned char **shadow_info,
cache_mode_t cache_mode,
lookup_ttl_t lookup_ttl,
gcry_sexp_t *result);
gpg_error_t agent_public_key_from_file (ctrl_t ctrl,
const unsigned char *grip,
@ -249,7 +254,7 @@ int agent_askpin (ctrl_t ctrl,
struct pin_entry_info_s *pininfo);
int agent_get_passphrase (ctrl_t ctrl, char **retpass,
const char *desc, const char *prompt,
const char *errtext);
const char *errtext, int with_qualitybar);
int agent_get_confirmation (ctrl_t ctrl, const char *desc, const char *ok,
const char *cancel);
int agent_show_message (ctrl_t ctrl, const char *desc, const char *ok_btn);
@ -270,7 +275,7 @@ void agent_unlock_cache_entry (void **cache_id);
/*-- pksign.c --*/
int agent_pksign_do (ctrl_t ctrl, const char *desc_text,
gcry_sexp_t *signature_sexp,
cache_mode_t cache_mode);
cache_mode_t cache_mode, lookup_ttl_t lookup_ttl);
int agent_pksign (ctrl_t ctrl, const char *desc_text,
membuf_t *outbuf, cache_mode_t cache_mode);

View File

@ -194,8 +194,8 @@ agent_flush_cache (void)
with a maximum lifetime of TTL seconds. If there is already data
under this key, it will be replaced. Using a DATA of NULL deletes
the entry. A TTL of 0 is replaced by the default TTL and a TTL of
-1 set infinite timeout. CACHE_MODE is stored with the cache entry
and used t select different timeouts. */
-1 set infinite timeout. CACHE_MODE is stored with the cache entry
and used to select different timeouts. */
int
agent_put_cache (const char *key, cache_mode_t cache_mode,
const char *data, int ttl)

View File

@ -570,6 +570,59 @@ inq_quality (void *opaque, const char *line)
}
/* Helper for agent_askpin and agent_get_passphrase. */
static int
setup_qualitybar (void)
{
int rc;
char line[ASSUAN_LINELENGTH];
char *tmpstr, *tmpstr2;
const char *tooltip;
/* TRANSLATORS: This string is displayed by Pinentry as the label
for the quality bar. */
tmpstr = try_percent_escape (_("Quality:"), "\t\r\n\f\v");
snprintf (line, DIM(line)-1, "SETQUALITYBAR %s", tmpstr? tmpstr:"");
line[DIM(line)-1] = 0;
xfree (tmpstr);
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
if (rc == 103 /*(Old assuan error code)*/
|| gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
; /* Ignore Unknown Command from old Pinentry versions. */
else if (rc)
return rc;
tmpstr2 = gnupg_get_help_string ("pinentry.qualitybar.tooltip", 0);
if (tmpstr2)
tooltip = tmpstr2;
else
{
/* TRANSLATORS: This string is a tooltip, shown by pinentry when
hovering over the quality bar. Please use an appropriate
string to describe what this is about. The length of the
tooltip is limited to about 900 characters. If you do not
translate this entry, a default english text (see source)
will be used. */
tooltip = _("pinentry.qualitybar.tooltip");
if (!strcmp ("pinentry.qualitybar.tooltip", tooltip))
tooltip = ("The quality of the text entered above.\n"
"Please ask your administrator for "
"details about the criteria.");
}
tmpstr = try_percent_escape (tooltip, "\t\r\n\f\v");
xfree (tmpstr2);
snprintf (line, DIM(line)-1, "SETQUALITYBAR_TT %s", tmpstr? tmpstr:"");
line[DIM(line)-1] = 0;
xfree (tmpstr);
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
if (rc == 103 /*(Old assuan error code)*/
|| gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
; /* Ignore Unknown Command from old pinentry versions. */
else if (rc)
return rc;
return 0;
}
@ -627,51 +680,8 @@ agent_askpin (ctrl_t ctrl,
to the pinentry. */
if (pininfo->with_qualitybar && opt.min_passphrase_len )
{
char *tmpstr, *tmpstr2;
const char *tooltip;
/* TRANSLATORS: This string is displayed by pinentry as the
label for the quality bar. */
tmpstr = try_percent_escape (_("Quality:"), "\t\r\n\f\v");
snprintf (line, DIM(line)-1, "SETQUALITYBAR %s", tmpstr? tmpstr:"");
line[DIM(line)-1] = 0;
xfree (tmpstr);
rc = assuan_transact (entry_ctx, line,
NULL, NULL, NULL, NULL, NULL, NULL);
if (rc == 103 /*(Old assuan error code)*/
|| gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
; /* Ignore Unknown Command from old pinentry versions. */
else if (rc)
return unlock_pinentry (rc);
tmpstr2 = gnupg_get_help_string ("pinentry.qualitybar.tooltip", 0);
if (tmpstr2)
tooltip = tmpstr2;
else
{
/* TRANSLATORS: This string is a tooltip, shown by pinentry
when hovering over the quality bar. Please use an
appropriate string to describe what this is about. The
length of the tooltip is limited to about 900 characters.
If you do not translate this entry, a default english
text (see source) will be used. */
tooltip = _("pinentry.qualitybar.tooltip");
if (!strcmp ("pinentry.qualitybar.tooltip", tooltip))
tooltip = ("The quality of the text entered above.\n"
"Please ask your administrator for "
"details about the criteria.");
}
tmpstr = try_percent_escape (tooltip, "\t\r\n\f\v");
xfree (tmpstr2);
snprintf (line, DIM(line)-1, "SETQUALITYBAR_TT %s", tmpstr? tmpstr:"");
line[DIM(line)-1] = 0;
xfree (tmpstr);
rc = assuan_transact (entry_ctx, line,
NULL, NULL, NULL, NULL, NULL, NULL);
if (rc == 103 /*(Old assuan error code)*/
|| gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
; /* Ignore Unknown Command from old pinentry versions. */
else if (rc)
rc = setup_qualitybar ();
if (rc)
return unlock_pinentry (rc);
}
@ -764,7 +774,7 @@ agent_askpin (ctrl_t ctrl,
int
agent_get_passphrase (ctrl_t ctrl,
char **retpass, const char *desc, const char *prompt,
const char *errtext)
const char *errtext, int with_qualitybar)
{
int rc;
@ -798,6 +808,13 @@ agent_get_passphrase (ctrl_t ctrl,
if (rc)
return unlock_pinentry (rc);
if (with_qualitybar && opt.min_passphrase_len)
{
rc = setup_qualitybar ();
if (rc)
return unlock_pinentry (rc);
}
if (errtext)
{
snprintf (line, DIM(line)-1, "SETERROR %s", errtext);
@ -815,7 +832,7 @@ agent_get_passphrase (ctrl_t ctrl,
assuan_begin_confidential (entry_ctx);
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
for canceled which gets translated to an assuan Cancel error and
not to the code for a user cancel. Fix this here. */

View File

@ -1,5 +1,5 @@
/* command-ssh.c - gpg-agent's ssh-agent emulation layer
* Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
* Copyright (C) 2004, 2005, 2006, 2009 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -710,17 +710,20 @@ open_control_file (FILE **r_fp, int append)
/* Search the file at stream FP from the beginning until a matching
HEXGRIP is found; return success in this case and store true at
DISABLED if the found key has been disabled. */
DISABLED if the found key has been disabled. If R_TTL is not NULL
a specified TTL for that key is stored there. */
static gpg_error_t
search_control_file (FILE *fp, const char *hexgrip, int *disabled)
search_control_file (FILE *fp, const char *hexgrip,
int *r_disabled, int *r_ttl)
{
int c, i;
char *p, line[256];
char *p, *pend, line[256];
long ttl;
assert (strlen (hexgrip) == 40 );
rewind (fp);
*disabled = 0;
*r_disabled = 0;
next_line:
do
{
@ -746,10 +749,10 @@ search_control_file (FILE *fp, const char *hexgrip, int *disabled)
}
while (!*p || *p == '\n' || *p == '#');
*disabled = 0;
*r_disabled = 0;
if (*p == '!')
{
*disabled = 1;
*r_disabled = 1;
for (p++; spacep (p); p++)
;
}
@ -763,7 +766,17 @@ search_control_file (FILE *fp, const char *hexgrip, int *disabled)
return gpg_error (GPG_ERR_BAD_DATA);
}
/* Fixme: Get TTL and flags. */
ttl = strtol (p, &pend, 10);
p = pend;
if (!(spacep (p) || *p == '\n') || ttl < -1)
{
log_error ("invalid TTL value in ssh control file; assuming 0\n");
ttl = 0;
}
if (r_ttl)
*r_ttl = ttl;
/* Here is the place to parse flags if we need them. */
return 0; /* Okay: found it. */
}
@ -788,7 +801,7 @@ add_control_entry (ctrl_t ctrl, const char *hexgrip, int ttl)
if (err)
return err;
err = search_control_file (fp, hexgrip, &disabled);
err = search_control_file (fp, hexgrip, &disabled, NULL);
if (err && gpg_err_code(err) == GPG_ERR_EOF)
{
struct tm *tp;
@ -808,6 +821,29 @@ add_control_entry (ctrl_t ctrl, const char *hexgrip, int ttl)
}
/* Scan the sshcontrol file and return the TTL. */
static int
ttl_from_sshcontrol (const char *hexgrip)
{
FILE *fp;
int disabled, ttl;
if (!hexgrip || strlen (hexgrip) != 40)
return 0; /* Wrong input: Use global default. */
if (open_control_file (&fp, 0))
return 0; /* Error: Use the global default TTL. */
if (search_control_file (fp, hexgrip, &disabled, &ttl)
|| disabled)
ttl = 0; /* Use the global default if not found or disabled. */
fclose (fp);
return ttl;
}
@ -1875,7 +1911,7 @@ ssh_handler_request_identities (ctrl_t ctrl,
hexgrip[40] = 0;
if ( strlen (hexgrip) != 40 )
continue;
if (search_control_file (ctrl_fp, hexgrip, &disabled)
if (search_control_file (ctrl_fp, hexgrip, &disabled, NULL)
|| disabled)
continue;
@ -1972,6 +2008,7 @@ ssh_handler_request_identities (ctrl_t ctrl,
return ret_err;
}
/* This function hashes the data contained in DATA of size DATA_N
according to the message digest algorithm specified by MD_ALGORITHM
and writes the message digest to HASH, which needs to large enough
@ -2017,7 +2054,7 @@ data_sign (ctrl_t ctrl, ssh_signature_encoder_t sig_encoder,
err = agent_pksign_do (ctrl,
_("Please enter the passphrase "
"for the ssh key%0A %c"), &signature_sexp,
CACHE_MODE_SSH);
CACHE_MODE_SSH, ttl_from_sshcontrol);
ctrl->use_auth_call = 0;
if (err)
goto out;

View File

@ -986,7 +986,8 @@ send_back_passphrase (assuan_context_t ctx, int via_data, const char *pw)
}
/* GET_PASSPHRASE [--data] [--check] [--no-ask] [--repeat[=N]] <cache_id>
/* GET_PASSPHRASE [--data] [--check] [--no-ask] [--repeat[=N]]
[--qualitybar] <cache_id>
[<error_message> <prompt> <description>]
This function is usually used to ask for a passphrase to be used
@ -1007,6 +1008,10 @@ send_back_passphrase (assuan_context_t ctx, int via_data, const char *pw)
If the option "--no-ask" is used and the passphrase is not in the
cache the user will not be asked to enter a passphrase but the error
code GPG_ERR_NO_DATA is returned.
If the option "--qualitybar" is used a visual indication of the
entered passphrase quality is shown. (Unless no minimum passphrase
length has been configured.)
*/
static int
@ -1020,7 +1025,8 @@ cmd_get_passphrase (assuan_context_t ctx, char *line)
const char *desc2 = _("Please re-enter this passphrase");
char *p;
void *cache_marker;
int opt_data, opt_check, opt_no_ask, opt_repeat = 0;
int opt_data, opt_check, opt_no_ask, opt_qualbar;
int opt_repeat = 0;
char *repeat_errtext = NULL;
opt_data = has_option (line, "--data");
@ -1034,6 +1040,7 @@ cmd_get_passphrase (assuan_context_t ctx, char *line)
else
opt_repeat = 1;
}
opt_qualbar = has_option (line, "--qualitybar");
line = skip_options (line);
cacheid = line;
@ -1102,7 +1109,8 @@ cmd_get_passphrase (assuan_context_t ctx, char *line)
next_try:
rc = agent_get_passphrase (ctrl, &response, desc, prompt,
repeat_errtext? repeat_errtext:errtext);
repeat_errtext? repeat_errtext:errtext,
opt_qualbar);
xfree (repeat_errtext);
repeat_errtext = NULL;
if (!rc)
@ -1119,7 +1127,7 @@ cmd_get_passphrase (assuan_context_t ctx, char *line)
char *response2;
rc = agent_get_passphrase (ctrl, &response2, desc2, prompt,
errtext);
errtext, 0);
if (rc)
break;
if (strcmp (response2, response))
@ -1265,7 +1273,8 @@ cmd_passwd (assuan_context_t ctx, char *line)
ctrl->in_passwd++;
rc = agent_key_from_file (ctrl, ctrl->server_local->keydesc,
grip, &shadow_info, CACHE_MODE_IGNORE, &s_skey);
grip, &shadow_info, CACHE_MODE_IGNORE, NULL,
&s_skey);
if (rc)
;
else if (!s_skey)

View File

@ -297,11 +297,12 @@ modify_description (const char *in, const char *comment, char **result)
/* Unprotect the canconical encoded S-expression key in KEYBUF. GRIP
should be the hex encoded keygrip of that key to be used with the
caching mechanism. DESC_TEXT may be set to override the default
description used for the pinentry. */
description used for the pinentry. If LOOKUP_TTL is given this
function is used to lookup the default ttl. */
static int
unprotect (ctrl_t ctrl, const char *desc_text,
unsigned char **keybuf, const unsigned char *grip,
cache_mode_t cache_mode)
cache_mode_t cache_mode, lookup_ttl_t lookup_ttl)
{
struct pin_entry_info_s *pi;
struct try_unprotect_arg_s arg;
@ -406,7 +407,8 @@ unprotect (ctrl_t ctrl, const char *desc_text,
return rc;
}
}
agent_put_cache (hexgrip, cache_mode, pi->pin, 0);
agent_put_cache (hexgrip, cache_mode, pi->pin,
lookup_ttl? lookup_ttl (hexgrip) : 0);
xfree (*keybuf);
*keybuf = arg.unprotected_key;
}
@ -488,11 +490,16 @@ read_key_file (const unsigned char *grip, gcry_sexp_t *result)
to a token; in this case an allocated S-expression with the
shadow_info part from the file is stored at SHADOW_INFO.
CACHE_MODE defines now the cache shall be used. DESC_TEXT may be
set to present a custom description for the pinentry. */
set to present a custom description for the pinentry. LOOKUP_TTL
is an optional function to convey a TTL to the cache manager; we do
not simply pass the TTL value because the value is only needed if an
unprotect action was needed and looking up the TTL may have some
overhead (e.g. scanning the sshcontrol file). */
gpg_error_t
agent_key_from_file (ctrl_t ctrl, const char *desc_text,
const unsigned char *grip, unsigned char **shadow_info,
cache_mode_t cache_mode, gcry_sexp_t *result)
cache_mode_t cache_mode, lookup_ttl_t lookup_ttl,
gcry_sexp_t *result)
{
int rc;
unsigned char *buf;
@ -502,7 +509,7 @@ agent_key_from_file (ctrl_t ctrl, const char *desc_text,
*result = NULL;
if (shadow_info)
*shadow_info = NULL;
*shadow_info = NULL;
rc = read_key_file (grip, &s_skey);
if (rc)
@ -563,7 +570,8 @@ agent_key_from_file (ctrl_t ctrl, const char *desc_text,
if (!rc)
{
rc = unprotect (ctrl, desc_text_final, &buf, grip, cache_mode);
rc = unprotect (ctrl, desc_text_final, &buf, grip,
cache_mode, lookup_ttl);
if (rc)
log_error ("failed to unprotect the secret key: %s\n",
gpg_strerror (rc));

View File

@ -66,7 +66,7 @@ agent_pkdecrypt (ctrl_t ctrl, const char *desc_text,
}
rc = agent_key_from_file (ctrl, desc_text,
ctrl->keygrip, &shadow_info,
CACHE_MODE_NORMAL, &s_skey);
CACHE_MODE_NORMAL, NULL, &s_skey);
if (rc)
{
if (gpg_err_code (rc) == GPG_ERR_ENOENT)

View File

@ -125,10 +125,12 @@ do_encode_raw_pkcs1 (const byte *md, size_t mdlen, unsigned int nbits,
/* SIGN whatever information we have accumulated in CTRL and return
the signature S-Expression. */
the signature S-expression. LOOKUP is an optional function to
provide a way for lower layers to ask for the caching TTL. */
int
agent_pksign_do (ctrl_t ctrl, const char *desc_text,
gcry_sexp_t *signature_sexp, cache_mode_t cache_mode)
gcry_sexp_t *signature_sexp,
cache_mode_t cache_mode, lookup_ttl_t lookup_ttl)
{
gcry_sexp_t s_skey = NULL, s_sig = NULL;
unsigned char *shadow_info = NULL;
@ -138,7 +140,8 @@ agent_pksign_do (ctrl_t ctrl, const char *desc_text,
return gpg_error (GPG_ERR_NO_SECKEY);
rc = agent_key_from_file (ctrl, desc_text, ctrl->keygrip,
&shadow_info, cache_mode, &s_skey);
&shadow_info, cache_mode, lookup_ttl,
&s_skey);
if (rc)
{
log_error ("failed to read the secret key\n");
@ -238,7 +241,7 @@ agent_pksign (ctrl_t ctrl, const char *desc_text,
size_t len = 0;
int rc = 0;
rc = agent_pksign_do (ctrl, desc_text, &s_sig, cache_mode);
rc = agent_pksign_do (ctrl, desc_text, &s_sig, cache_mode, NULL);
if (rc)
goto leave;