mirror of
git://git.gnupg.org/gnupg.git
synced 2025-04-12 22:11:29 +02: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>
|
2002-06-12 Werner Koch <wk@gnupg.org>
|
||||||
|
|
||||||
* gpg-agent.c (main): New option --disable-pth.
|
* 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_digits; /* max. number of allowed digits allowed*/
|
||||||
int max_tries;
|
int max_tries;
|
||||||
int failed_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 */
|
size_t max_length; /* allocated length of the buffer */
|
||||||
char pin[1];
|
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);
|
int agent_key_available (const unsigned char *grip);
|
||||||
|
|
||||||
/*-- query.c --*/
|
/*-- query.c --*/
|
||||||
int agent_askpin (const char *desc_text, const char *err_text,
|
int agent_askpin (const char *desc_text, struct pin_entry_info_s *pininfo);
|
||||||
struct pin_entry_info_s *pininfo);
|
|
||||||
int agent_get_passphrase (char **retpass,
|
int agent_get_passphrase (char **retpass,
|
||||||
const char *desc, const char *prompt,
|
const char *desc, const char *prompt,
|
||||||
const char *errtext);
|
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
|
/* 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
|
buf has been allocated by the caller and is of size MAXBUF which
|
||||||
includes the terminating null. The function should return an UTF-8
|
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 */
|
with arbitrary characters */
|
||||||
static int
|
static int
|
||||||
getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
|
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;
|
struct pin_entry_info_s *pi;
|
||||||
int rc;
|
int rc;
|
||||||
int tries = 0;
|
int tries = 0;
|
||||||
const char *errtext;
|
|
||||||
|
|
||||||
assert (!opaque);
|
assert (!opaque);
|
||||||
|
|
||||||
if (maxbuf < 2)
|
if (maxbuf < 2)
|
||||||
return GNUPG_Invalid_Value;
|
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 = gcry_calloc_secure (1, sizeof (*pi) + 100);
|
||||||
pi->max_length = maxbuf-1;
|
pi->max_length = maxbuf-1;
|
||||||
pi->min_digits = 0; /* we want a real passphrase */
|
pi->min_digits = 0; /* we want a real passphrase */
|
||||||
pi->max_digits = 8;
|
pi->max_digits = 8;
|
||||||
pi->max_tries = 3;
|
pi->max_tries = 3;
|
||||||
|
|
||||||
errtext = NULL;
|
rc = agent_askpin (info, pi);
|
||||||
do
|
if (!rc)
|
||||||
{
|
{
|
||||||
rc = agent_askpin (info, errtext, pi);
|
strncpy (buf, pi->pin, maxbuf-1);
|
||||||
if (!rc)
|
buf[maxbuf-1] = 0;
|
||||||
{
|
|
||||||
strncpy (buf, pi->pin, maxbuf-1);
|
|
||||||
buf[maxbuf-1] = 0;
|
|
||||||
xfree (pi);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
errtext = pi->min_digits? trans ("Bad PIN") : trans ("Bad Passphrase");
|
|
||||||
}
|
}
|
||||||
while ((rc == GNUPG_Bad_Passphrase || rc == GNUPG_Bad_PIN)
|
|
||||||
&& tries++ < 3);
|
|
||||||
xfree (pi);
|
xfree (pi);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -27,9 +27,17 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include "agent.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
|
int
|
||||||
agent_write_private_key (const unsigned char *grip,
|
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
|
static int
|
||||||
unprotect (unsigned char **keybuf, const unsigned char *grip)
|
unprotect (unsigned char **keybuf, const unsigned char *grip)
|
||||||
{
|
{
|
||||||
struct pin_entry_info_s *pi;
|
struct pin_entry_info_s *pi;
|
||||||
|
struct try_unprotect_arg_s arg;
|
||||||
int rc, i;
|
int rc, i;
|
||||||
unsigned char *result;
|
unsigned char *result;
|
||||||
size_t resultlen;
|
size_t resultlen;
|
||||||
int tries = 0;
|
|
||||||
char hexgrip[40+1];
|
char hexgrip[40+1];
|
||||||
const char *errtext;
|
|
||||||
|
|
||||||
for (i=0; i < 20; i++)
|
for (i=0; i < 20; i++)
|
||||||
sprintf (hexgrip+2*i, "%02X", grip[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->min_digits = 0; /* we want a real passphrase */
|
||||||
pi->max_digits = 8;
|
pi->max_digits = 8;
|
||||||
pi->max_tries = 3;
|
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;
|
rc = agent_askpin (NULL, pi);
|
||||||
do
|
if (!rc)
|
||||||
{
|
{
|
||||||
rc = agent_askpin (NULL, errtext, pi);
|
assert (arg.unprotected_key);
|
||||||
if (!rc)
|
agent_put_cache (hexgrip, pi->pin, 0);
|
||||||
{
|
xfree (*keybuf);
|
||||||
rc = agent_unprotect (*keybuf, pi->pin, &result, &resultlen);
|
*keybuf = arg.unprotected_key;
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
while ((rc == GNUPG_Bad_Passphrase || rc == GNUPG_Bad_PIN)
|
|
||||||
&& tries++ < 3);
|
|
||||||
xfree (pi);
|
xfree (pi);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,19 @@ store_key (GCRY_SEXP private, const char *passphrase)
|
|||||||
return rc;
|
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
|
/* 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);
|
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"
|
const char *text1 = trans ("Please enter the passphrase to%0A"
|
||||||
"to protect your new key");
|
"to protect your new key");
|
||||||
const char *text2 = trans ("Please re-enter this passphrase");
|
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);
|
pi = gcry_calloc_secure (2, sizeof (*pi) + 100);
|
||||||
pi2 = pi + sizeof *pi;
|
pi2 = pi + (sizeof *pi + 100);
|
||||||
pi->max_length = 100;
|
pi->max_length = 100;
|
||||||
pi->max_tries = 3;
|
pi->max_tries = 3;
|
||||||
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_arg = pi->pin;
|
||||||
|
|
||||||
rc = agent_askpin (text1, NULL, pi);
|
rc = agent_askpin (text1, pi);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
{
|
rc = agent_askpin (text2, pi2);
|
||||||
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;
|
|
||||||
}
|
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
if (!*pi->pin)
|
if (!*pi->pin)
|
||||||
{
|
{
|
||||||
xfree (pi);
|
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 */
|
/* store the secret key */
|
||||||
log_debug ("storing private key\n");
|
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;
|
xfree (pi); pi = NULL;
|
||||||
gcry_sexp_release (s_private);
|
gcry_sexp_release (s_private);
|
||||||
if (rc)
|
if (rc)
|
||||||
|
@ -218,13 +218,12 @@ all_digitsp( const char *s)
|
|||||||
number here and repeat it as long as we have invalid formed
|
number here and repeat it as long as we have invalid formed
|
||||||
numbers. */
|
numbers. */
|
||||||
int
|
int
|
||||||
agent_askpin (const char *desc_text, const char *start_err_text,
|
agent_askpin (const char *desc_text, struct pin_entry_info_s *pininfo)
|
||||||
struct pin_entry_info_s *pininfo)
|
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
char line[ASSUAN_LINELENGTH];
|
char line[ASSUAN_LINELENGTH];
|
||||||
struct entry_parm_s parm;
|
struct entry_parm_s parm;
|
||||||
const char *errtext = start_err_text;
|
const char *errtext = NULL;
|
||||||
|
|
||||||
if (opt.batch)
|
if (opt.batch)
|
||||||
return 0; /* fixme: we should return BAD PIN */
|
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)
|
if (errtext)
|
||||||
{
|
{
|
||||||
/* fixme: should we show the try count? It must be translated */
|
/* fixme: should we show the try count? It must be translated */
|
||||||
if (start_err_text)
|
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", 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);
|
|
||||||
line[DIM(line)-1] = 0;
|
line[DIM(line)-1] = 0;
|
||||||
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
if (rc)
|
if (rc)
|
||||||
@ -276,25 +269,42 @@ agent_askpin (const char *desc_text, const char *start_err_text,
|
|||||||
errtext = NULL;
|
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)
|
if (rc == ASSUAN_Too_Much_Data)
|
||||||
errtext = pininfo->min_digits? trans ("PIN too long")
|
errtext = pininfo->min_digits? trans ("PIN too long")
|
||||||
: trans ("Passphrase too long");
|
: trans ("Passphrase too long");
|
||||||
else if (rc)
|
else if (rc)
|
||||||
return unlock_pinentry (map_assuan_err (rc));
|
return unlock_pinentry (map_assuan_err (rc));
|
||||||
if (!errtext && !pininfo->min_digits)
|
|
||||||
return unlock_pinentry (0); /* okay, got a passphrase */
|
if (!errtext && pininfo->min_digits)
|
||||||
if (!errtext && !all_digitsp (pininfo->pin))
|
{
|
||||||
errtext = trans ("Invalid characters in PIN");
|
/* do some basic checks on the entered PIN. */
|
||||||
if (!errtext && pininfo->max_digits
|
if (!all_digitsp (pininfo->pin))
|
||||||
&& strlen (pininfo->pin) > pininfo->max_digits)
|
errtext = trans ("Invalid characters in PIN");
|
||||||
errtext = trans ("PIN too long");
|
else if (pininfo->max_digits
|
||||||
if (!errtext
|
&& strlen (pininfo->pin) > pininfo->max_digits)
|
||||||
&& strlen (pininfo->pin) < pininfo->min_digits)
|
errtext = trans ("PIN too long");
|
||||||
errtext = trans ("PIN too short");
|
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)
|
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
|
return unlock_pinentry (pininfo->min_digits? GNUPG_Bad_PIN
|
||||||
|
Loading…
x
Reference in New Issue
Block a user