* configure.ac: New option --disable-finger.

* keyserver.c (keyserver_spawn): Print an empty string in log_info
if the host is not set (e.g. finger).

* gpgkeys_finger.c: New.
This commit is contained in:
Werner Koch 2004-10-11 08:44:35 +00:00
parent f3687f6b6c
commit 5bdb171026
10 changed files with 398 additions and 31 deletions

View File

@ -1,3 +1,7 @@
2004-10-11 Werner Koch <wk@g10code.com>
* configure.ac: New option --disable-finger.
2004-09-17 Werner Koch <wk@g10code.com>
* configure.ac: Don't check for usb_create_match or

View File

@ -303,6 +303,13 @@ if test "$use_exec" = yes ; then
try_http=$enableval, try_http=yes)
AC_MSG_RESULT($try_http)
AC_MSG_CHECKING([whether Finger key fetching support is requested])
AC_ARG_ENABLE(http,
AC_HELP_STRING([--disable-finger],
[disable Finger key fetching interface]),
try_finger=$enableval, try_finger=yes)
AC_MSG_RESULT($try_finger)
AC_MSG_CHECKING([whether email keyserver support is requested])
AC_ARG_ENABLE(mailto,
[ --disable-mailto disable email keyserver interface],
@ -492,6 +499,10 @@ if test x"$try_http" = xyes ; then
AC_SUBST(GPGKEYS_HTTP,"gpgkeys_http$EXEEXT")
fi
if test x"$try_finger" = xyes ; then
AC_SUBST(GPGKEYS_FINGER,"gpgkeys_finger$EXEEXT")
fi
dnl Must check for network library requirements before doing link tests
dnl for ldap, for example. If ldap libs are static (or dynamic and without
dnl ELF runtime link paths), then link will fail and LDAP support won't

View File

@ -1,3 +1,8 @@
2004-10-11 Werner Koch <wk@g10code.com>
* keyserver.c (keyserver_spawn): Print an empty string in log_info
if the host is not set (e.g. finger).
2004-10-10 David Shaw <dshaw@jabberwocky.com>
* card-util.c, keyedit.c, openfile.c, pkclist.c, delkey.c,
@ -51,6 +56,13 @@
revoked/expired/expires string change of 2004-09-29 was too
simple. Use two styles for each tag.
2004-10-06 Werner Koch <wk@g10code.com>
* ccid-driver.c (ccid_open_reader): Store the vendor ID.
(ccid_transceive_secure): New.
(parse_ccid_descriptor): Workaround for an SCM reader problem.
(send_escape_cmd): New.
2004-10-05 David Shaw <dshaw@jabberwocky.com>
* passphrase.c (agent_get_passphrase): Use keystrs for agent

View File

@ -154,8 +154,6 @@
enum {
RDR_to_PC_NotifySlotChange= 0x50,
RDR_to_PC_HardwareError = 0x51,
@ -183,12 +181,21 @@ enum {
};
/* We need to know the vendor to do some hacks. */
enum {
VENDOR_SCM = 0x04e6
};
/* Store information on the driver's state. A pointer to such a
structure is used as handle for most functions. */
struct ccid_driver_s
{
usb_dev_handle *idev;
char *rid;
unsigned short id_vendor;
unsigned short id_product;
unsigned short bcd_device;
int seqno;
unsigned char t1_ns;
unsigned char t1_nr;
@ -251,6 +258,8 @@ parse_ccid_descriptor (ccid_driver_t handle,
handle->max_ifsd = 32;
handle->ifsd = 0;
handle->has_pinpad = 0;
DEBUGOUT_3 ("idVendor: %04X idProduct: %04X bcdDevice: %04X\n",
handle->id_vendor, handle->id_product, handle->bcd_device);
if (buflen < 54 || buf[0] < 54)
{
DEBUGOUT ("CCID device descriptor is too short\n");
@ -417,8 +426,25 @@ parse_ccid_descriptor (ccid_driver_t handle,
"this is not available\n");
return -1;
}
else
return 0;
/* SCM drivers get stuck in their internal USB stack if they try to
send a frame of n*wMaxPacketSize back to us. Given that
wMaxPacketSize is 64 for these readers we set the IFSD to a value
lower than that:
64 - 10 CCID header - 4 T1frame - 2 reserved = 48 */
if (handle->id_vendor == VENDOR_SCM
/* FIXME: check whether it is the same
firmware version for all drivers. */
&& handle->bcd_device < 0x0513
&& handle->max_ifsd > 48)
{
DEBUGOUT ("enabling workaround for buggy SCM readers\n");
handle->max_ifsd = 48;
}
return 0;
}
@ -436,7 +462,7 @@ get_escaped_usb_string (usb_dev_handle *idev, int idx,
if (!idx)
return NULL;
/* Fixme: The next line for the current Valgrid without support
/* Fixme: The next line is for the current Valgrid without support
for USB IOCTLs. */
memset (buf, 0, sizeof buf);
@ -825,6 +851,9 @@ ccid_open_reader (ccid_driver_t *handle, const char *readerid)
}
(*handle)->idev = idev;
(*handle)->rid = rid;
(*handle)->id_vendor = dev->descriptor.idVendor;
(*handle)->id_product = dev->descriptor.idProduct;
(*handle)->bcd_device = dev->descriptor.bcdDevice;
DEBUGOUT_2 ("using CCID reader %d (ID=%s)\n", readerno, rid );
@ -1082,6 +1111,43 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
}
/* Note that this fucntion won't return the error codes NO_CARD or
CARD_INACTIVE */
static int
send_escape_cmd (ccid_driver_t handle,
const unsigned char *data, size_t datalen)
{
int i, rc;
unsigned char msg[100];
size_t msglen;
unsigned char seqno;
if (datalen > sizeof msg - 10)
return CCID_DRIVER_ERR_INV_VALUE; /* Escape data too large. */
msg[0] = PC_to_RDR_Escape;
msg[5] = 0; /* slot */
msg[6] = seqno = handle->seqno++;
msg[7] = 0; /* RFU */
msg[8] = 0; /* RFU */
msg[9] = 0; /* RFU */
memcpy (msg+10, data, datalen);
msglen = 10 + datalen;
set_msg_len (msg, datalen);
DEBUGOUT ("sending");
for (i=0; i < msglen; i++)
DEBUGOUT_CONT_1 (" %02X", msg[i]);
DEBUGOUT_LF ();
rc = bulk_out (handle, msg, msglen);
if (rc)
return rc;
rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Escape, seqno);
return rc;
}
/* experimental */
int
ccid_poll (ccid_driver_t handle)
@ -1617,10 +1683,232 @@ ccid_transceive (ccid_driver_t handle,
}
/* Send the CCID Secure command to the reader. APDU_BUF should contain the APDU template. PIN_MODE defines now the pin gets formatted:
1 := The PIN is ASCII encoded and of variable length. The
length of the PIN entered will be put into Lc by the reader.
The APDU should me made up of 4 bytes without Lc.
PINLEN_MIN and PINLEN_MAX define the limits for the pin length. 0
may be used t enable usbale defaults. PIN_PADLEN should be 0
When called with RESP and NRESP set to NULL, the function will
merely check whether the reader supports the secure command for the
given APDU and PIN_MODE. */
int
ccid_transceive_secure (ccid_driver_t handle,
const unsigned char *apdu_buf, size_t apdu_buflen,
int pin_mode, int pinlen_min, int pinlen_max,
int pin_padlen,
unsigned char *resp, size_t maxresplen, size_t *nresp)
{
int rc;
unsigned char send_buffer[10+259], recv_buffer[10+259];
unsigned char *msg, *tpdu, *p;
size_t msglen, tpdulen, n;
unsigned char seqno;
int i;
size_t dummy_nresp;
int testmode;
testmode = !resp && !nresp;
if (!nresp)
nresp = &dummy_nresp;
*nresp = 0;
if (apdu_buflen >= 4 && apdu_buf[1] == 0x20 && (handle->has_pinpad & 1))
;
else if (apdu_buflen >= 4 && apdu_buf[1] == 0x24 && (handle->has_pinpad & 2))
return CCID_DRIVER_ERR_NOT_SUPPORTED; /* Not yet by our code. */
else
return CCID_DRIVER_ERR_NOT_SUPPORTED;
if (pin_mode != 1)
return CCID_DRIVER_ERR_NOT_SUPPORTED;
if (pin_padlen != 0)
return CCID_DRIVER_ERR_NOT_SUPPORTED;
if (!pinlen_min)
pinlen_min = 1;
if (!pinlen_max)
pinlen_max = 25;
/* Note that the 25 is the maximum value the SPR532 allows. */
if (pinlen_min < 1 || pinlen_min > 25
|| pinlen_max < 1 || pinlen_max > 25
|| pinlen_min > pinlen_max)
return CCID_DRIVER_ERR_INV_VALUE;
/* We have only tested this with an SCM reader so better don't risk
anything and do not allow the use with other readers. */
if (handle->id_vendor != VENDOR_SCM)
return CCID_DRIVER_ERR_NOT_SUPPORTED;
if (testmode)
return 0; /* Success */
msg = send_buffer;
if (handle->id_vendor == VENDOR_SCM)
{
DEBUGOUT ("sending escape sequence to switch to a case 1 APDU\n");
rc = send_escape_cmd (handle, "\x80\x02\x00", 3);
if (rc)
return rc;
}
msg[0] = PC_to_RDR_Secure;
msg[5] = 0; /* slot */
msg[6] = seqno = handle->seqno++;
msg[7] = 4; /* bBWI */
msg[8] = 0; /* RFU */
msg[9] = 0; /* RFU */
msg[10] = 0; /* Perform PIN verification. */
msg[11] = 0; /* Timeout in seconds. */
msg[12] = 0x82; /* bmFormatString: Byte, pos=0, left, ASCII. */
if (handle->id_vendor == VENDOR_SCM)
{
/* For the SPR532 the next 2 bytes need to be zero. We do this
for all SCM product. Kudos to to Martin Paljak for this
hint. */
msg[13] = msg[14] = 0;
}
else
{
msg[13] = 0x00; /* bmPINBlockString:
0 bits of pin length to insert.
0 bytes of PIN block size. */
msg[14] = 0x00; /* bmPINLengthFormat:
Units are bytes, position is 0. */
}
msg[15] = pinlen_min; /* wPINMaxExtraDigit-Minimum. */
msg[16] = pinlen_max; /* wPINMaxExtraDigit-Maximum. */
msg[17] = 0x02; /* bEntryValidationCondition:
Validation key pressed */
if (pinlen_min && pinlen_max && pinlen_min == pinlen_max)
msg[17] |= 0x01; /* Max size reached. */
msg[18] = 0xff; /* bNumberMessage: Default. */
msg[19] = 0x04; /* wLangId-High. */
msg[20] = 0x09; /* wLangId-Low: English FIXME: use the first entry. */
msg[21] = 0; /* bMsgIndex. */
/* bTeoProlog follows: */
msg[22] = handle->nonnull_nad? ((1 << 4) | 0): 0;
msg[23] = ((handle->t1_ns & 1) << 6); /* I-block */
msg[24] = 4; /* apdulen. */
/* APDU follows: */
msg[25] = apdu_buf[0]; /* CLA */
msg[26] = apdu_buf[1]; /* INS */
msg[27] = apdu_buf[2]; /* P1 */
msg[28] = apdu_buf[3]; /* P2 */
msglen = 29;
set_msg_len (msg, msglen - 10);
DEBUGOUT ("sending");
for (i=0; i < msglen; i++)
DEBUGOUT_CONT_1 (" %02X", msg[i]);
DEBUGOUT_LF ();
rc = bulk_out (handle, msg, msglen);
if (rc)
return rc;
msg = recv_buffer;
rc = bulk_in (handle, msg, sizeof recv_buffer, &msglen,
RDR_to_PC_DataBlock, seqno);
if (rc)
return rc;
tpdu = msg + 10;
tpdulen = msglen - 10;
if (tpdulen < 4)
{
usb_clear_halt (handle->idev, 0x82);
return CCID_DRIVER_ERR_ABORTED;
}
#ifdef DEBUG_T1
fprintf (stderr, "T1: got %c-block seq=%d err=%d\n",
((msg[11] & 0xc0) == 0x80)? 'R' :
(msg[11] & 0x80)? 'S' : 'I',
((msg[11] & 0x80)? !!(msg[11]& 0x10) : !!(msg[11] & 0x40)),
((msg[11] & 0xc0) == 0x80)? (msg[11] & 0x0f) : 0
);
#endif
if (!(tpdu[1] & 0x80))
{ /* This is an I-block. */
/* Last block sent was successful. */
handle->t1_ns ^= 1;
if (!!(tpdu[1] & 0x40) != handle->t1_nr)
{ /* Reponse does not match our sequence number. */
DEBUGOUT ("I-block with wrong seqno received\n");
return CCID_DRIVER_ERR_CARD_IO_ERROR;
}
handle->t1_nr ^= 1;
p = tpdu + 3; /* Skip the prologue field. */
n = tpdulen - 3 - 1; /* Strip the epilogue field. */
/* fixme: verify the checksum. */
if (resp)
{
if (n > maxresplen)
{
DEBUGOUT_2 ("provided buffer too short for received data "
"(%u/%u)\n",
(unsigned int)n, (unsigned int)maxresplen);
return CCID_DRIVER_ERR_INV_VALUE;
}
memcpy (resp, p, n);
resp += n;
*nresp += n;
maxresplen -= n;
}
if (!(tpdu[1] & 0x20))
return 0; /* No chaining requested - ready. */
DEBUGOUT ("chaining requested but not supported for Secure operation\n");
return CCID_DRIVER_ERR_CARD_IO_ERROR;
}
else if ((tpdu[1] & 0xc0) == 0x80)
{ /* This is a R-block. */
if ( (tpdu[1] & 0x0f))
{ /* Error: repeat last block */
DEBUGOUT ("No retries supported for Secure operation\n");
return CCID_DRIVER_ERR_CARD_IO_ERROR;
}
else if (!!(tpdu[1] & 0x40) == handle->t1_ns)
{ /* Reponse does not match our sequence number. */
DEBUGOUT ("R-block with wrong seqno received on more bit\n");
return CCID_DRIVER_ERR_CARD_IO_ERROR;
}
else
{ /* Send next chunk. */
DEBUGOUT ("chaining not supported on Secure operation\n");
return CCID_DRIVER_ERR_CARD_IO_ERROR;
}
}
else
{ /* This is a S-block. */
DEBUGOUT_2 ("T1 S-block %s received cmd=%d for Secure operation\n",
(tpdu[1] & 0x20)? "response": "request",
(tpdu[1] & 0x1f));
return CCID_DRIVER_ERR_CARD_IO_ERROR;
}
return 0;
}
#ifdef TEST
static void
print_error (int err)
{
@ -1682,6 +1970,9 @@ main (int argc, char **argv)
unsigned int slotstat;
unsigned char result[512];
size_t resultlen;
int no_pinpad = 0;
int verify_123456 = 0;
int did_verify = 0;
if (argc)
{
@ -1706,6 +1997,16 @@ main (int argc, char **argv)
ccid_set_debug_level (1);
argc--; argv++;
}
else if ( !strcmp (*argv, "--no-pinpad"))
{
no_pinpad = 1;
argc--; argv++;
}
else if ( !strcmp (*argv, "--verify-123456"))
{
verify_123456 = 1;
argc--; argv++;
}
else
break;
}
@ -1755,28 +2056,55 @@ main (int argc, char **argv)
print_result (rc, result, resultlen);
}
ccid_poll (ccid);
if (!no_pinpad)
{
}
/* if (!ccid->has_pinpad) */
/* { */
/* fputs ("verifying that CHV1 is 123456....\n", stderr); */
/* { */
/* static unsigned char apdu[] = {0, 0x20, 0, 0x81, */
/* 6, '1','2','3','4','5','6'}; */
/* rc = ccid_transceive (ccid, apdu, sizeof apdu, */
/* result, sizeof result, &resultlen); */
/* print_result (rc, result, resultlen); */
/* } */
/* } */
/* else */
/* { */
/* fputs ("verifying CHV1 using the PINPad ....\n", stderr); */
/* { */
/* rc = ccid_secure_transceive (ccid, */
/* result, sizeof result, &resultlen); */
/* print_result (rc, result, resultlen); */
/* } */
/* } */
if (!no_pinpad)
{
static unsigned char apdu[] = { 0, 0x20, 0, 0x81 };
if (ccid_transceive_secure (ccid,
apdu, sizeof apdu,
1, 0, 0, 0,
NULL, 0, NULL))
fputs ("can't verify using a PIN-Pad reader\n", stderr);
else
{
fputs ("verifying CHV1 using the PINPad ....\n", stderr);
rc = ccid_transceive_secure (ccid,
apdu, sizeof apdu,
1, 0, 0, 0,
result, sizeof result, &resultlen);
print_result (rc, result, resultlen);
did_verify = 1;
}
}
if (verify_123456 && !did_verify)
{
fputs ("verifying that CHV1 is 123456....\n", stderr);
{
static unsigned char apdu[] = {0, 0x20, 0, 0x81,
6, '1','2','3','4','5','6'};
rc = ccid_transceive (ccid, apdu, sizeof apdu,
result, sizeof result, &resultlen);
print_result (rc, result, resultlen);
}
}
if (!rc)
{
fputs ("getting OpenPGP DO 0x5E ....\n", stderr);
{
static unsigned char apdu[] = { 0, 0xCA, 0, 0x5E, 254 };
rc = ccid_transceive (ccid, apdu, sizeof apdu,
result, sizeof result, &resultlen);
print_result (rc, result, resultlen);
}
}
ccid_close_reader (ccid);

View File

@ -86,6 +86,11 @@ int ccid_slot_status (ccid_driver_t handle, int *statusbits);
int ccid_transceive (ccid_driver_t handle,
const unsigned char *apdu, size_t apdulen,
unsigned char *resp, size_t maxresplen, size_t *nresp);
int ccid_transceive_secure (ccid_driver_t handle,
const unsigned char *apdu, size_t apdulen,
int pin_mode,
int pinlen_min, int pinlen_max, int pin_padlen,
unsigned char *resp, size_t maxresplen, size_t *nresp);

View File

@ -25,6 +25,8 @@
#include "cardglue.h"
#endif
gpg_error_t iso7816_map_sw (int sw);
gpg_error_t iso7816_select_application (int slot,
const char *aid, size_t aidlen);
gpg_error_t iso7816_select_file (int slot, int tag, int is_dir,

View File

@ -894,7 +894,7 @@ keyserver_spawn(int action,STRLIST list,KEYDB_SEARCH_DESC *desc,
log_info(_("requesting key %s from %s server %s\n"),
keystr_from_desc(&desc[i]),
keyserver->scheme,keyserver->host);
keyserver->scheme,keyserver->host?keyserver->host:"");
}
fprintf(spawn->tochild,"\n");
@ -1039,7 +1039,7 @@ keyserver_spawn(int action,STRLIST list,KEYDB_SEARCH_DESC *desc,
log_info(_("sending key %s to %s server %s\n"),
keystr(block->pkt->pkt.public_key->keyid),
keyserver->scheme,keyserver->host);
keyserver->scheme,keyserver->host?keyserver->host:"");
release_kbnode(block);
}
@ -1080,7 +1080,7 @@ keyserver_spawn(int action,STRLIST list,KEYDB_SEARCH_DESC *desc,
fprintf(spawn->tochild,"\n");
log_info(_("searching for \"%s\" from %s server %s\n"),
searchstr,keyserver->scheme,keyserver->host);
searchstr,keyserver->scheme,keyserver->host?keyserver->host:"");
break;
}

View File

@ -1,3 +1,7 @@
2004-10-11 Werner Koch <wk@g10code.com>
* gpgkeys_finger.c: New.
2004-08-27 Stefan Bellon <sbellon@sbellon.de>
* gpgkeys_hkp.c (search_key): Fix the prior faulty fix by

View File

@ -19,17 +19,18 @@
## Process this file with automake to produce Makefile.in
INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/intl
EXTRA_PROGRAMS = gpgkeys_ldap gpgkeys_hkp gpgkeys_http
EXTRA_PROGRAMS = gpgkeys_ldap gpgkeys_hkp gpgkeys_http gpgkeys_finger
EXTRA_SCRIPTS = gpgkeys_mailto
libexecdir = @libexecdir@/@PACKAGE@
libexec_PROGRAMS = @GPGKEYS_LDAP@ @GPGKEYS_HKP@ @GPGKEYS_HTTP@
libexec_PROGRAMS = @GPGKEYS_LDAP@ @GPGKEYS_HKP@ @GPGKEYS_HTTP@ @GPGKEYS_FINGER@
libexec_SCRIPTS = @GPGKEYS_MAILTO@
noinst_SCRIPTS = gpgkeys_test
gpgkeys_ldap_LDADD = ../util/libutil.a @LDAPLIBS@ @NETLIBS@ @LIBINTL@ @CAPLIBS@ @GETOPT@ @W32LIBS@
gpgkeys_hkp_LDADD = ../util/libutil.a @NETLIBS@ @SRVLIBS@ @LIBINTL@ @CAPLIBS@ @GETOPT@ @W32LIBS@
gpgkeys_http_LDADD = ../util/libutil.a @NETLIBS@ @SRVLIBS@ @LIBINTL@ @CAPLIBS@ @GETOPT@ @W32LIBS@
gpgkeys_finger_LDADD = ../util/libutil.a @NETLIBS@ @LIBINTL@ @CAPLIBS@ @GETOPT@ @W32LIBS@
install-exec-hook:
if GPGKEYS_LDAP

BIN
keyserver/gpgkeys_finger Executable file

Binary file not shown.