mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-03 12:11:33 +01:00
* agent.h: Add a callback function to the pin_entry_info structure.
* query.c (agent_askpin): Use the callback to check for a correct PIN. Removed the start_err_text argument becuase it is not anymore needed; changed callers. * findkey.c (unprotect): Replace our own check loop by a callback. (try_unprotect_cb): New. * genkey.c (reenter_compare_cb): New. (agent_genkey): Use this callback here. Fixed setting of the pi2 variable and a segv in case of an empty PIN. * divert-scd.c (getpin_cb): Removed some unused stuff and explained what we still have to change.
This commit is contained in:
parent
ccb0bb10e1
commit
469dc1043d
@ -1,3 +1,18 @@
|
||||
2002-06-17 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* agent.h: Add a callback function to the pin_entry_info structure.
|
||||
* query.c (agent_askpin): Use the callback to check for a correct
|
||||
PIN. Removed the start_err_text argument becuase it is not
|
||||
anymore needed; changed callers.
|
||||
* findkey.c (unprotect): Replace our own check loop by a callback.
|
||||
(try_unprotect_cb): New.
|
||||
* genkey.c (reenter_compare_cb): New.
|
||||
(agent_genkey): Use this callback here. Fixed setting of the pi2
|
||||
variable and a segv in case of an empty PIN.
|
||||
|
||||
* divert-scd.c (getpin_cb): Removed some unused stuff and
|
||||
explained what we still have to change.
|
||||
|
||||
2002-06-12 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* gpg-agent.c (main): New option --disable-pth.
|
||||
|
@ -85,6 +85,9 @@ struct pin_entry_info_s {
|
||||
int max_digits; /* max. number of allowed digits allowed*/
|
||||
int max_tries;
|
||||
int failed_tries;
|
||||
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 */
|
||||
const char *cb_errtext; /* used by the cb to displaye a specific error */
|
||||
size_t max_length; /* allocated length of the buffer */
|
||||
char pin[1];
|
||||
};
|
||||
@ -114,8 +117,7 @@ GCRY_SEXP agent_key_from_file (const unsigned char *grip,
|
||||
int agent_key_available (const unsigned char *grip);
|
||||
|
||||
/*-- query.c --*/
|
||||
int agent_askpin (const char *desc_text, const char *err_text,
|
||||
struct pin_entry_info_s *pininfo);
|
||||
int agent_askpin (const char *desc_text, struct pin_entry_info_s *pininfo);
|
||||
int agent_get_passphrase (char **retpass,
|
||||
const char *desc, const char *prompt,
|
||||
const char *errtext);
|
||||
|
@ -166,7 +166,7 @@ encode_md_for_card (const unsigned char *digest, size_t digestlen, int algo,
|
||||
/* Callback used to ask for the PIN which should be set into BUF. The
|
||||
buf has been allocated by the caller and is of size MAXBUF which
|
||||
includes the terminating null. The function should return an UTF-8
|
||||
string with the passphrase, the buffer may optioanlly be padded
|
||||
string with the passphrase, the buffer may optionally be padded
|
||||
with arbitrary characters */
|
||||
static int
|
||||
getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
|
||||
@ -174,35 +174,27 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
|
||||
struct pin_entry_info_s *pi;
|
||||
int rc;
|
||||
int tries = 0;
|
||||
const char *errtext;
|
||||
|
||||
|
||||
assert (!opaque);
|
||||
|
||||
if (maxbuf < 2)
|
||||
return GNUPG_Invalid_Value;
|
||||
|
||||
/* FIXME: keep PI and TRIES in OPAQUE */
|
||||
/* FIXME: keep PI and TRIES in OPAQUE. Actually this is a whole
|
||||
mess becuase we should call the card's verify function from the
|
||||
pinentry check pin CB. */
|
||||
pi = gcry_calloc_secure (1, sizeof (*pi) + 100);
|
||||
pi->max_length = maxbuf-1;
|
||||
pi->min_digits = 0; /* we want a real passphrase */
|
||||
pi->max_digits = 8;
|
||||
pi->max_tries = 3;
|
||||
|
||||
errtext = NULL;
|
||||
do
|
||||
rc = agent_askpin (info, pi);
|
||||
if (!rc)
|
||||
{
|
||||
rc = agent_askpin (info, errtext, pi);
|
||||
if (!rc)
|
||||
{
|
||||
strncpy (buf, pi->pin, maxbuf-1);
|
||||
buf[maxbuf-1] = 0;
|
||||
xfree (pi);
|
||||
return 0;
|
||||
}
|
||||
errtext = pi->min_digits? trans ("Bad PIN") : trans ("Bad Passphrase");
|
||||
strncpy (buf, pi->pin, maxbuf-1);
|
||||
buf[maxbuf-1] = 0;
|
||||
}
|
||||
while ((rc == GNUPG_Bad_Passphrase || rc == GNUPG_Bad_PIN)
|
||||
&& tries++ < 3);
|
||||
xfree (pi);
|
||||
return rc;
|
||||
}
|
||||
|
@ -27,9 +27,17 @@
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "agent.h"
|
||||
|
||||
/* Helper to pass data to the check callback of the unprotect function. */
|
||||
struct try_unprotect_arg_s {
|
||||
const unsigned char *protected_key;
|
||||
unsigned char *unprotected_key;
|
||||
};
|
||||
|
||||
|
||||
|
||||
int
|
||||
agent_write_private_key (const unsigned char *grip,
|
||||
@ -88,16 +96,32 @@ agent_write_private_key (const unsigned char *grip,
|
||||
}
|
||||
|
||||
|
||||
/* Callback function to try the unprotection from the passpharse query
|
||||
code. */
|
||||
static int
|
||||
try_unprotect_cb (struct pin_entry_info_s *pi)
|
||||
{
|
||||
struct try_unprotect_arg_s *arg = pi->check_cb_arg;
|
||||
size_t dummy;
|
||||
|
||||
assert (!arg->unprotected_key);
|
||||
return agent_unprotect (arg->protected_key, pi->pin,
|
||||
&arg->unprotected_key, &dummy);
|
||||
}
|
||||
|
||||
|
||||
/* Unprotect the canconical encoded S-expression key in KEYBUF. GRIP
|
||||
should be the hex encoded keygrip of that key to be used with the
|
||||
cahing mechanism. */
|
||||
static int
|
||||
unprotect (unsigned char **keybuf, const unsigned char *grip)
|
||||
{
|
||||
struct pin_entry_info_s *pi;
|
||||
struct try_unprotect_arg_s arg;
|
||||
int rc, i;
|
||||
unsigned char *result;
|
||||
size_t resultlen;
|
||||
int tries = 0;
|
||||
char hexgrip[40+1];
|
||||
const char *errtext;
|
||||
|
||||
for (i=0; i < 20; i++)
|
||||
sprintf (hexgrip+2*i, "%02X", grip[i]);
|
||||
@ -127,27 +151,19 @@ unprotect (unsigned char **keybuf, const unsigned char *grip)
|
||||
pi->min_digits = 0; /* we want a real passphrase */
|
||||
pi->max_digits = 8;
|
||||
pi->max_tries = 3;
|
||||
pi->check_cb = try_unprotect_cb;
|
||||
arg.protected_key = *keybuf;
|
||||
arg.unprotected_key = NULL;
|
||||
pi->check_cb_arg = &arg;
|
||||
|
||||
errtext = NULL;
|
||||
do
|
||||
rc = agent_askpin (NULL, pi);
|
||||
if (!rc)
|
||||
{
|
||||
rc = agent_askpin (NULL, errtext, pi);
|
||||
if (!rc)
|
||||
{
|
||||
rc = agent_unprotect (*keybuf, pi->pin, &result, &resultlen);
|
||||
if (!rc)
|
||||
{
|
||||
agent_put_cache (hexgrip, pi->pin, 0);
|
||||
xfree (*keybuf);
|
||||
*keybuf = result;
|
||||
xfree (pi);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
errtext = pi->min_digits? trans ("Bad PIN") : trans ("Bad Passphrase");
|
||||
assert (arg.unprotected_key);
|
||||
agent_put_cache (hexgrip, pi->pin, 0);
|
||||
xfree (*keybuf);
|
||||
*keybuf = arg.unprotected_key;
|
||||
}
|
||||
while ((rc == GNUPG_Bad_Passphrase || rc == GNUPG_Bad_PIN)
|
||||
&& tries++ < 3);
|
||||
xfree (pi);
|
||||
return rc;
|
||||
}
|
||||
|
@ -70,6 +70,19 @@ store_key (GCRY_SEXP private, const char *passphrase)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Callback function to compare the first entered PIN with the one
|
||||
currently beeing entered. */
|
||||
static int
|
||||
reenter_compare_cb (struct pin_entry_info_s *pi)
|
||||
{
|
||||
const char *pin1 = pi->check_cb_arg;
|
||||
|
||||
if (!strcmp (pin1, pi->pin))
|
||||
return 0; /* okay */
|
||||
pi->cb_errtext = trans ("does not match - try again");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Generate a new keypair according to the parameters given in
|
||||
@ -91,39 +104,30 @@ agent_genkey (CTRL ctrl, const char *keyparam, size_t keyparamlen,
|
||||
return seterr (Invalid_Data);
|
||||
}
|
||||
|
||||
/* Get the passphrase now, cause key generation may take a while */
|
||||
/* Get the passphrase now, cause key generation may take a while. */
|
||||
{
|
||||
const char *text1 = trans ("Please enter the passphrase to%0A"
|
||||
"to protect your new key");
|
||||
const char *text2 = trans ("Please re-enter this passphrase");
|
||||
const char *nomatch = trans ("does not match - try again");
|
||||
int tries = 0;
|
||||
|
||||
pi = gcry_calloc_secure (2, sizeof (*pi) + 100);
|
||||
pi2 = pi + sizeof *pi;
|
||||
pi2 = pi + (sizeof *pi + 100);
|
||||
pi->max_length = 100;
|
||||
pi->max_tries = 3;
|
||||
pi2->max_length = 100;
|
||||
pi2->max_tries = 3;
|
||||
pi2->check_cb = reenter_compare_cb;
|
||||
pi2->check_cb_arg = pi->pin;
|
||||
|
||||
rc = agent_askpin (text1, NULL, pi);
|
||||
rc = agent_askpin (text1, pi);
|
||||
if (!rc)
|
||||
{
|
||||
do
|
||||
{
|
||||
rc = agent_askpin (text2, tries? nomatch:NULL, pi2);
|
||||
tries++;
|
||||
}
|
||||
while (!rc && tries < 3 && strcmp (pi->pin, pi2->pin));
|
||||
if (!rc && strcmp (pi->pin, pi2->pin))
|
||||
rc = GNUPG_Canceled;
|
||||
}
|
||||
rc = agent_askpin (text2, pi2);
|
||||
if (rc)
|
||||
return rc;
|
||||
if (!*pi->pin)
|
||||
{
|
||||
xfree (pi);
|
||||
pi = NULL; /* use does not want a passphrase */
|
||||
pi = NULL; /* User does not want a passphrase. */
|
||||
}
|
||||
}
|
||||
|
||||
@ -158,7 +162,7 @@ agent_genkey (CTRL ctrl, const char *keyparam, size_t keyparamlen,
|
||||
|
||||
/* store the secret key */
|
||||
log_debug ("storing private key\n");
|
||||
rc = store_key (s_private, pi->pin);
|
||||
rc = store_key (s_private, pi? pi->pin:NULL);
|
||||
xfree (pi); pi = NULL;
|
||||
gcry_sexp_release (s_private);
|
||||
if (rc)
|
||||
|
@ -218,13 +218,12 @@ all_digitsp( const char *s)
|
||||
number here and repeat it as long as we have invalid formed
|
||||
numbers. */
|
||||
int
|
||||
agent_askpin (const char *desc_text, const char *start_err_text,
|
||||
struct pin_entry_info_s *pininfo)
|
||||
agent_askpin (const char *desc_text, struct pin_entry_info_s *pininfo)
|
||||
{
|
||||
int rc;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
struct entry_parm_s parm;
|
||||
const char *errtext = start_err_text;
|
||||
const char *errtext = NULL;
|
||||
|
||||
if (opt.batch)
|
||||
return 0; /* fixme: we should return BAD PIN */
|
||||
@ -261,14 +260,8 @@ agent_askpin (const char *desc_text, const char *start_err_text,
|
||||
if (errtext)
|
||||
{
|
||||
/* fixme: should we show the try count? It must be translated */
|
||||
if (start_err_text)
|
||||
{
|
||||
snprintf (line, DIM(line)-1, "SETERROR %s", errtext);
|
||||
start_err_text = NULL;
|
||||
}
|
||||
else
|
||||
snprintf (line, DIM(line)-1, "SETERROR %s (try %d of %d)",
|
||||
errtext, pininfo->failed_tries+1, pininfo->max_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, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
if (rc)
|
||||
@ -276,25 +269,42 @@ agent_askpin (const char *desc_text, const char *start_err_text,
|
||||
errtext = NULL;
|
||||
}
|
||||
|
||||
rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm, NULL, NULL, NULL, NULL);
|
||||
rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
|
||||
NULL, NULL, NULL, NULL);
|
||||
if (rc == ASSUAN_Too_Much_Data)
|
||||
errtext = pininfo->min_digits? trans ("PIN too long")
|
||||
: trans ("Passphrase too long");
|
||||
else if (rc)
|
||||
return unlock_pinentry (map_assuan_err (rc));
|
||||
if (!errtext && !pininfo->min_digits)
|
||||
return unlock_pinentry (0); /* okay, got a passphrase */
|
||||
if (!errtext && !all_digitsp (pininfo->pin))
|
||||
errtext = trans ("Invalid characters in PIN");
|
||||
if (!errtext && pininfo->max_digits
|
||||
&& strlen (pininfo->pin) > pininfo->max_digits)
|
||||
errtext = trans ("PIN too long");
|
||||
if (!errtext
|
||||
&& strlen (pininfo->pin) < pininfo->min_digits)
|
||||
errtext = trans ("PIN too short");
|
||||
|
||||
if (!errtext && pininfo->min_digits)
|
||||
{
|
||||
/* do some basic checks on the entered PIN. */
|
||||
if (!all_digitsp (pininfo->pin))
|
||||
errtext = trans ("Invalid characters in PIN");
|
||||
else if (pininfo->max_digits
|
||||
&& strlen (pininfo->pin) > pininfo->max_digits)
|
||||
errtext = trans ("PIN too long");
|
||||
else if (strlen (pininfo->pin) < pininfo->min_digits)
|
||||
errtext = trans ("PIN too short");
|
||||
}
|
||||
|
||||
if (!errtext && pininfo->check_cb)
|
||||
{
|
||||
/* More checks by utilizing the optional callback. */
|
||||
pininfo->cb_errtext = NULL;
|
||||
rc = pininfo->check_cb (pininfo);
|
||||
if (rc == -1 && pininfo->cb_errtext)
|
||||
errtext = pininfo->cb_errtext;
|
||||
else if (rc == GNUPG_Bad_Passphrase || rc == GNUPG_Bad_PIN)
|
||||
errtext = (pininfo->min_digits? trans ("Bad PIN")
|
||||
: trans ("Bad Passphrase"));
|
||||
else if (rc)
|
||||
return unlock_pinentry (map_assuan_err (rc));
|
||||
}
|
||||
|
||||
if (!errtext)
|
||||
return unlock_pinentry (0); /* okay, got a PIN */
|
||||
return unlock_pinentry (0); /* okay, got a PIN or passphrase */
|
||||
}
|
||||
|
||||
return unlock_pinentry (pininfo->min_digits? GNUPG_Bad_PIN
|
||||
|
Loading…
x
Reference in New Issue
Block a user