(parse_login_data): New.

(app_select_openpgp): Call it.
(do_setattr): Reparse it after change.
This commit is contained in:
Werner Koch 2004-10-14 13:22:03 +00:00
parent e1f3dc1c77
commit 2c31e2f853
2 changed files with 112 additions and 29 deletions

View File

@ -1,3 +1,9 @@
2004-10-14 Werner Koch <wk@g10code.com>
* app-openpgp.c (parse_login_data): New.
(app_select_openpgp): Call it.
(do_setattr): Reparse it after change.
2004-10-06 Werner Koch <wk@g10code.de>
* ccid-driver.c (ccid_open_reader): Store the vendor ID.

View File

@ -101,6 +101,11 @@ struct app_local_s {
unsigned int change_force_chv:1;
unsigned int private_dos:1;
} extcap;
struct
{
unsigned int no_sync:1; /* Do not sync CHV1 and CHV2 */
unsigned int def_chv2:1; /* Use 123456 for CHV2. */
} flags;
};
@ -411,6 +416,75 @@ count_bits (const unsigned char *a, size_t len)
return n;
}
/* GnuPG makes special use of the login-data DO, this fucntion parses
the login data to store the flags for later use. It may be called
at any time and should be called after changing the login-data DO.
Everything up to a LF is considered a mailbox or account name. If
the first LF is follewed by DC4 (0x14) control sequence are
expected up to the next LF. Control sequences are separated by FS
(0x28) and consist of key=value pairs. There is one key defined:
F=<flags>
Were FLAGS is a plain hexadecimal number representing flag values.
The lsb is here the rightmost bit. Defined flags bits are:
Bit 0 = CHV1 and CHV2 are not syncronized
Bit 1 = CHV2 has been been set to the default PIN of "123456"
(this implies that bit 0 is also set).
*/
static void
parse_login_data (app_t app)
{
unsigned char *buffer, *p;
size_t buflen, len;
void *relptr;
/* Set defaults. */
app->app_local->flags.no_sync = 0;
app->app_local->flags.def_chv2 = 0;
/* Read the DO. */
relptr = get_one_do (app, 0x005E, &buffer, &buflen);
if (!relptr)
return; /* Ooops. */
for (; buflen; buflen--, buffer++)
if (*buffer == '\n')
break;
if (buflen < 2 || buffer[1] != '\x14')
return; /* No control sequences. */
buflen--;
buffer++;
do
{
buflen--;
buffer++;
if (buflen > 1 && *buffer == 'F' && buffer[1] == '=')
{
/* Flags control sequence found. */
int lastdig = 0;
/* For now we are only interested in the last digit, so skip
any leading digits but bail out on invalid characters. */
for (p=buffer+2, len = buflen-2; len && hexdigitp (p); p++, len--)
lastdig = xtoi_1 (p);
if (len && !(*p == '\n' || *p == '\x18'))
goto next; /* Invalid characters in field. */
app->app_local->flags.no_sync = !!(lastdig & 1);
app->app_local->flags.def_chv2 = (lastdig & 3) == 3;
}
next:
for (; buflen && *buffer != '\x18'; buflen--, buffer++)
if (*buffer == '\n')
buflen = 1;
}
while (buflen);
xfree (relptr);
}
/* Note, that FPR must be at least 20 bytes. */
static int
store_fpr (int slot, int keynumber, u32 timestamp,
@ -479,7 +553,7 @@ store_fpr (int slot, int keynumber, u32 timestamp,
static void
send_fpr_if_not_null (CTRL ctrl, const char *keyword,
send_fpr_if_not_null (ctrl_t ctrl, const char *keyword,
int number, const unsigned char *fpr)
{
int i;
@ -502,7 +576,7 @@ send_fpr_if_not_null (CTRL ctrl, const char *keyword,
}
static void
send_key_data (CTRL ctrl, const char *name,
send_key_data (ctrl_t ctrl, const char *name,
const unsigned char *a, size_t alen)
{
char *p, *buf = xmalloc (alen*2+1);
@ -520,7 +594,7 @@ send_key_data (CTRL ctrl, const char *name,
/* Implement the GETATTR command. This is similar to the LEARN
command but returns just one value via the status interface. */
static int
do_getattr (APP app, CTRL ctrl, const char *name)
do_getattr (app_t app, ctrl_t ctrl, const char *name)
{
static struct {
const char *name;
@ -622,7 +696,7 @@ do_getattr (APP app, CTRL ctrl, const char *name)
static int
do_learn_status (APP app, CTRL ctrl)
do_learn_status (app_t app, ctrl_t ctrl)
{
do_getattr (app, ctrl, "EXTCAP");
do_getattr (app, ctrl, "DISP-NAME");
@ -661,7 +735,7 @@ verify_chv2 (app_t app,
if (strlen (pinvalue) < 6)
{
log_error (_("prassphrase (CHV%d) is too short;"
log_error (_("PIN for CHV%d is too short;"
" minimum length is %d\n"), 2, 6);
xfree (pinvalue);
return gpg_error (GPG_ERR_BAD_PIN);
@ -698,7 +772,7 @@ verify_chv2 (app_t app,
/* Verify CHV3 if required. */
static int
verify_chv3 (APP app,
verify_chv3 (app_t app,
int (*pincb)(void*, const char *, char **),
void *pincb_arg)
{
@ -780,7 +854,7 @@ verify_chv3 (APP app,
/* Handle the SETATTR operation. All arguments are already basically
checked. */
static int
do_setattr (APP app, const char *name,
do_setattr (app_t app, const char *name,
int (*pincb)(void*, const char *, char **),
void *pincb_arg,
const unsigned char *value, size_t valuelen)
@ -793,7 +867,7 @@ do_setattr (APP app, const char *name,
int special;
} table[] = {
{ "DISP-NAME", 0x005B },
{ "LOGIN-DATA", 0x005E },
{ "LOGIN-DATA", 0x005E, 2 },
{ "DISP-LANG", 0x5F2D },
{ "DISP-SEX", 0x5F35 },
{ "PUBKEY-URL", 0x5F50 },
@ -824,6 +898,8 @@ do_setattr (APP app, const char *name,
if (table[idx].special == 1)
app->force_chv1 = (valuelen && *value == 0);
else if (table[idx].special == 2)
parse_login_data (app);
return rc;
}
@ -831,7 +907,7 @@ do_setattr (APP app, const char *name,
/* Handle the PASSWD command. */
static int
do_change_pin (APP app, CTRL ctrl, const char *chvnostr, int reset_mode,
do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, int reset_mode,
int (*pincb)(void*, const char *, char **),
void *pincb_arg)
{
@ -918,7 +994,7 @@ do_change_pin (APP app, CTRL ctrl, const char *chvnostr, int reset_mode,
/* Handle the GENKEY command. */
static int
do_genkey (APP app, CTRL ctrl, const char *keynostr, unsigned int flags,
do_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags,
int (*pincb)(void*, const char *, char **),
void *pincb_arg)
{
@ -1060,7 +1136,7 @@ convert_sig_counter_value (const unsigned char *value, size_t valuelen)
}
static unsigned long
get_sig_counter (APP app)
get_sig_counter (app_t app)
{
void *relptr;
unsigned char *value;
@ -1076,7 +1152,7 @@ get_sig_counter (APP app)
}
static int
compare_fingerprint (APP app, int keyno, unsigned char *sha1fpr)
compare_fingerprint (app_t app, int keyno, unsigned char *sha1fpr)
{
const unsigned char *fpr;
unsigned char *buffer;
@ -1116,7 +1192,7 @@ compare_fingerprint (APP app, int keyno, unsigned char *sha1fpr)
known to gpg was not updated. If there is no fingerprint we
assume that this is okay. */
static int
check_against_given_fingerprint (APP app, const char *fpr, int keyno)
check_against_given_fingerprint (app_t app, const char *fpr, int keyno)
{
unsigned char tmp[20];
const char *s;
@ -1147,7 +1223,7 @@ check_against_given_fingerprint (APP app, const char *fpr, int keyno)
not match the one required for the requested action (e.g. the
serial number does not match). */
static int
do_sign (APP app, const char *keyidstr, int hashalgo,
do_sign (app_t app, const char *keyidstr, int hashalgo,
int (*pincb)(void*, const char *, char **),
void *pincb_arg,
const void *indata, size_t indatalen,
@ -1222,20 +1298,20 @@ do_sign (APP app, const char *keyidstr, int hashalgo,
{
char *prompt;
if (asprintf (&prompt, "PIN [sigs done: %lu]", sigcount) < 0)
if (asprintf (&prompt, _("PIN [sigs done: %lu]"), sigcount) < 0)
return gpg_error_from_errno (errno);
rc = pincb (pincb_arg, prompt, &pinvalue);
free (prompt);
}
if (rc)
{
log_info ("PIN callback returned error: %s\n", gpg_strerror (rc));
log_info (_("PIN callback returned error: %s\n"), gpg_strerror (rc));
return rc;
}
if (strlen (pinvalue) < 6)
{
log_error (_("prassphrase (CHV%d) is too short;"
log_error (_("PIN for CHV%d is too short;"
" minimum length is %d\n"), 1, 6);
xfree (pinvalue);
return gpg_error (GPG_ERR_BAD_PIN);
@ -1282,7 +1358,7 @@ do_sign (APP app, const char *keyidstr, int hashalgo,
not match the one required for the requested action (e.g. the
serial number does not match). */
static int
do_auth (APP app, const char *keyidstr,
do_auth (app_t app, const char *keyidstr,
int (*pincb)(void*, const char *, char **),
void *pincb_arg,
const void *indata, size_t indatalen,
@ -1341,7 +1417,7 @@ do_auth (APP app, const char *keyidstr,
static int
do_decipher (APP app, const char *keyidstr,
do_decipher (app_t app, const char *keyidstr,
int (pincb)(void*, const char *, char **),
void *pincb_arg,
const void *indata, size_t indatalen,
@ -1403,7 +1479,7 @@ do_decipher (APP app, const char *keyidstr,
dangerous CHV3. KEYIDSTR is the usual card's serial number; an
optional fingerprint part will be ignored. */
static int
do_check_pin (APP app, const char *keyidstr,
do_check_pin (app_t app, const char *keyidstr,
int (pincb)(void*, const char *, char **),
void *pincb_arg)
{
@ -1450,7 +1526,7 @@ do_check_pin (APP app, const char *keyidstr,
/* Select the OpenPGP application on the card in SLOT. This function
must be used before any other OpenPGP application functions. */
int
app_select_openpgp (APP app)
app_select_openpgp (app_t app)
{
static char const aid[] = { 0xD2, 0x76, 0x00, 0x01, 0x24, 0x01 };
int slot = app->slot;
@ -1503,8 +1579,8 @@ app_select_openpgp (APP app)
relptr = get_one_do (app, 0x00C4, &buffer, &buflen);
if (!relptr)
{
log_error (_("can't access CHV Status Bytes "
"- invalid OpenPGP card?\n"));
log_error (_("can't access %s - invalid OpenPGP card?\n"),
"CHV Status Bytes");
goto leave;
}
app->force_chv1 = (buflen && *buffer == 0);
@ -1513,8 +1589,8 @@ app_select_openpgp (APP app)
relptr = get_one_do (app, 0x00C0, &buffer, &buflen);
if (!relptr)
{
log_error (_("can't access Extended Capability Flags - "
"invalid OpenPGP card?\n"));
log_error (_("can't access %s - invalid OpenPGP card?\n"),
"Extended Capability Flags" );
goto leave;
}
if (buflen)
@ -1531,6 +1607,7 @@ app_select_openpgp (APP app)
if (app->card_version <= 0x0100 && manufacturer == 1)
app->app_local->extcap.change_force_chv = 1;
parse_login_data (app);
if (opt.verbose > 1)
dump_all_do (slot);
@ -1562,7 +1639,7 @@ leave:
buffers or NULL if the data object is not available. All returned
values are sanitized. */
int
app_openpgp_cardinfo (APP app,
app_openpgp_cardinfo (app_t app,
char **serialno,
char **disp_name,
char **pubkey_url,
@ -1644,7 +1721,7 @@ app_openpgp_cardinfo (APP app,
/* This function is currently only used by the sc-copykeys program to
store a key on the smartcard. APP ist the application handle,
store a key on the smartcard. app_t ist the application handle,
KEYNO is the number of the key and PINCB, PINCB_ARG are used to ask
for the SO PIN. TEMPLATE and TEMPLATE_LEN describe a buffer with
the key template to store. CREATED_AT is the timestamp used to
@ -1652,7 +1729,7 @@ app_openpgp_cardinfo (APP app,
RSA public exponent. This function silently overwrites an existing
key.*/
int
app_openpgp_storekey (APP app, int keyno,
app_openpgp_storekey (app_t app, int keyno,
unsigned char *template, size_t template_len,
time_t created_at,
const unsigned char *m, size_t mlen,
@ -1697,7 +1774,7 @@ app_openpgp_storekey (APP app, int keyno,
/* Utility function for external tools: Read the public RSA key at
KEYNO and return modulus and exponent in (M,MLEN) and (E,ELEN). */
int
app_openpgp_readkey (APP app, int keyno, unsigned char **m, size_t *mlen,
app_openpgp_readkey (app_t app, int keyno, unsigned char **m, size_t *mlen,
unsigned char **e, size_t *elen)
{
int rc;