1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-02 22:46:30 +02:00

We have reached a state where we are able to import certs and

check the certification path.
This commit is contained in:
Werner Koch 2001-11-13 12:50:14 +00:00
parent 6dec3847d8
commit 90d060c199
25 changed files with 2486 additions and 731 deletions

View file

@ -25,134 +25,417 @@
#include "keybox-defs.h"
static ulong
get32 (const byte *buffer)
{
ulong a;
a = *buffer << 24;
a |= buffer[1] << 16;
a |= buffer[2] << 8;
a |= buffer[3];
return a;
}
/****************
* Check whether the given fingerprint (20 bytes) is in the
* given keyblob. fpr is always 20 bytes.
* Return: 0 = found
* -1 = not found
other = error (fixme: do not always reurn gpgerr_general)
static ulong
get16 (const byte *buffer)
{
ulong a;
a = *buffer << 8;
a |= buffer[1];
return a;
}
static int
blob_get_type (KEYBOXBLOB blob)
{
const unsigned char *buffer;
size_t length;
buffer = _keybox_get_blob_image (blob, &length);
if (length < 40)
return -1; /* blob too short */
return buffer[4];
}
static int
blob_cmp_sn (KEYBOXBLOB blob, const unsigned char *sn)
{
size_t snlen;
const unsigned char *buffer;
size_t length;
size_t pos, off;
size_t nkeys, keyinfolen;
size_t nserial;
snlen = (sn[0] << 24) | (sn[1] << 16) | (sn[2] << 8) | sn[3];
sn += 4;
buffer = _keybox_get_blob_image (blob, &length);
if (length < 40)
return 0; /* blob too short */
/*keys*/
nkeys = get16 (buffer + 16);
keyinfolen = get16 (buffer + 18 );
if (keyinfolen < 28)
return 0; /* invalid blob */
pos = 20 + keyinfolen*nkeys;
if (pos+2 > length)
return 0; /* out of bounds */
/*serial*/
nserial = get16 (buffer+pos);
off = pos + 2;
if (off+nserial > length)
return 0; /* out of bounds */
return nserial == snlen && !memcmp (buffer+off, sn, snlen);
}
static int
blob_cmp_name (KEYBOXBLOB blob, int idx, const char *name, size_t namelen)
{
const unsigned char *buffer;
size_t length;
size_t pos, off, len;
size_t nkeys, keyinfolen;
size_t nuids, uidinfolen;
size_t nserial;
buffer = _keybox_get_blob_image (blob, &length);
if (length < 40)
return 0; /* blob too short */
/*keys*/
nkeys = get16 (buffer + 16);
keyinfolen = get16 (buffer + 18 );
if (keyinfolen < 28)
return 0; /* invalid blob */
pos = 20 + keyinfolen*nkeys;
if (pos+2 > length)
return 0; /* out of bounds */
/*serial*/
nserial = get16 (buffer+pos);
pos += 2 + nserial;
if (pos+4 > length)
return 0; /* out of bounds */
/* user ids*/
nuids = get16 (buffer + pos); pos += 2;
uidinfolen = get16 (buffer + pos); pos += 2;
if (uidinfolen < 12 /* should add a: || nuidinfolen > MAX_UIDINFOLEN */)
return 0; /* invalid blob */
if (pos + uidinfolen*nuids > length)
return 0; /* out of bounds */
if (idx > nuids)
return 0; /* no user ID with that idx */
pos += idx*uidinfolen;
off = get32 (buffer+pos);
len = get32 (buffer+pos+4);
if (off+len > length)
return 0; /* out of bounds */
if (len < 2)
return 0; /* empty name or 0 not stored */
len--;
return len == namelen && !memcmp (buffer+off, name, len);
}
/*
The has_foo functions are used as helpers for search
*/
#if 0
static int
has_short_kid (KEYBOXBLOB blob, u32 kid)
{
return 0;
}
static int
has_long_kid (KEYBOXBLOB blob, u32 *kid)
{
return 0;
}
#endif
static int
has_fingerprint (KEYBOXBLOB blob, const unsigned char *fpr)
{
return 0;
}
static int
has_issuer (KEYBOXBLOB blob, const char *name)
{
size_t namelen;
return_val_if_fail (name, 0);
if (blob_get_type (blob) != BLOBTYPE_X509)
return 0;
namelen = strlen (name);
return blob_cmp_name (blob, 0 /* issuer */, name, namelen);
}
static int
has_issuer_sn (KEYBOXBLOB blob, const char *name, const unsigned char *sn)
{
size_t namelen;
return_val_if_fail (name, 0);
return_val_if_fail (sn, 0);
if (blob_get_type (blob) != BLOBTYPE_X509)
return 0;
namelen = strlen (name);
return (blob_cmp_sn (blob, sn)
&& blob_cmp_name (blob, 0 /* issuer */, name, namelen));
}
/*
The search API
*/
int
keybox_search_reset (KEYBOX_HANDLE hd)
{
if (!hd)
return KEYBOX_Invalid_Value;
if (hd->found.blob)
{
_keybox_release_blob (hd->found.blob);
hd->found.blob = NULL;
}
if (hd->fp)
{
fclose (hd->fp);
hd->fp = NULL;
}
hd->error = 0;
hd->eof = 0;
return 0;
}
int
keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc)
{
int rc;
size_t n;
int need_words, any_skip;
KEYBOXBLOB blob = NULL;
if (!hd)
return KEYBOX_Invalid_Value;
/* clear last found result */
if (hd->found.blob)
{
_keybox_release_blob (hd->found.blob);
hd->found.blob = NULL;
}
if (hd->error)
return hd->error; /* still in error state */
if (hd->eof)
return -1; /* still EOF */
/* figure out what information we need */
need_words = any_skip = 0;
for (n=0; n < ndesc; n++)
{
switch (desc[n].mode)
{
case KEYDB_SEARCH_MODE_WORDS:
need_words = 1;
break;
case KEYDB_SEARCH_MODE_FIRST:
/* always restart the search in this mode */
keybox_search_reset (hd);
break;
default:
break;
}
if (desc[n].skipfnc)
any_skip = 1;
}
if (!hd->fp)
{
hd->fp = fopen (hd->kb->fname, "rb");
if (!hd->fp)
return (hd->error = KEYBOX_File_Open_Error);
}
for (;;)
{
_keybox_release_blob (blob); blob = NULL;
rc = _keybox_read_blob (&blob, hd->fp);
if (rc)
break;
for (n=0; n < ndesc; n++)
{
switch (desc[n].mode)
{
case KEYDB_SEARCH_MODE_NONE:
never_reached ();
break;
case KEYDB_SEARCH_MODE_EXACT:
case KEYDB_SEARCH_MODE_SUBSTR:
case KEYDB_SEARCH_MODE_MAIL:
case KEYDB_SEARCH_MODE_MAILSUB:
case KEYDB_SEARCH_MODE_MAILEND:
case KEYDB_SEARCH_MODE_WORDS:
never_reached (); /* not yet implemented */
break;
case KEYDB_SEARCH_MODE_ISSUER:
if (has_issuer (blob, desc[n].u.name))
goto found;
break;
case KEYDB_SEARCH_MODE_ISSUER_SN:
if (has_issuer_sn (blob, desc[n].u.name, desc[n].sn))
goto found;
break;
case KEYDB_SEARCH_MODE_SHORT_KID:
/* if (has_short_kid (blob, desc[n].u.kid[1])) */
/* goto found; */
break;
case KEYDB_SEARCH_MODE_LONG_KID:
/* if (has_long_kid (blob, desc[n].u.kid)) */
/* goto found; */
break;
case KEYDB_SEARCH_MODE_FPR:
if (has_fingerprint (blob, desc[n].u.fpr))
goto found;
break;
case KEYDB_SEARCH_MODE_FIRST:
goto found;
break;
case KEYDB_SEARCH_MODE_NEXT:
goto found;
break;
default:
rc = KEYBOX_Invalid_Value;
goto found;
}
}
continue;
found:
for (n=any_skip?0:ndesc; n < ndesc; n++)
{
/* if (desc[n].skipfnc */
/* && desc[n].skipfnc (desc[n].skipfncvalue, aki)) */
/* break; */
}
if (n == ndesc)
break; /* got it */
}
if (!rc)
{
hd->found.blob = blob;
}
else if (rc == -1)
{
_keybox_release_blob (blob);
hd->eof = 1;
}
else
{
_keybox_release_blob (blob);
hd->error = rc;
}
return rc;
}
/*
Functions to return a certificate or a keyblock. To be used after
a successful search operation.
*/
#ifdef KEYBOX_WITH_X509
/*
Return the last found cert. Caller must free it.
*/
int
keybox_blob_has_fpr ( KEYBOXBLOB blob, const byte *fpr )
keybox_get_cert (KEYBOX_HANDLE hd, KsbaCert *r_cert)
{
ulong n, nkeys, keyinfolen;
const byte *p, *pend;
byte *buffer = blob->blob;
size_t buflen = blob->bloblen;
const unsigned char *buffer;
size_t length;
size_t cert_off, cert_len;
KsbaReader reader = NULL;
KsbaCert cert = NULL;
int rc;
if ( buflen < 40 )
return GPGERR_GENERAL; /* blob too short */
n = get32( buffer );
if ( n > buflen )
return GPGERR_GENERAL; /* blob larger than announced length */
buflen = n; /* ignore trailing stuff */
pend = buffer + n - 1;
if (!hd)
return KEYBOX_Invalid_Value;
if (!hd->found.blob)
return KEYBOX_Nothing_Found;
if ( buffer[4] != 2 )
return GPGERR_GENERAL; /* invalid blob type */
if ( buffer[5] != 1 )
return GPGERR_GENERAL; /* invalid blob format version */
if (blob_get_type (hd->found.blob) != BLOBTYPE_X509)
return KEYBOX_Wrong_Blob_Type;
nkeys = get16( buffer + 16 );
keyinfolen = get16( buffer + 18 );
p = buffer + 20;
for(n=0; n < nkeys; n++, p += keyinfolen ) {
if ( p+20 > pend )
return GPGERR_GENERAL; /* blob shorter than required */
if (!memcmp ( p, fpr, 20 ) )
return 0; /* found */
}
return -1;
}
buffer = _keybox_get_blob_image (hd->found.blob, &length);
if (length < 40)
return KEYBOX_Blob_Too_Short;
cert_off = get32 (buffer+8);
cert_len = get32 (buffer+12);
if (cert_off+cert_len > length)
return KEYBOX_Blob_Too_Short;
/****************
* Check whether the given keyID (20 bytes) is in the
* given keyblob.
* Return: 0 = found
* -1 = not found
other = error (fixme: do not always return gpgerr_general)
*/
int
keybox_blob_has_kid ( KEYBOXBLOB blob, const byte *keyidbuf, size_t keyidlen )
{
ulong n, nkeys, keyinfolen, off;
const byte *p, *pend;
byte *buffer = blob->blob;
size_t buflen = blob->bloblen;
if ( buflen < 40 )
return GPGERR_GENERAL; /* blob too short */
n = get32( buffer );
if ( n > buflen )
return GPGERR_GENERAL; /* blob larger than announced length */
buflen = n; /* ignore trailing stuff */
pend = buffer + n - 1;
if ( buffer[4] != 2 )
return GPGERR_GENERAL; /* invalid blob type */
if ( buffer[5] != 1 )
return GPGERR_GENERAL; /* invalid blob format version */
nkeys = get16( buffer + 16 );
keyinfolen = get16( buffer + 18 );
p = buffer + 20;
for(n=0; n < nkeys; n++, p += keyinfolen ) {
if ( p+24 > pend )
return GPGERR_GENERAL; /* blob shorter than required */
off = get32 ( p + 20 );
if (keyidlen < 8 ) /* actually keyidlen may either be 4 or 8 */
off +=4;
if ( off+keyidlen > buflen )
return GPGERR_GENERAL; /* offset out of bounds */
if ( !memcmp ( buffer+off, keyidbuf, keyidlen ) )
return 0; /* found */
}
return -1;
}
int
keybox_blob_has_uid ( KEYBOXBLOB blob,
int (*cmp)(const byte *, size_t, void *), void *opaque )
{
ulong n, nuids, uidinfolen, off, len;
const byte *p, *pend;
byte *buffer = blob->blob;
size_t buflen = blob->bloblen;
if ( buflen < 40 )
return GPGERR_GENERAL; /* blob too short */
n = get32( buffer );
if ( n > buflen )
return GPGERR_GENERAL; /* blob larger than announced length */
buflen = n; /* ignore trailing stuff */
pend = buffer + n - 1;
if ( buffer[4] != 2 )
return GPGERR_GENERAL; /* invalid blob type */
if ( buffer[5] != 1 )
return GPGERR_GENERAL; /* invalid blob format version */
p = buffer + 20 + get16( buffer + 16 ) * get16( buffer + 18 );
if ( p+4 > pend )
return GPGERR_GENERAL; /* blob shorter than required */
nuids = get16( p ); p+= 2;
uidinfolen = get16( p ); p+=2;
for(n=0; n < nuids; n++, p += uidinfolen ) {
if ( p+8 > pend )
return GPGERR_GENERAL; /* blob shorter than required */
off = get32 ( p );
len = get32 ( p + 4 );
if ( off+len > buflen )
return GPGERR_GENERAL; /* offset out of bounds */
if ( (*cmp) ( buffer+off, len, opaque ) )
return 0; /* found */
reader = ksba_reader_new ();
if (!reader)
return KEYBOX_Out_Of_Core;
rc = ksba_reader_set_mem (reader, buffer+cert_off, cert_len);
if (rc)
{
ksba_reader_release (reader);
/* fixme: need to map the error codes */
return KEYBOX_General_Error;
}
return -1;
cert = ksba_cert_new ();
if (!cert)
{
ksba_reader_release (reader);
return KEYBOX_Out_Of_Core;
}
rc = ksba_cert_read_der (cert, reader);
if (rc)
{
ksba_cert_release (cert);
ksba_reader_release (reader);
/* fixme: need to map the error codes */
return KEYBOX_General_Error;
}
*r_cert = cert;
ksba_reader_release (reader);
return 0;
}
#endif /*KEYBOX_WITH_X509*/