mirror of
git://git.gnupg.org/gnupg.git
synced 2025-07-02 22:46:30 +02:00
This commit was manufactured by cvs2svn to create branch
'GNUPG-1-9-BRANCH'.
This commit is contained in:
parent
a3d4ac6f3e
commit
7250331472
77 changed files with 58548 additions and 0 deletions
119
kbx/ChangeLog
Normal file
119
kbx/ChangeLog
Normal file
|
@ -0,0 +1,119 @@
|
|||
2003-06-03 Werner Koch <wk@gnupg.org>
|
||||
|
||||
Changed all error codes in all files to the new libgpg-error scheme.
|
||||
|
||||
* keybox-defs.h: Include gpg-error.h .
|
||||
(KeyboxError): Removed.
|
||||
* Makefile.am: Removed keybox-error.c stuff.
|
||||
|
||||
2002-11-14 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* keybox-search.c (blob_cmp_name) <compare all names>: Fixed
|
||||
length compare; there is no 0 stored since nearly a year.
|
||||
|
||||
2002-10-31 Neal H. Walfield <neal@g10code.de>
|
||||
|
||||
* Makefile.am (AM_CPPFLAGS): Fix ytpo.
|
||||
|
||||
2002-08-10 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* keybox-search.c (blob_cmp_fpr_part): New.
|
||||
(has_short_kid, has_long_kid): Implemented.
|
||||
|
||||
2002-07-22 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* keybox-defs.h: New BLOBTYPTE_EMPTY.
|
||||
* keybox-dump.c (_keybox_dump_blob): Handle new type.
|
||||
* keybox-file.c (_keybox_read_blob): Skip over empty blobs. Store
|
||||
the file offset.
|
||||
* keybox-blob.c (_keybox_new_blob): Add new arg OFF.
|
||||
(_keybox_get_blob_fileoffset): New.
|
||||
* keybox-update.c (keybox_delete): Implemented.
|
||||
|
||||
2002-06-19 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* keybox-init.c (keybox_set_ephemeral): New.
|
||||
* keybox-blob.c (create_blob_header): Store ephemeral flag.
|
||||
(_keybox_create_x509_blob): Pass epheermal flag on.
|
||||
* keybox-update.c (keybox_insert_cert): Ditto.
|
||||
* keybox-search.c (blob_get_blob_flags): New.
|
||||
(keybox_search): Ignore ephemeral blobs when not in ephemeral mode.
|
||||
|
||||
* keybox-dump.c (_keybox_dump_blob): Print blob flags as strings.
|
||||
|
||||
2002-02-25 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* keybox-search.c (blob_cmp_mail): Use case-insensitive compare
|
||||
because mail addresses are in general case insensitive (well
|
||||
RFC2822 allows for case sensitive mailbox parts, but this is in
|
||||
general considired a Bad Thing). Add additional substr parameter
|
||||
to allow for substring matches within the mail address. Change
|
||||
all callers to pass this along.
|
||||
(blob_cmp_name): Likewise but do the case-insensitive search only
|
||||
in sub string mode.
|
||||
(keybox_search): Implement MAILSUB and SUBSTR mode.
|
||||
|
||||
2002-01-21 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* keybox-search.c (keybox_search): Allow KEYDB_SEARCH_MODE_FPR20.
|
||||
|
||||
2002-01-15 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* keybox-search.c (blob_cmp_fpr): New.
|
||||
(has_fingerprint): Implemented;
|
||||
|
||||
2001-12-20 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* keybox-blob.c (_keybox_create_x509_blob): Skip the leading
|
||||
parenthesis of the serial number's S-exp.
|
||||
(_keybox_create_x509_blob): And fixed length calculation.
|
||||
(create_blob_header): Don't add an offset when writing the serial.
|
||||
|
||||
2001-12-18 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* Makefile.am (AM_CPPFLAGS): Add flags for libksba
|
||||
|
||||
* keybox-blob.c (_keybox_create_x509_blob): Use
|
||||
gcry_sexp_canon_len to get the length of the serial number.
|
||||
(_keybox_release_blob): Need to use a new serialbuf to free the memory.
|
||||
|
||||
2001-12-17 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* keybox-search.c: Changed the way the serial number is
|
||||
represented.
|
||||
|
||||
2001-12-15 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* keybox-search.c (blob_cmp_name): There is no terminating 0 stored
|
||||
for the uid; fixed length compare.
|
||||
|
||||
2001-12-14 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* keybox-blob.c (x509_email_kludge): New.
|
||||
(_keybox_create_x509_blob): Insert an extra email address if the
|
||||
subject's DN has an email part.
|
||||
* keybox-defs.h: Added the xtoi_2 and digitp macros.
|
||||
|
||||
2001-12-13 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* keybox-search.c (blob_cmp_name): Kludge to allow searching for
|
||||
more than one name.
|
||||
(has_subject_or_alt): New.
|
||||
(blob_cmp_mail): New.
|
||||
(has_mail): New.
|
||||
(keybox_search): Implemented exact search and exact mail search.
|
||||
|
||||
* kbx/keybox-blob.c (_keybox_create_x509_blob): Insert alternate
|
||||
names.
|
||||
|
||||
|
||||
Copyright 2001 g10 Code GmbH
|
||||
|
||||
This file is free software; as a special exception the author gives
|
||||
unlimited permission to copy and/or distribute it, with or without
|
||||
modifications, as long as this notice is preserved.
|
||||
|
||||
This file is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
186
kbx/keybox-defs.h
Normal file
186
kbx/keybox-defs.h
Normal file
|
@ -0,0 +1,186 @@
|
|||
/* keybox-defs.h - interal Keybox defintions
|
||||
* Copyright (C) 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#ifndef KEYBOX_DEFS_H
|
||||
#define KEYBOX_DEFS_H 1
|
||||
|
||||
#include <sys/types.h> /* off_t */
|
||||
#include "keybox.h"
|
||||
|
||||
#ifdef GPG_ERR_SOURCE_DEFAULT
|
||||
#error GPG_ERR_SOURCE_DEFAULT already defined
|
||||
#endif
|
||||
#define GPG_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_KEYBOX
|
||||
#include <gpg-error.h>
|
||||
|
||||
|
||||
#ifndef HAVE_BYTE_TYPEDEF
|
||||
typedef unsigned char byte; /* fixme */
|
||||
#endif
|
||||
#ifndef HAVE_U16_TYPEDEF
|
||||
typedef unsigned short u16; /* fixme */
|
||||
#endif
|
||||
#ifndef HAVE_U32_TYPEDEF
|
||||
typedef unsigned int u32; /* fixme */
|
||||
#endif
|
||||
|
||||
enum {
|
||||
BLOBTYPE_EMPTY = 0,
|
||||
BLOBTYPE_HEADER = 1,
|
||||
BLOBTYPE_PGP = 2,
|
||||
BLOBTYPE_X509 = 3
|
||||
};
|
||||
|
||||
|
||||
typedef struct keyboxblob *KEYBOXBLOB;
|
||||
|
||||
|
||||
typedef struct keybox_name *KB_NAME;
|
||||
typedef struct keybox_name const * CONST_KB_NAME;
|
||||
struct keybox_name {
|
||||
struct keybox_name *next;
|
||||
int secret;
|
||||
/*DOTLOCK lockhd;*/
|
||||
int is_locked;
|
||||
int did_full_scan;
|
||||
char fname[1];
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct keybox_handle {
|
||||
CONST_KB_NAME kb;
|
||||
int secret; /* this is for a secret keybox */
|
||||
FILE *fp;
|
||||
int eof;
|
||||
int error;
|
||||
int ephemeral;
|
||||
struct {
|
||||
KEYBOXBLOB blob;
|
||||
off_t offset;
|
||||
size_t pk_no;
|
||||
size_t uid_no;
|
||||
unsigned int n_packets; /*used for delete and update*/
|
||||
} found;
|
||||
struct {
|
||||
char *name;
|
||||
char *pattern;
|
||||
} word_match;
|
||||
};
|
||||
|
||||
|
||||
/* Don't know whether this is needed: */
|
||||
/* static struct { */
|
||||
/* const char *homedir; */
|
||||
/* int dry_run; */
|
||||
/* int quiet; */
|
||||
/* int verbose; */
|
||||
/* int preserve_permissions; */
|
||||
/* } keybox_opt; */
|
||||
|
||||
|
||||
/*-- keybox-blob.c --*/
|
||||
#ifdef KEYBOX_WITH_OPENPGP
|
||||
/* fixme */
|
||||
#endif /*KEYBOX_WITH_OPENPGP*/
|
||||
#ifdef KEYBOX_WITH_X509
|
||||
int _keybox_create_x509_blob (KEYBOXBLOB *r_blob, KsbaCert cert,
|
||||
unsigned char *sha1_digest, int as_ephemeral);
|
||||
#endif /*KEYBOX_WITH_X509*/
|
||||
|
||||
int _keybox_new_blob (KEYBOXBLOB *r_blob, char *image, size_t imagelen,
|
||||
off_t off);
|
||||
void _keybox_release_blob (KEYBOXBLOB blob);
|
||||
const char *_keybox_get_blob_image (KEYBOXBLOB blob, size_t *n);
|
||||
off_t _keybox_get_blob_fileoffset (KEYBOXBLOB blob);
|
||||
|
||||
/*-- keybox-file.c --*/
|
||||
int _keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp);
|
||||
int _keybox_write_blob (KEYBOXBLOB blob, FILE *fp);
|
||||
|
||||
/*-- keybox-dump.c --*/
|
||||
int _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp);
|
||||
int _keybox_dump_file (const char *filename, FILE *outfp);
|
||||
|
||||
|
||||
/*-- keybox-util.c --*/
|
||||
void *_keybox_malloc (size_t n);
|
||||
void *_keybox_calloc (size_t n, size_t m);
|
||||
void *_keybox_realloc (void *p, size_t n);
|
||||
void _keybox_free (void *p);
|
||||
|
||||
#define xtrymalloc(a) _keybox_malloc ((a))
|
||||
#define xtrycalloc(a,b) _keybox_calloc ((a),(b))
|
||||
#define xtryrealloc(a,b) _keybox_realloc((a),(b))
|
||||
#define xfree(a) _keybox_free ((a))
|
||||
|
||||
|
||||
#define DIM(v) (sizeof(v)/sizeof((v)[0]))
|
||||
#define DIMof(type,member) DIM(((type *)0)->member)
|
||||
#ifndef STR
|
||||
#define STR(v) #v
|
||||
#endif
|
||||
#define STR2(v) STR(v)
|
||||
|
||||
/*
|
||||
a couple of handy macros
|
||||
*/
|
||||
|
||||
#define return_if_fail(expr) do { \
|
||||
if (!(expr)) { \
|
||||
fprintf (stderr, "%s:%d: assertion `%s' failed\n", \
|
||||
__FILE__, __LINE__, #expr ); \
|
||||
return; \
|
||||
} } while (0)
|
||||
#define return_null_if_fail(expr) do { \
|
||||
if (!(expr)) { \
|
||||
fprintf (stderr, "%s:%d: assertion `%s' failed\n", \
|
||||
__FILE__, __LINE__, #expr ); \
|
||||
return NULL; \
|
||||
} } while (0)
|
||||
#define return_val_if_fail(expr,val) do { \
|
||||
if (!(expr)) { \
|
||||
fprintf (stderr, "%s:%d: assertion `%s' failed\n", \
|
||||
__FILE__, __LINE__, #expr ); \
|
||||
return (val); \
|
||||
} } while (0)
|
||||
#define never_reached() do { \
|
||||
fprintf (stderr, "%s:%d: oops; should never get here\n", \
|
||||
__FILE__, __LINE__ ); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* some macros to replace ctype ones and avoid locale problems */
|
||||
#define digitp(p) (*(p) >= '0' && *(p) <= '9')
|
||||
#define hexdigitp(a) (digitp (a) \
|
||||
|| (*(a) >= 'A' && *(a) <= 'F') \
|
||||
|| (*(a) >= 'a' && *(a) <= 'f'))
|
||||
/* the atoi macros assume that the buffer has only valid digits */
|
||||
#define atoi_1(p) (*(p) - '0' )
|
||||
#define atoi_2(p) ((atoi_1(p) * 10) + atoi_1((p)+1))
|
||||
#define atoi_4(p) ((atoi_2(p) * 100) + atoi_2((p)+2))
|
||||
#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
|
||||
*(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
|
||||
#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
|
||||
|
||||
|
||||
#endif /*KEYBOX_DEFS_H*/
|
||||
|
||||
|
346
kbx/keybox-dump.c
Normal file
346
kbx/keybox-dump.c
Normal file
|
@ -0,0 +1,346 @@
|
|||
/* keybox-dump.c - Debug helpers
|
||||
* Copyright (C) 2001, 2003 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
static ulong
|
||||
get16 (const byte *buffer)
|
||||
{
|
||||
ulong a;
|
||||
a = *buffer << 8;
|
||||
a |= buffer[1];
|
||||
return a;
|
||||
}
|
||||
|
||||
void
|
||||
print_string (FILE *fp, const byte *p, size_t n, int delim)
|
||||
{
|
||||
for ( ; n; n--, p++ )
|
||||
{
|
||||
if (*p < 0x20 || (*p >= 0x7f && *p < 0xa0) || *p == delim)
|
||||
{
|
||||
putc('\\', fp);
|
||||
if( *p == '\n' )
|
||||
putc('n', fp);
|
||||
else if( *p == '\r' )
|
||||
putc('r', fp);
|
||||
else if( *p == '\f' )
|
||||
putc('f', fp);
|
||||
else if( *p == '\v' )
|
||||
putc('v', fp);
|
||||
else if( *p == '\b' )
|
||||
putc('b', fp);
|
||||
else if( !*p )
|
||||
putc('0', fp);
|
||||
else
|
||||
fprintf(fp, "x%02x", *p );
|
||||
}
|
||||
else
|
||||
putc(*p, fp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
dump_header_blob (const byte *buffer, size_t length, FILE *fp)
|
||||
{
|
||||
fprintf (fp, "Version: %d\n", buffer[5]);
|
||||
if ( memcmp (buffer+8, "KBXf", 4))
|
||||
fprintf (fp, "[Error: invalid magic number]\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Dump one block to FP */
|
||||
int
|
||||
_keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
|
||||
{
|
||||
const byte *buffer;
|
||||
size_t length;
|
||||
int type;
|
||||
ulong n, nkeys, keyinfolen;
|
||||
ulong nuids, uidinfolen;
|
||||
ulong nsigs, siginfolen;
|
||||
ulong rawdata_off, rawdata_len;
|
||||
ulong nserial;
|
||||
const byte *p;
|
||||
|
||||
buffer = _keybox_get_blob_image (blob, &length);
|
||||
|
||||
if (length < 40)
|
||||
{
|
||||
fprintf (fp, "[blob too short]\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
n = get32( buffer );
|
||||
if (n > length)
|
||||
fprintf (fp, "[blob larger than length - output truncated]\n");
|
||||
else
|
||||
length = n; /* ignore the rest */
|
||||
|
||||
fprintf (fp, "Length: %lu\n", n );
|
||||
type = buffer[4];
|
||||
switch (type)
|
||||
{
|
||||
case BLOBTYPE_EMPTY:
|
||||
fprintf (fp, "Type: Empty\n");
|
||||
return 0;
|
||||
|
||||
case BLOBTYPE_HEADER:
|
||||
fprintf (fp, "Type: Header\n");
|
||||
return dump_header_blob (buffer, length, fp);
|
||||
case BLOBTYPE_PGP:
|
||||
fprintf (fp, "Type: OpenPGP\n");
|
||||
break;
|
||||
case BLOBTYPE_X509:
|
||||
fprintf (fp, "Type: X.509\n");
|
||||
break;
|
||||
default:
|
||||
fprintf (fp, "Type: %d\n", type);
|
||||
fprintf (fp, "[can't dump this blob type]\n");
|
||||
return 0;
|
||||
}
|
||||
fprintf (fp, "Version: %d\n", buffer[5]);
|
||||
|
||||
n = get16 (buffer + 6);
|
||||
fprintf( fp, "Blob-Flags: %04lX", n);
|
||||
if (n)
|
||||
{
|
||||
int any = 0;
|
||||
|
||||
fputs (" (", fp);
|
||||
if ((n & 1))
|
||||
{
|
||||
fputs ("secret", fp);
|
||||
any++;
|
||||
}
|
||||
if ((n & 2))
|
||||
{
|
||||
if (any)
|
||||
putc (',', fp);
|
||||
fputs ("ephemeral", fp);
|
||||
any++;
|
||||
}
|
||||
putc (')', fp);
|
||||
}
|
||||
putc ('\n', fp);
|
||||
|
||||
rawdata_off = get32 (buffer + 8);
|
||||
rawdata_len = get32 (buffer + 12);
|
||||
|
||||
fprintf( fp, "Data-Offset: %lu\n", rawdata_off );
|
||||
fprintf( fp, "Data-Length: %lu\n", rawdata_len );
|
||||
|
||||
nkeys = get16 (buffer + 16);
|
||||
fprintf (fp, "Key-Count: %lu\n", nkeys );
|
||||
if (!nkeys)
|
||||
fprintf (fp, "[Error: no keys]\n");
|
||||
if (nkeys > 1 && type == BLOBTYPE_X509)
|
||||
fprintf (fp, "[Error: only one key allowed for X509]\n");
|
||||
|
||||
keyinfolen = get16 (buffer + 18 );
|
||||
fprintf (fp, "Key-Info-Length: %lu\n", keyinfolen);
|
||||
/* fixme: check bounds */
|
||||
p = buffer + 20;
|
||||
for (n=0; n < nkeys; n++, p += keyinfolen)
|
||||
{
|
||||
int i;
|
||||
ulong kidoff, kflags;
|
||||
|
||||
fprintf (fp, "Key-Fpr[%lu]: ", n );
|
||||
for (i=0; i < 20; i++ )
|
||||
fprintf (fp, "%02X", p[i]);
|
||||
kidoff = get32 (p + 20);
|
||||
fprintf (fp, "\nKey-Kid-Off[%lu]: %lu\n", n, kidoff );
|
||||
fprintf (fp, "Key-Kid[%lu]: ", n );
|
||||
/* fixme: check bounds */
|
||||
for (i=0; i < 8; i++ )
|
||||
fprintf (fp, "%02X", buffer[kidoff+i] );
|
||||
kflags = get16 (p + 24 );
|
||||
fprintf( fp, "\nKey-Flags[%lu]: %04lX\n", n, kflags);
|
||||
}
|
||||
|
||||
/* serial number */
|
||||
fputs ("Serial-No: ", fp);
|
||||
nserial = get16 (p);
|
||||
p += 2;
|
||||
if (!nserial)
|
||||
fputs ("none", fp);
|
||||
else
|
||||
{
|
||||
for (; nserial; nserial--, p++)
|
||||
fprintf (fp, "%02X", *p);
|
||||
}
|
||||
putc ('\n', fp);
|
||||
|
||||
/* user IDs */
|
||||
nuids = get16 (p);
|
||||
fprintf (fp, "Uid-Count: %lu\n", nuids );
|
||||
uidinfolen = get16 (p + 2);
|
||||
fprintf (fp, "Uid-Info-Length: %lu\n", uidinfolen);
|
||||
/* fixme: check bounds */
|
||||
p += 4;
|
||||
for (n=0; n < nuids; n++, p += uidinfolen)
|
||||
{
|
||||
ulong uidoff, uidlen, uflags;
|
||||
|
||||
uidoff = get32( p );
|
||||
uidlen = get32( p+4 );
|
||||
if (type == BLOBTYPE_X509 && !n)
|
||||
{
|
||||
fprintf (fp, "Issuer-Off: %lu\n", uidoff );
|
||||
fprintf (fp, "Issuer-Len: %lu\n", uidlen );
|
||||
fprintf (fp, "Issuer: \"");
|
||||
}
|
||||
else if (type == BLOBTYPE_X509 && n == 1)
|
||||
{
|
||||
fprintf (fp, "Subject-Off: %lu\n", uidoff );
|
||||
fprintf (fp, "Subject-Len: %lu\n", uidlen );
|
||||
fprintf (fp, "Subject: \"");
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (fp, "Uid-Off[%lu]: %lu\n", n, uidoff );
|
||||
fprintf (fp, "Uid-Len[%lu]: %lu\n", n, uidlen );
|
||||
fprintf (fp, "Uid[%lu]: \"", n );
|
||||
}
|
||||
print_string (fp, buffer+uidoff, uidlen, '\"');
|
||||
fputs ("\"\n", fp);
|
||||
uflags = get16 (p + 8);
|
||||
if (type == BLOBTYPE_X509 && !n)
|
||||
{
|
||||
fprintf (fp, "Issuer-Flags: %04lX\n", uflags );
|
||||
fprintf (fp, "Issuer-Validity: %d\n", p[10] );
|
||||
}
|
||||
else if (type == BLOBTYPE_X509 && n == 1)
|
||||
{
|
||||
fprintf (fp, "Subject-Flags: %04lX\n", uflags );
|
||||
fprintf (fp, "Subject-Validity: %d\n", p[10] );
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (fp, "Uid-Flags[%lu]: %04lX\n", n, uflags );
|
||||
fprintf (fp, "Uid-Validity[%lu]: %d\n", n, p[10] );
|
||||
}
|
||||
}
|
||||
|
||||
nsigs = get16 (p);
|
||||
fprintf (fp, "Sig-Count: %lu\n", nsigs );
|
||||
siginfolen = get16 (p + 2);
|
||||
fprintf (fp, "Sig-Info-Length: %lu\n", siginfolen );
|
||||
/* fixme: check bounds */
|
||||
p += 4;
|
||||
for (n=0; n < nsigs; n++, p += siginfolen)
|
||||
{
|
||||
ulong sflags;
|
||||
|
||||
sflags = get32 (p);
|
||||
fprintf (fp, "Sig-Expire[%lu]: ", n );
|
||||
if (!sflags)
|
||||
fputs ("[not checked]", fp);
|
||||
else if (sflags == 1 )
|
||||
fputs ("[missing key]", fp);
|
||||
else if (sflags == 2 )
|
||||
fputs ("[bad signature]", fp);
|
||||
else if (sflags < 0x10000000)
|
||||
fprintf (fp, "[bad flag %0lx]", sflags);
|
||||
else if (sflags == 0xffffffff)
|
||||
fputs ("0", fp );
|
||||
else
|
||||
fputs ("a time"/*strtimestamp( sflags )*/, fp );
|
||||
putc ('\n', fp );
|
||||
}
|
||||
|
||||
fprintf (fp, "Ownertrust: %d\n", p[0] );
|
||||
fprintf (fp, "All-Validity: %d\n", p[1] );
|
||||
p += 4;
|
||||
n = get32 (p); p += 4;
|
||||
fprintf (fp, "Recheck-After: %s\n", /*n? strtimestamp(n) :*/ "0" );
|
||||
n = get32 (p ); p += 4;
|
||||
fprintf( fp, "Latest-Timestamp: %s\n", "0"/*strtimestamp(n)*/ );
|
||||
n = get32 (p ); p += 4;
|
||||
fprintf (fp, "Created-At: %s\n", "0"/*strtimestamp(n)*/ );
|
||||
n = get32 (p ); p += 4;
|
||||
fprintf (fp, "Reserved-Space: %lu\n", n );
|
||||
|
||||
/* check that the keyblock is at the correct offset and other bounds */
|
||||
/*fprintf (fp, "Blob-Checksum: [MD5-hash]\n");*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
_keybox_dump_file (const char *filename, FILE *outfp)
|
||||
{
|
||||
FILE *fp;
|
||||
KEYBOXBLOB blob;
|
||||
int rc;
|
||||
unsigned long count = 0;
|
||||
|
||||
if (!filename)
|
||||
{
|
||||
filename = "-";
|
||||
fp = stdin;
|
||||
}
|
||||
else
|
||||
fp = fopen (filename, "rb");
|
||||
if (!fp)
|
||||
{
|
||||
gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
|
||||
fprintf (outfp, "can't open `%s': %s\n", filename, strerror(errno));
|
||||
return tmperr;
|
||||
}
|
||||
|
||||
while ( !(rc = _keybox_read_blob (&blob, fp)) )
|
||||
{
|
||||
fprintf (outfp, "BEGIN-RECORD: %lu\n", count );
|
||||
_keybox_dump_blob (blob, outfp);
|
||||
_keybox_release_blob (blob);
|
||||
fprintf (outfp, "END-RECORD\n");
|
||||
count++;
|
||||
}
|
||||
if (rc == -1)
|
||||
rc = 0;
|
||||
if (rc)
|
||||
fprintf (outfp, "error reading `%s': %s\n", filename, gpg_strerror (rc));
|
||||
|
||||
if (fp != stdin)
|
||||
fclose (fp);
|
||||
return rc;
|
||||
}
|
102
kbx/keybox-file.c
Normal file
102
kbx/keybox-file.c
Normal file
|
@ -0,0 +1,102 @@
|
|||
/* keybox-file.c - file oeprations
|
||||
* Copyright (C) 2001, 2003 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "keybox-defs.h"
|
||||
|
||||
/* Read a block at the current postion and return it in r_blob.
|
||||
r_blob may be NULL to simply skip the current block */
|
||||
int
|
||||
_keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp)
|
||||
{
|
||||
char *image;
|
||||
size_t imagelen = 0;
|
||||
int c1, c2, c3, c4, type;
|
||||
int rc;
|
||||
off_t off;
|
||||
|
||||
again:
|
||||
*r_blob = NULL;
|
||||
off = ftello (fp);
|
||||
if (off == (off_t)-1)
|
||||
return gpg_error (gpg_err_code_from_errno (errno));
|
||||
|
||||
if ((c1 = getc (fp)) == EOF
|
||||
|| (c2 = getc (fp)) == EOF
|
||||
|| (c3 = getc (fp)) == EOF
|
||||
|| (c4 = getc (fp)) == EOF
|
||||
|| (type = getc (fp)) == EOF)
|
||||
{
|
||||
if ( c1 == EOF && !ferror (fp) )
|
||||
return -1; /* eof */
|
||||
return gpg_error (gpg_err_code_from_errno (errno));
|
||||
}
|
||||
|
||||
imagelen = (c1 << 24) | (c2 << 16) | (c3 << 8 ) | c4;
|
||||
if (imagelen > 500000) /* sanity check */
|
||||
return gpg_error (GPG_ERR_TOO_LARGE);
|
||||
|
||||
if (imagelen < 5)
|
||||
return gpg_error (GPG_ERR_TOO_SHORT);
|
||||
|
||||
if (!type)
|
||||
{
|
||||
/* special treatment for empty blobs. */
|
||||
if (fseek (fp, imagelen-5, SEEK_CUR))
|
||||
return gpg_error (gpg_err_code_from_errno (errno));
|
||||
goto again;
|
||||
}
|
||||
|
||||
image = xtrymalloc (imagelen);
|
||||
if (!image)
|
||||
return gpg_error (gpg_err_code_from_errno (errno));
|
||||
|
||||
image[0] = c1; image[1] = c2; image[2] = c3; image[3] = c4; image[4] = type;
|
||||
if (fread (image+5, imagelen-5, 1, fp) != 1)
|
||||
{
|
||||
gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
|
||||
xfree (image);
|
||||
return tmperr;
|
||||
}
|
||||
|
||||
rc = r_blob? _keybox_new_blob (r_blob, image, imagelen, off) : 0;
|
||||
if (rc || !r_blob)
|
||||
xfree (image);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/* Write the block to the current file position */
|
||||
int
|
||||
_keybox_write_blob (KEYBOXBLOB blob, FILE *fp)
|
||||
{
|
||||
const char *image;
|
||||
size_t length;
|
||||
|
||||
image = _keybox_get_blob_image (blob, &length);
|
||||
if (fwrite (image, length, 1, fp) != 1)
|
||||
return gpg_error (gpg_err_code_from_errno (errno));
|
||||
return 0;
|
||||
}
|
127
kbx/keybox-init.c
Normal file
127
kbx/keybox-init.c
Normal file
|
@ -0,0 +1,127 @@
|
|||
/* keybox-init.c - Initalization of the library
|
||||
* Copyright (C) 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "keybox-defs.h"
|
||||
|
||||
#define compare_filenames strcmp
|
||||
|
||||
static KB_NAME kb_names;
|
||||
|
||||
|
||||
/*
|
||||
Register a filename for plain keybox files. Returns a pointer to be
|
||||
used to create a handles etc or NULL to indicate that it has already
|
||||
been registered */
|
||||
void *
|
||||
keybox_register_file (const char *fname, int secret)
|
||||
{
|
||||
KB_NAME kr;
|
||||
|
||||
for (kr=kb_names; kr; kr = kr->next)
|
||||
{
|
||||
if ( !compare_filenames (kr->fname, fname) )
|
||||
return NULL; /* already registered */
|
||||
}
|
||||
|
||||
kr = xtrymalloc (sizeof *kr + strlen (fname));
|
||||
if (!kr)
|
||||
return NULL;
|
||||
strcpy (kr->fname, fname);
|
||||
kr->secret = !!secret;
|
||||
/* kr->lockhd = NULL;*/
|
||||
kr->is_locked = 0;
|
||||
kr->did_full_scan = 0;
|
||||
/* keep a list of all issued pointers */
|
||||
kr->next = kb_names;
|
||||
kb_names = kr;
|
||||
|
||||
/* create the offset table the first time a function here is used */
|
||||
/* if (!kb_offtbl) */
|
||||
/* kb_offtbl = new_offset_hash_table (); */
|
||||
|
||||
return kr;
|
||||
}
|
||||
|
||||
int
|
||||
keybox_is_writable (void *token)
|
||||
{
|
||||
KB_NAME r = token;
|
||||
|
||||
return r? !access (r->fname, W_OK) : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Create a new handle for the resource associated with TOKEN. SECRET
|
||||
is just a cross-check.
|
||||
|
||||
The returned handle must be released using keybox_release (). */
|
||||
KEYBOX_HANDLE
|
||||
keybox_new (void *token, int secret)
|
||||
{
|
||||
KEYBOX_HANDLE hd;
|
||||
KB_NAME resource = token;
|
||||
|
||||
assert (resource && !resource->secret == !secret);
|
||||
hd = xtrycalloc (1, sizeof *hd);
|
||||
if (hd)
|
||||
{
|
||||
hd->kb = resource;
|
||||
hd->secret = !!secret;
|
||||
}
|
||||
return hd;
|
||||
}
|
||||
|
||||
void
|
||||
keybox_release (KEYBOX_HANDLE hd)
|
||||
{
|
||||
if (!hd)
|
||||
return;
|
||||
_keybox_release_blob (hd->found.blob);
|
||||
xfree (hd->word_match.name);
|
||||
xfree (hd->word_match.pattern);
|
||||
xfree (hd);
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
keybox_get_resource_name (KEYBOX_HANDLE hd)
|
||||
{
|
||||
if (!hd || !hd->kb)
|
||||
return NULL;
|
||||
return hd->kb->fname;
|
||||
}
|
||||
|
||||
int
|
||||
keybox_set_ephemeral (KEYBOX_HANDLE hd, int yes)
|
||||
{
|
||||
if (!hd)
|
||||
return gpg_error (GPG_ERR_INV_HANDLE);
|
||||
hd->ephemeral = yes;
|
||||
return 0;
|
||||
}
|
||||
|
813
kbx/keybox-search.c
Normal file
813
kbx/keybox-search.c
Normal file
|
@ -0,0 +1,813 @@
|
|||
/* keybox-search.c - Search operations
|
||||
* Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "../jnlib/stringhelp.h" /* ascii_xxxx() */
|
||||
#include "keybox-defs.h"
|
||||
|
||||
#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
|
||||
*(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
|
||||
#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
|
||||
|
||||
struct sn_array_s {
|
||||
int snlen;
|
||||
unsigned char *sn;
|
||||
};
|
||||
|
||||
|
||||
|
||||
static ulong
|
||||
get32 (const byte *buffer)
|
||||
{
|
||||
ulong a;
|
||||
a = *buffer << 24;
|
||||
a |= buffer[1] << 16;
|
||||
a |= buffer[2] << 8;
|
||||
a |= buffer[3];
|
||||
return a;
|
||||
}
|
||||
|
||||
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 unsigned int
|
||||
blob_get_blob_flags (KEYBOXBLOB blob)
|
||||
{
|
||||
const unsigned char *buffer;
|
||||
size_t length;
|
||||
|
||||
buffer = _keybox_get_blob_image (blob, &length);
|
||||
if (length < 8)
|
||||
return 0; /* oops */
|
||||
|
||||
return get16 (buffer + 6);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
blob_cmp_sn (KEYBOXBLOB blob, const unsigned char *sn, int snlen)
|
||||
{
|
||||
const unsigned char *buffer;
|
||||
size_t length;
|
||||
size_t pos, off;
|
||||
size_t nkeys, keyinfolen;
|
||||
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);
|
||||
off = pos + 2;
|
||||
if (off+nserial > length)
|
||||
return 0; /* out of bounds */
|
||||
|
||||
return nserial == snlen && !memcmp (buffer+off, sn, snlen);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
blob_cmp_fpr (KEYBOXBLOB blob, const unsigned char *fpr)
|
||||
{
|
||||
const unsigned char *buffer;
|
||||
size_t length;
|
||||
size_t pos, off;
|
||||
size_t nkeys, keyinfolen;
|
||||
int idx;
|
||||
|
||||
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;
|
||||
if (pos + keyinfolen*nkeys > length)
|
||||
return 0; /* out of bounds */
|
||||
|
||||
for (idx=0; idx < nkeys; idx++)
|
||||
{
|
||||
off = pos + idx*keyinfolen;
|
||||
if (!memcmp (buffer + off, fpr, 20))
|
||||
return 1; /* found */
|
||||
}
|
||||
return 0; /* not found */
|
||||
}
|
||||
|
||||
static int
|
||||
blob_cmp_fpr_part (KEYBOXBLOB blob, const unsigned char *fpr,
|
||||
int fproff, int fprlen)
|
||||
{
|
||||
const unsigned char *buffer;
|
||||
size_t length;
|
||||
size_t pos, off;
|
||||
size_t nkeys, keyinfolen;
|
||||
int idx;
|
||||
|
||||
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;
|
||||
if (pos + keyinfolen*nkeys > length)
|
||||
return 0; /* out of bounds */
|
||||
|
||||
for (idx=0; idx < nkeys; idx++)
|
||||
{
|
||||
off = pos + idx*keyinfolen;
|
||||
if (!memcmp (buffer + off + fproff, fpr, fprlen))
|
||||
return 1; /* found */
|
||||
}
|
||||
return 0; /* not found */
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
blob_cmp_name (KEYBOXBLOB blob, int idx,
|
||||
const char *name, size_t namelen, int substr)
|
||||
{
|
||||
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 < 0)
|
||||
{ /* compare all names starting with that (negated) index */
|
||||
idx = -idx;
|
||||
|
||||
for ( ;idx < nuids; idx++)
|
||||
{
|
||||
size_t mypos = pos;
|
||||
|
||||
mypos += idx*uidinfolen;
|
||||
off = get32 (buffer+mypos);
|
||||
len = get32 (buffer+mypos+4);
|
||||
if (off+len > length)
|
||||
return 0; /* error: better stop here out of bounds */
|
||||
if (len < 1)
|
||||
continue; /* empty name */
|
||||
if (substr)
|
||||
{
|
||||
if (ascii_memcasemem (buffer+off, len, name, namelen))
|
||||
return 1; /* found */
|
||||
}
|
||||
else
|
||||
{
|
||||
if (len == namelen && !memcmp (buffer+off, name, len))
|
||||
return 1; /* found */
|
||||
}
|
||||
}
|
||||
return 0; /* not found */
|
||||
}
|
||||
else
|
||||
{
|
||||
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 < 1)
|
||||
return 0; /* empty name */
|
||||
|
||||
if (substr)
|
||||
{
|
||||
return !!ascii_memcasemem (buffer+off, len, name, namelen);
|
||||
}
|
||||
else
|
||||
{
|
||||
return len == namelen && !memcmp (buffer+off, name, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* compare all email addresses of the subject. With SUBSTR given as
|
||||
True a substring search is done in the mail address */
|
||||
static int
|
||||
blob_cmp_mail (KEYBOXBLOB blob, const char *name, size_t namelen, int substr)
|
||||
{
|
||||
const unsigned char *buffer;
|
||||
size_t length;
|
||||
size_t pos, off, len;
|
||||
size_t nkeys, keyinfolen;
|
||||
size_t nuids, uidinfolen;
|
||||
size_t nserial;
|
||||
int idx;
|
||||
|
||||
/* fixme: this code is common to blob_cmp_mail */
|
||||
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 (namelen < 1)
|
||||
return 0;
|
||||
|
||||
for (idx=1 ;idx < nuids; idx++)
|
||||
{
|
||||
size_t mypos = pos;
|
||||
|
||||
mypos += idx*uidinfolen;
|
||||
off = get32 (buffer+mypos);
|
||||
len = get32 (buffer+mypos+4);
|
||||
if (off+len > length)
|
||||
return 0; /* error: better stop here out of bounds */
|
||||
if (len < 2 || buffer[off] != '<')
|
||||
continue; /* empty name or trailing 0 not stored */
|
||||
len--; /* one back */
|
||||
if ( len < 3 || buffer[off+len] != '>')
|
||||
continue; /* not a proper email address */
|
||||
len--;
|
||||
if (substr)
|
||||
{
|
||||
if (ascii_memcasemem (buffer+off+1, len, name, namelen))
|
||||
return 1; /* found */
|
||||
}
|
||||
else
|
||||
{
|
||||
if (len == namelen && !ascii_memcasecmp (buffer+off+1, name, len))
|
||||
return 1; /* found */
|
||||
}
|
||||
}
|
||||
return 0; /* not found */
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
The has_foo functions are used as helpers for search
|
||||
*/
|
||||
static int
|
||||
has_short_kid (KEYBOXBLOB blob, const unsigned char *kid)
|
||||
{
|
||||
return blob_cmp_fpr_part (blob, kid+4, 16, 4);
|
||||
}
|
||||
|
||||
static int
|
||||
has_long_kid (KEYBOXBLOB blob, const unsigned char *kid)
|
||||
{
|
||||
return blob_cmp_fpr_part (blob, kid, 12, 8);
|
||||
}
|
||||
|
||||
static int
|
||||
has_fingerprint (KEYBOXBLOB blob, const unsigned char *fpr)
|
||||
{
|
||||
return blob_cmp_fpr (blob, fpr);
|
||||
}
|
||||
|
||||
|
||||
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, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
has_issuer_sn (KEYBOXBLOB blob, const char *name,
|
||||
const unsigned char *sn, int snlen)
|
||||
{
|
||||
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, snlen)
|
||||
&& blob_cmp_name (blob, 0 /* issuer */, name, namelen, 0));
|
||||
}
|
||||
|
||||
static int
|
||||
has_sn (KEYBOXBLOB blob, const unsigned char *sn, int snlen)
|
||||
{
|
||||
return_val_if_fail (sn, 0);
|
||||
|
||||
if (blob_get_type (blob) != BLOBTYPE_X509)
|
||||
return 0;
|
||||
return blob_cmp_sn (blob, sn, snlen);
|
||||
}
|
||||
|
||||
static int
|
||||
has_subject (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, 1 /* subject */, name, namelen, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
has_subject_or_alt (KEYBOXBLOB blob, const char *name, int substr)
|
||||
{
|
||||
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, -1 /* all subject names*/, name,
|
||||
namelen, substr);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
has_mail (KEYBOXBLOB blob, const char *name, int substr)
|
||||
{
|
||||
size_t namelen;
|
||||
|
||||
return_val_if_fail (name, 0);
|
||||
|
||||
if (blob_get_type (blob) != BLOBTYPE_X509)
|
||||
return 0;
|
||||
|
||||
namelen = strlen (name);
|
||||
if (namelen && name[namelen-1] == '>')
|
||||
namelen--;
|
||||
return blob_cmp_mail (blob, name, namelen, substr);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
release_sn_array (struct sn_array_s *array, size_t size)
|
||||
{
|
||||
size_t n;
|
||||
|
||||
for (n=0; n < size; n++)
|
||||
xfree (array[n].sn);
|
||||
xfree (array);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
The search API
|
||||
|
||||
*/
|
||||
|
||||
int
|
||||
keybox_search_reset (KEYBOX_HANDLE hd)
|
||||
{
|
||||
if (!hd)
|
||||
return gpg_error (GPG_ERR_INV_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;
|
||||
}
|
||||
|
||||
|
||||
/* Note: When in ephemeral mode the search function does visit all
|
||||
blobs but in standard mode, blobs flagged as ephemeral are ignored. */
|
||||
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;
|
||||
struct sn_array_s *sn_array = NULL;
|
||||
|
||||
if (!hd)
|
||||
return gpg_error (GPG_ERR_INV_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 (desc[n].snlen == -1 && !sn_array)
|
||||
{
|
||||
sn_array = xtrycalloc (ndesc, sizeof *sn_array);
|
||||
if (!sn_array)
|
||||
return (hd->error = gpg_error (gpg_err_code_from_errno (errno)));
|
||||
}
|
||||
}
|
||||
|
||||
if (!hd->fp)
|
||||
{
|
||||
hd->fp = fopen (hd->kb->fname, "rb");
|
||||
if (!hd->fp)
|
||||
{
|
||||
hd->error = gpg_error (gpg_err_code_from_errno (errno));
|
||||
xfree (sn_array);
|
||||
return hd->error;
|
||||
}
|
||||
}
|
||||
|
||||
/* kludge: we need to convert an SN given as hexstring to it's
|
||||
binary representation - in some cases we are not able to store it
|
||||
in the search descriptor, because due to its usgae it is not
|
||||
possible to free allocated memory */
|
||||
if (sn_array)
|
||||
{
|
||||
const unsigned char *s;
|
||||
int i, odd;
|
||||
size_t snlen;
|
||||
|
||||
for (n=0; n < ndesc; n++)
|
||||
{
|
||||
if (!desc[n].sn)
|
||||
;
|
||||
else if (desc[n].snlen == -1)
|
||||
{
|
||||
unsigned char *sn;
|
||||
|
||||
s = desc[n].sn;
|
||||
for (i=0; *s && *s != '/'; s++, i++)
|
||||
;
|
||||
odd = (i & 1);
|
||||
snlen = (i+1)/2;
|
||||
sn_array[n].sn = xtrymalloc (snlen);
|
||||
if (!sn_array[n].sn)
|
||||
{
|
||||
hd->error = gpg_error (gpg_err_code_from_errno (errno));
|
||||
release_sn_array (sn_array, n);
|
||||
return hd->error;
|
||||
}
|
||||
sn_array[n].snlen = snlen;
|
||||
sn = sn_array[n].sn;
|
||||
s = desc[n].sn;
|
||||
if (odd)
|
||||
{
|
||||
*sn++ = xtoi_1 (s);
|
||||
s++;
|
||||
}
|
||||
for (; *s && *s != '/'; s += 2)
|
||||
*sn++ = xtoi_2 (s);
|
||||
}
|
||||
else
|
||||
{
|
||||
const unsigned char *sn;
|
||||
|
||||
sn = desc[n].sn;
|
||||
snlen = desc[n].snlen;
|
||||
sn_array[n].sn = xtrymalloc (snlen);
|
||||
if (!sn_array[n].sn)
|
||||
{
|
||||
hd->error = gpg_error (gpg_err_code_from_errno (errno));
|
||||
release_sn_array (sn_array, n);
|
||||
return hd->error;
|
||||
}
|
||||
sn_array[n].snlen = snlen;
|
||||
memcpy (sn_array[n].sn, sn, snlen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (;;)
|
||||
{
|
||||
unsigned int blobflags;
|
||||
|
||||
_keybox_release_blob (blob); blob = NULL;
|
||||
rc = _keybox_read_blob (&blob, hd->fp);
|
||||
if (rc)
|
||||
break;
|
||||
|
||||
blobflags = blob_get_blob_flags (blob);
|
||||
if (!hd->ephemeral && (blobflags & 2))
|
||||
continue; /* not in ephemeral mode but blob is flagged ephemeral */
|
||||
|
||||
for (n=0; n < ndesc; n++)
|
||||
{
|
||||
switch (desc[n].mode)
|
||||
{
|
||||
case KEYDB_SEARCH_MODE_NONE:
|
||||
never_reached ();
|
||||
break;
|
||||
case KEYDB_SEARCH_MODE_EXACT:
|
||||
if (has_subject_or_alt (blob, desc[n].u.name, 0))
|
||||
goto found;
|
||||
break;
|
||||
case KEYDB_SEARCH_MODE_MAIL:
|
||||
if (has_mail (blob, desc[n].u.name, 0))
|
||||
goto found;
|
||||
break;
|
||||
case KEYDB_SEARCH_MODE_MAILSUB:
|
||||
if (has_mail (blob, desc[n].u.name, 1))
|
||||
goto found;
|
||||
break;
|
||||
case KEYDB_SEARCH_MODE_SUBSTR:
|
||||
if (has_subject_or_alt (blob, desc[n].u.name, 1))
|
||||
goto found;
|
||||
break;
|
||||
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,
|
||||
sn_array? sn_array[n].sn : desc[n].sn,
|
||||
sn_array? sn_array[n].snlen : desc[n].snlen))
|
||||
goto found;
|
||||
break;
|
||||
case KEYDB_SEARCH_MODE_SN:
|
||||
if (has_sn (blob, sn_array? sn_array[n].sn : desc[n].sn,
|
||||
sn_array? sn_array[n].snlen : desc[n].snlen))
|
||||
goto found;
|
||||
break;
|
||||
case KEYDB_SEARCH_MODE_SUBJECT:
|
||||
if (has_subject (blob, desc[n].u.name))
|
||||
goto found;
|
||||
break;
|
||||
case KEYDB_SEARCH_MODE_SHORT_KID:
|
||||
if (has_short_kid (blob, desc[n].u.kid))
|
||||
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:
|
||||
case KEYDB_SEARCH_MODE_FPR20:
|
||||
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 = gpg_error (GPG_ERR_INV_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;
|
||||
}
|
||||
|
||||
if (sn_array)
|
||||
release_sn_array (sn_array, ndesc);
|
||||
|
||||
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_get_cert (KEYBOX_HANDLE hd, KsbaCert *r_cert)
|
||||
{
|
||||
const unsigned char *buffer;
|
||||
size_t length;
|
||||
size_t cert_off, cert_len;
|
||||
KsbaReader reader = NULL;
|
||||
KsbaCert cert = NULL;
|
||||
int rc;
|
||||
|
||||
if (!hd)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
if (!hd->found.blob)
|
||||
return gpg_error (GPG_ERR_NOTHING_FOUND);
|
||||
|
||||
if (blob_get_type (hd->found.blob) != BLOBTYPE_X509)
|
||||
return gpg_error (GPG_ERR_WRONG_BLOB_TYPE);
|
||||
|
||||
buffer = _keybox_get_blob_image (hd->found.blob, &length);
|
||||
if (length < 40)
|
||||
return gpg_error (GPG_ERR_TOO_SHORT);
|
||||
cert_off = get32 (buffer+8);
|
||||
cert_len = get32 (buffer+12);
|
||||
if (cert_off+cert_len > length)
|
||||
return gpg_error (GPG_ERR_TOO_SHORT);
|
||||
|
||||
reader = ksba_reader_new ();
|
||||
if (!reader)
|
||||
return gpg_error (GPG_ERR_ENOMEM);
|
||||
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 gpg_error (GPG_ERR_GENERAL);
|
||||
}
|
||||
|
||||
cert = ksba_cert_new ();
|
||||
if (!cert)
|
||||
{
|
||||
ksba_reader_release (reader);
|
||||
return gpg_error (GPG_ERR_ENOMEM);
|
||||
}
|
||||
|
||||
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 gpg_error (GPG_ERR_GENERAL);
|
||||
}
|
||||
|
||||
*r_cert = cert;
|
||||
ksba_reader_release (reader);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /*KEYBOX_WITH_X509*/
|
437
kbx/keybox-update.c
Normal file
437
kbx/keybox-update.c
Normal file
|
@ -0,0 +1,437 @@
|
|||
/* keybox-update.c - keybox update operations
|
||||
* Copyright (C) 2001, 2003 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "keybox-defs.h"
|
||||
|
||||
#define EXTSEP_S "."
|
||||
|
||||
|
||||
static int
|
||||
create_tmp_file (const char *template,
|
||||
char **r_bakfname, char **r_tmpfname, FILE **r_fp)
|
||||
{
|
||||
char *bakfname, *tmpfname;
|
||||
|
||||
*r_bakfname = NULL;
|
||||
*r_tmpfname = NULL;
|
||||
|
||||
# ifdef USE_ONLY_8DOT3
|
||||
/* Here is another Windoze bug?:
|
||||
* you cant rename("pubring.kbx.tmp", "pubring.kbx");
|
||||
* but rename("pubring.kbx.tmp", "pubring.aaa");
|
||||
* works. So we replace .kbx by .bak or .tmp
|
||||
*/
|
||||
if (strlen (template) > 4
|
||||
&& !strcmp (template+strlen(template)-4, EXTSEP_S "kbx") )
|
||||
{
|
||||
bakfname = xtrymalloc (strlen (template) + 1);
|
||||
if (!bakfname)
|
||||
return gpg_error (gpg_err_code_from_errno (errno));
|
||||
strcpy (bakfname, template);
|
||||
strcpy (bakfname+strlen(template)-4, EXTSEP_S "bak");
|
||||
|
||||
tmpfname = xtrymalloc (strlen (template) + 1);
|
||||
if (!tmpfname)
|
||||
{
|
||||
gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
|
||||
xfree (bakfname);
|
||||
return tmperr;
|
||||
}
|
||||
strcpy (tmpfname,template);
|
||||
strcpy (tmpfname + strlen (template)-4, EXTSEP_S "tmp");
|
||||
}
|
||||
else
|
||||
{ /* file does not end with kbx; hmmm */
|
||||
bakfname = xtrymalloc ( strlen (template) + 5);
|
||||
if (!bakfname)
|
||||
return gpg_error (gpg_err_code_from_errno (errno));
|
||||
strcpy (stpcpy (bakfname, template), EXTSEP_S "bak");
|
||||
|
||||
tmpfname = xtrymalloc ( strlen (template) + 5);
|
||||
if (!tmpfname)
|
||||
{
|
||||
gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
|
||||
xfree (bakfname);
|
||||
return tmperr;
|
||||
}
|
||||
strcpy (stpcpy (tmpfname, template), EXTSEP_S "tmp");
|
||||
}
|
||||
# else /* Posix file names */
|
||||
bakfname = xtrymalloc (strlen (template) + 2);
|
||||
if (!bakfname)
|
||||
return gpg_error (gpg_err_code_from_errno (errno));
|
||||
strcpy (stpcpy (bakfname,template),"~");
|
||||
|
||||
tmpfname = xtrymalloc ( strlen (template) + 5);
|
||||
if (!tmpfname)
|
||||
{
|
||||
gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
|
||||
xfree (bakfname);
|
||||
return tmperr;
|
||||
}
|
||||
strcpy (stpcpy (tmpfname,template), EXTSEP_S "tmp");
|
||||
# endif /* Posix filename */
|
||||
|
||||
*r_fp = fopen (tmpfname, "wb");
|
||||
if (!*r_fp)
|
||||
{
|
||||
gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
|
||||
xfree (tmpfname);
|
||||
xfree (bakfname);
|
||||
return tmperr;
|
||||
}
|
||||
|
||||
*r_bakfname = bakfname;
|
||||
*r_tmpfname = tmpfname;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
rename_tmp_file (const char *bakfname, const char *tmpfname,
|
||||
const char *fname, int secret )
|
||||
{
|
||||
int rc=0;
|
||||
|
||||
/* restrict the permissions for secret keyboxs */
|
||||
#ifndef HAVE_DOSISH_SYSTEM
|
||||
/* if (secret && !opt.preserve_permissions) */
|
||||
/* { */
|
||||
/* if (chmod (tmpfname, S_IRUSR | S_IWUSR) ) */
|
||||
/* { */
|
||||
/* log_debug ("chmod of `%s' failed: %s\n", */
|
||||
/* tmpfname, strerror(errno) ); */
|
||||
/* return KEYBOX_Write_File; */
|
||||
/* } */
|
||||
/* } */
|
||||
#endif
|
||||
|
||||
/* fixme: invalidate close caches (not used with stdio)*/
|
||||
/* iobuf_ioctl (NULL, 2, 0, (char*)tmpfname ); */
|
||||
/* iobuf_ioctl (NULL, 2, 0, (char*)bakfname ); */
|
||||
/* iobuf_ioctl (NULL, 2, 0, (char*)fname ); */
|
||||
|
||||
/* first make a backup file except for secret keyboxs */
|
||||
if (!secret)
|
||||
{
|
||||
#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
|
||||
remove (bakfname);
|
||||
#endif
|
||||
if (rename (fname, bakfname) )
|
||||
{
|
||||
return gpg_error (gpg_err_code_from_errno (errno));
|
||||
}
|
||||
}
|
||||
|
||||
/* then rename the file */
|
||||
#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
|
||||
remove (fname);
|
||||
#endif
|
||||
if (rename (tmpfname, fname) )
|
||||
{
|
||||
rc = gpg_error (gpg_err_code_from_errno (errno));
|
||||
if (secret)
|
||||
{
|
||||
/* log_info ("WARNING: 2 files with confidential" */
|
||||
/* " information exists.\n"); */
|
||||
/* log_info ("%s is the unchanged one\n", fname ); */
|
||||
/* log_info ("%s is the new one\n", tmpfname ); */
|
||||
/* log_info ("Please fix this possible security flaw\n"); */
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Perform insert/delete/update operation.
|
||||
mode 1 = insert
|
||||
2 = delete
|
||||
3 = update
|
||||
*/
|
||||
static int
|
||||
blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
|
||||
int secret, off_t start_offset, unsigned int n_packets )
|
||||
{
|
||||
FILE *fp, *newfp;
|
||||
int rc=0;
|
||||
char *bakfname = NULL;
|
||||
char *tmpfname = NULL;
|
||||
char buffer[4096];
|
||||
int nread, nbytes;
|
||||
|
||||
/* Open the source file. Because we do a rename, we have to check the
|
||||
permissions of the file */
|
||||
if (access (fname, W_OK))
|
||||
return gpg_error (gpg_err_code_from_errno (errno));
|
||||
|
||||
fp = fopen (fname, "rb");
|
||||
if (mode == 1 && !fp && errno == ENOENT)
|
||||
{ /* insert mode but file does not exist: create a new keybox file */
|
||||
newfp = fopen (fname, "wb");
|
||||
if (!newfp )
|
||||
{
|
||||
return gpg_error (gpg_err_code_from_errno (errno));
|
||||
}
|
||||
|
||||
rc = _keybox_write_blob (blob, newfp);
|
||||
if (rc)
|
||||
{
|
||||
return rc;
|
||||
}
|
||||
if ( fclose (newfp) )
|
||||
{
|
||||
return gpg_error (gpg_err_code_from_errno (errno));
|
||||
}
|
||||
|
||||
/* if (chmod( fname, S_IRUSR | S_IWUSR )) */
|
||||
/* { */
|
||||
/* log_debug ("%s: chmod failed: %s\n", fname, strerror(errno) ); */
|
||||
/* return KEYBOX_File_Error; */
|
||||
/* } */
|
||||
return 0; /* ready */
|
||||
}
|
||||
|
||||
if (!fp)
|
||||
{
|
||||
rc = gpg_error (gpg_err_code_from_errno (errno));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* create the new file */
|
||||
rc = create_tmp_file (fname, &bakfname, &tmpfname, &newfp);
|
||||
if (rc)
|
||||
{
|
||||
fclose(fp);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* prepare for insert */
|
||||
if (mode == 1)
|
||||
{
|
||||
/* copy everything to the new file */
|
||||
while ( (nread = fread (buffer, 1, DIM(buffer), fp)) > 0 )
|
||||
{
|
||||
if (fwrite (buffer, nread, 1, newfp) != 1)
|
||||
{
|
||||
rc = gpg_error (gpg_err_code_from_errno (errno));
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
if (ferror (fp))
|
||||
{
|
||||
rc = gpg_error (gpg_err_code_from_errno (errno));
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
|
||||
/* prepare for delete or update */
|
||||
if ( mode == 2 || mode == 3 )
|
||||
{
|
||||
off_t current = 0;
|
||||
|
||||
/* copy first part to the new file */
|
||||
while ( current < start_offset )
|
||||
{
|
||||
nbytes = DIM(buffer);
|
||||
if (current + nbytes > start_offset)
|
||||
nbytes = start_offset - current;
|
||||
nread = fread (buffer, 1, nbytes, fp);
|
||||
if (!fread)
|
||||
break;
|
||||
current += nread;
|
||||
|
||||
if (fwrite (buffer, nread, 1, newfp) != 1)
|
||||
{
|
||||
rc = gpg_error (gpg_err_code_from_errno (errno));
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
if (ferror (fp))
|
||||
{
|
||||
rc = gpg_error (gpg_err_code_from_errno (errno));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* skip this blob */
|
||||
rc = _keybox_read_blob (NULL, fp);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Do an insert or update */
|
||||
if ( mode == 1 || mode == 3 )
|
||||
{
|
||||
rc = _keybox_write_blob (blob, newfp);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* copy the rest of the packet for an delete or update */
|
||||
if (mode == 2 || mode == 3)
|
||||
{
|
||||
while ( (nread = fread (buffer, 1, DIM(buffer), fp)) > 0 )
|
||||
{
|
||||
if (fwrite (buffer, nread, 1, newfp) != 1)
|
||||
{
|
||||
rc = gpg_error (gpg_err_code_from_errno (errno));
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
if (ferror (fp))
|
||||
{
|
||||
rc = gpg_error (gpg_err_code_from_errno (errno));
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
|
||||
/* close both files */
|
||||
if (fclose(fp))
|
||||
{
|
||||
rc = gpg_error (gpg_err_code_from_errno (errno));
|
||||
fclose (newfp);
|
||||
goto leave;
|
||||
}
|
||||
if (fclose(newfp))
|
||||
{
|
||||
rc = gpg_error (gpg_err_code_from_errno (errno));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
rc = rename_tmp_file (bakfname, tmpfname, fname, secret);
|
||||
|
||||
leave:
|
||||
xfree(bakfname);
|
||||
xfree(tmpfname);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef KEYBOX_WITH_X509
|
||||
int
|
||||
keybox_insert_cert (KEYBOX_HANDLE hd, KsbaCert cert,
|
||||
unsigned char *sha1_digest)
|
||||
{
|
||||
int rc;
|
||||
const char *fname;
|
||||
KEYBOXBLOB blob;
|
||||
|
||||
if (!hd)
|
||||
return gpg_error (GPG_ERR_INV_HANDLE);
|
||||
if (!hd->kb)
|
||||
return gpg_error (GPG_ERR_INV_HANDLE);
|
||||
fname = hd->kb->fname;
|
||||
if (!fname)
|
||||
return gpg_error (GPG_ERR_INV_HANDLE);
|
||||
|
||||
/* close this one otherwise we will mess up the position for a next
|
||||
search. Fixme: it would be better to adjust the position after
|
||||
the write opertions. */
|
||||
if (hd->fp)
|
||||
{
|
||||
fclose (hd->fp);
|
||||
hd->fp = NULL;
|
||||
}
|
||||
|
||||
rc = _keybox_create_x509_blob (&blob, cert, sha1_digest, hd->ephemeral);
|
||||
if (!rc)
|
||||
{
|
||||
rc = blob_filecopy (1, fname, blob, hd->secret, 0, 0 );
|
||||
_keybox_release_blob (blob);
|
||||
/* if (!rc && !hd->secret && kb_offtbl) */
|
||||
/* { */
|
||||
/* update_offset_hash_table_from_kb (kb_offtbl, kb, 0); */
|
||||
/* } */
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
keybox_update_cert (KEYBOX_HANDLE hd, KsbaCert cert,
|
||||
unsigned char *sha1_digest)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#endif /*KEYBOX_WITH_X509*/
|
||||
|
||||
|
||||
int
|
||||
keybox_delete (KEYBOX_HANDLE hd)
|
||||
{
|
||||
off_t off;
|
||||
const char *fname;
|
||||
FILE *fp;
|
||||
int rc;
|
||||
|
||||
if (!hd)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
if (!hd->found.blob)
|
||||
return gpg_error (GPG_ERR_NOTHING_FOUND);
|
||||
if (!hd->kb)
|
||||
return gpg_error (GPG_ERR_INV_HANDLE);
|
||||
fname = hd->kb->fname;
|
||||
if (!fname)
|
||||
return gpg_error (GPG_ERR_INV_HANDLE);
|
||||
|
||||
off = _keybox_get_blob_fileoffset (hd->found.blob);
|
||||
if (off == (off_t)-1)
|
||||
return gpg_error (GPG_ERR_GENERAL);
|
||||
off += 4;
|
||||
|
||||
if (hd->fp)
|
||||
{
|
||||
fclose (hd->fp);
|
||||
hd->fp = NULL;
|
||||
}
|
||||
|
||||
fp = fopen (hd->kb->fname, "r+b");
|
||||
if (!fp)
|
||||
return gpg_error (gpg_err_code_from_errno (errno));
|
||||
|
||||
if (fseeko (fp, off, SEEK_SET))
|
||||
rc = gpg_error (gpg_err_code_from_errno (errno));
|
||||
else if (putc (0, fp) == EOF)
|
||||
rc = gpg_error (gpg_err_code_from_errno (errno));
|
||||
else
|
||||
rc = 0;
|
||||
|
||||
if (fclose (fp))
|
||||
{
|
||||
if (!rc)
|
||||
rc = gpg_error (gpg_err_code_from_errno (errno));
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
101
kbx/keybox.h
Normal file
101
kbx/keybox.h
Normal file
|
@ -0,0 +1,101 @@
|
|||
/* keybox.h - Keybox operations
|
||||
* Copyright (C) 2001, 2003 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#ifndef KEYBOX_H
|
||||
#define KEYBOX_H 1
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#if 0
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "keybox-search-desc.h"
|
||||
|
||||
#define KEYBOX_WITH_OPENPGP 1
|
||||
#define KEYBOX_WITH_X509 1
|
||||
|
||||
|
||||
#ifdef KEYBOX_WITH_OPENPGP
|
||||
# undef KEYBOX_WITH_OPENPGP
|
||||
/*#include <lib-to-handle-gpg-data-structs.h>*/
|
||||
#endif
|
||||
|
||||
#ifdef KEYBOX_WITH_X509
|
||||
# include <ksba.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
typedef struct keybox_handle *KEYBOX_HANDLE;
|
||||
|
||||
|
||||
/*-- keybox-init.c --*/
|
||||
void *keybox_register_file (const char *fname, int secret);
|
||||
int keybox_is_writable (void *token);
|
||||
|
||||
KEYBOX_HANDLE keybox_new (void *token, int secret);
|
||||
void keybox_release (KEYBOX_HANDLE hd);
|
||||
const char *keybox_get_resource_name (KEYBOX_HANDLE hd);
|
||||
int keybox_set_ephemeral (KEYBOX_HANDLE hd, int yes);
|
||||
|
||||
|
||||
/*-- keybox-search.c --*/
|
||||
#ifdef KEYBOX_WITH_X509
|
||||
int keybox_get_cert (KEYBOX_HANDLE hd, KsbaCert *ret_cert);
|
||||
#endif /*KEYBOX_WITH_X509*/
|
||||
|
||||
int keybox_search_reset (KEYBOX_HANDLE hd);
|
||||
int keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc);
|
||||
|
||||
|
||||
/*-- keybox-update.c --*/
|
||||
#ifdef KEYBOX_WITH_X509
|
||||
int keybox_insert_cert (KEYBOX_HANDLE hd, KsbaCert cert,
|
||||
unsigned char *sha1_digest);
|
||||
int keybox_update_cert (KEYBOX_HANDLE hd, KsbaCert cert,
|
||||
unsigned char *sha1_digest);
|
||||
#endif /*KEYBOX_WITH_X509*/
|
||||
|
||||
int keybox_delete (KEYBOX_HANDLE hd);
|
||||
|
||||
|
||||
/*-- --*/
|
||||
|
||||
#if 0
|
||||
int keybox_lock (KEYBOX_HANDLE hd, int yes);
|
||||
int keybox_get_keyblock (KEYBOX_HANDLE hd, KBNODE *ret_kb);
|
||||
int keybox_locate_writable (KEYBOX_HANDLE hd);
|
||||
int keybox_search_reset (KEYBOX_HANDLE hd);
|
||||
int keybox_search (KEYBOX_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc);
|
||||
int keybox_rebuild_cache (void *);
|
||||
#endif
|
||||
|
||||
|
||||
/*-- keybox-util.c --*/
|
||||
void keybox_set_malloc_hooks ( void *(*new_alloc_func)(size_t n),
|
||||
void *(*new_realloc_func)(void *p, size_t n),
|
||||
void (*new_free_func)(void*) );
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /*KEYBOX_H*/
|
Loading…
Add table
Add a link
Reference in a new issue