1
0
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:
Werner Koch 2002-06-17 10:11:34 +00:00
parent ccb0bb10e1
commit 469dc1043d
6 changed files with 118 additions and 79 deletions

View File

@ -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.

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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)

View File

@ -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