1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-22 10:19:57 +01:00

The keybox gets now compressed after 3 hours and ephemeral

stored certificates are deleted after about a day.
This commit is contained in:
Werner Koch 2004-04-26 08:09:25 +00:00
parent cbc5ce3ea4
commit 6aaceac7fe
14 changed files with 413 additions and 57 deletions

6
NEWS
View File

@ -6,6 +6,12 @@ Noteworthy changes in version 1.9.8
* [scdaemon] Status files named ~/.gnupg/reader_<n>.status are now * [scdaemon] Status files named ~/.gnupg/reader_<n>.status are now
written when using the internal CCID driver. written when using the internal CCID driver.
* [gpgsm] New commands --dump-{,secret,external}-keys to show a very
detailed view of the certificates.
* The keybox gets now compressed after 3 hours and ephemeral
stored certificates are deleted after about a day.
Noteworthy changes in version 1.9.7 (2004-04-06) Noteworthy changes in version 1.9.7 (2004-04-06)
------------------------------------------------ ------------------------------------------------

1
TODO
View File

@ -41,7 +41,6 @@ might want to have an agent context for each service request
* sm/keydb.c * sm/keydb.c
** Check file permissions ** Check file permissions
** Write a keybox header and check for that magic value.
** Check that all error code mapping is done. ** Check that all error code mapping is done.
** Remove the inter-module dependencies between gpgsm and keybox ** Remove the inter-module dependencies between gpgsm and keybox
** Add an source_of_key field ** Add an source_of_key field

View File

@ -130,17 +130,36 @@ use @samp{--help} to get a list of supported operations.
Generate a new key and a certificate request. Generate a new key and a certificate request.
@item --list-keys @item --list-keys
@itemx -k
@opindex list-keys @opindex list-keys
List all available certificates stored in the local key database. List all available certificates stored in the local key database.
@item --list-secret-keys @item --list-secret-keys
@itemx -K
@opindex list-secret-keys @opindex list-secret-keys
List all available keys whenre a secret key is available. List all available certificates for which a corresponding a secret key
is available.
@item --list-external-keys @var{pattern} @item --list-external-keys @var{pattern}
@opindex list-keys @opindex list-keys
List certificates matching @var{pattern} using an external server. This List certificates matching @var{pattern} using an external server. This
utilies the @code{dirmngr} service. utilizes the @code{dirmngr} service.
@item --dump-keys
@opindex dump-keys
List all available certificates stored in the local key database using a
format useful mainly for debugging.
@item --dump-secret-keys
@opindex dump-secret-keys
List all available certificates for which a corresponding a secret key
is available using a format useful mainly for debugging.
@item --dump-external-keys @var{pattern}
@opindex dump-keys
List certificates matching @var{pattern} using an external server.
This utilizes the @code{dirmngr} service. It uses a format useful
mainly for debugging.
@item --delete-keys @var{pattern} @item --delete-keys @var{pattern}
@opindex delete-keys @opindex delete-keys

View File

@ -1,3 +1,27 @@
2004-04-23 Werner Koch <wk@gnupg.org>
* keybox-blob.c (_keybox_update_header_blob): New.
* keybox-update.c (blob_filecopy): Handle header blob.
* keybox-file.c (_keybox_read_blob2): New. Moved code from
_keybox_read_blob to there.
* keybox-dump.c (dump_header_blob): Print header info.
2004-04-21 Werner Koch <wk@gnupg.org>
* keybox-search.c (_keybox_get_flag_location): Add flag
KEYBOX_FLAG_CREATED_AT.
* keybox-update.c (keybox_compress): New.
* keybox-search.c (get32, get16, blob_get_type)
(blob_get_blob_flags, has_short_kid, has_long_kid)
(has_fingerprint, has_issuer, has_issuer_sn, has_sn, has_subject)
(has_subject_or_alt, has_mail): inline them.
* keybox-update.c (blob_filecopy): Fixed an error/eof check
(s/if(fread)/if(nread)/).
* keybox-dump.c (_keybox_dump_blob): Really print the timestamps.
2004-04-20 Werner Koch <wk@gnupg.org> 2004-04-20 Werner Koch <wk@gnupg.org>
* keybox-defs.h: Include jnlib/types.h and remove our own * keybox-defs.h: Include jnlib/types.h and remove our own

8
kbx/Manifest Normal file
View File

@ -0,0 +1,8 @@
keybox-update.c
keybox-file.c
$names$

View File

@ -35,9 +35,11 @@ The first record of a plain KBX file has a special format:
byte reserved byte reserved
byte reserved byte reserved
u32 magic 'KBXf' u32 magic 'KBXf'
byte pgp_marginals used for validity calculation of this file u32 reserved
byte pgp_completes ditto. u32 file_created_at
byte pgp_cert_depth ditto. u32 last_maintenance_run
u32 reserved
u32 reserved
The OpenPGP and X.509 blob are very similiar, things which are The OpenPGP and X.509 blob are very similiar, things which are
X.509 specific are noted like [X.509: xxx] X.509 specific are noted like [X.509: xxx]
@ -85,7 +87,7 @@ X.509 specific are noted like [X.509: xxx]
u8 assigned ownertrust [X509: not used] u8 assigned ownertrust [X509: not used]
u8 all_validity u8 all_validity
OpenPGP: see ../g10/trustdb/TRUST_* [not yet used] OpenPGP: see ../g10/trustdb/TRUST_* [not yet used]
X509: Bit 4 set := key has been revoked. nOte that this value X509: Bit 4 set := key has been revoked. Note that this value
matches TRUST_FLAG_REVOKED matches TRUST_FLAG_REVOKED
u16 reserved u16 reserved
u32 recheck_after u32 recheck_after
@ -978,6 +980,7 @@ _keybox_new_blob (KEYBOXBLOB *r_blob, char *image, size_t imagelen, off_t off)
return 0; return 0;
} }
void void
_keybox_release_blob (KEYBOXBLOB blob) _keybox_release_blob (KEYBOXBLOB blob)
{ {
@ -1010,3 +1013,19 @@ _keybox_get_blob_fileoffset (KEYBOXBLOB blob)
return blob->fileoffset; return blob->fileoffset;
} }
void
_keybox_update_header_blob (KEYBOXBLOB blob)
{
if (blob->bloblen >= 32 && blob->blob[4] == BLOBTYPE_HEADER)
{
u32 val = make_timestamp ();
/* Update the last maintenance run times tamp. */
blob->blob[20] = (val >> 24);
blob->blob[20+1] = (val >> 16);
blob->blob[20+2] = (val >> 8);
blob->blob[20+3] = (val );
}
}

View File

@ -106,10 +106,13 @@ int _keybox_new_blob (KEYBOXBLOB *r_blob, char *image, size_t imagelen,
void _keybox_release_blob (KEYBOXBLOB blob); void _keybox_release_blob (KEYBOXBLOB blob);
const char *_keybox_get_blob_image (KEYBOXBLOB blob, size_t *n); const char *_keybox_get_blob_image (KEYBOXBLOB blob, size_t *n);
off_t _keybox_get_blob_fileoffset (KEYBOXBLOB blob); off_t _keybox_get_blob_fileoffset (KEYBOXBLOB blob);
void _keybox_update_header_blob (KEYBOXBLOB blob);
/*-- keybox-file.c --*/ /*-- keybox-file.c --*/
int _keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp); int _keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp);
int _keybox_read_blob2 (KEYBOXBLOB *r_blob, FILE *fp, int *skipped_deleted);
int _keybox_write_blob (KEYBOXBLOB blob, FILE *fp); int _keybox_write_blob (KEYBOXBLOB blob, FILE *fp);
int _keybox_write_header_blob (FILE *fp);
/*-- keybox-search.c --*/ /*-- keybox-search.c --*/
gpg_err_code_t _keybox_get_flag_location (const unsigned char *buffer, gpg_err_code_t _keybox_get_flag_location (const unsigned char *buffer,

View File

@ -78,9 +78,22 @@ print_string (FILE *fp, const byte *p, size_t n, int delim)
static int static int
dump_header_blob (const byte *buffer, size_t length, FILE *fp) dump_header_blob (const byte *buffer, size_t length, FILE *fp)
{ {
unsigned long n;
if (length < 32)
{
fprintf (fp, "[blob too short]\n");
return -1;
}
fprintf (fp, "Version: %d\n", buffer[5]); fprintf (fp, "Version: %d\n", buffer[5]);
if ( memcmp (buffer+8, "KBXf", 4)) if ( memcmp (buffer+8, "KBXf", 4))
fprintf (fp, "[Error: invalid magic number]\n"); fprintf (fp, "[Error: invalid magic number]\n");
n = get32 (buffer+16);
fprintf( fp, "created-at: %lu\n", n );
n = get32 (buffer+20);
fprintf( fp, "last-maint: %lu\n", n );
return 0; return 0;
} }
@ -101,7 +114,7 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
buffer = _keybox_get_blob_image (blob, &length); buffer = _keybox_get_blob_image (blob, &length);
if (length < 40) if (length < 32)
{ {
fprintf (fp, "[blob too short]\n"); fprintf (fp, "[blob too short]\n");
return -1; return -1;
@ -136,6 +149,12 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
return 0; return 0;
} }
fprintf (fp, "Version: %d\n", buffer[5]); fprintf (fp, "Version: %d\n", buffer[5]);
if (length < 40)
{
fprintf (fp, "[blob too short]\n");
return -1;
}
n = get16 (buffer + 6); n = get16 (buffer + 6);
fprintf( fp, "Blob-Flags: %04lX", n); fprintf( fp, "Blob-Flags: %04lX", n);
@ -290,11 +309,11 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
fprintf (fp, "All-Validity: %d\n", p[1] ); fprintf (fp, "All-Validity: %d\n", p[1] );
p += 4; p += 4;
n = get32 (p); p += 4; n = get32 (p); p += 4;
fprintf (fp, "Recheck-After: %s\n", /*n? strtimestamp(n) :*/ "0" ); fprintf (fp, "Recheck-After: %lu\n", n );
n = get32 (p ); p += 4; n = get32 (p ); p += 4;
fprintf( fp, "Latest-Timestamp: %s\n", "0"/*strtimestamp(n)*/ ); fprintf( fp, "Latest-Timestamp: %lu\n", n );
n = get32 (p ); p += 4; n = get32 (p ); p += 4;
fprintf (fp, "Created-At: %s\n", "0"/*strtimestamp(n)*/ ); fprintf (fp, "Created-At: %lu\n", n );
n = get32 (p ); p += 4; n = get32 (p ); p += 4;
fprintf (fp, "Reserved-Space: %lu\n", n ); fprintf (fp, "Reserved-Space: %lu\n", n );

View File

@ -23,13 +23,14 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <time.h>
#include "keybox-defs.h" #include "keybox-defs.h"
/* Read a block at the current postion and return it in r_blob. /* Read a block at the current postion and return it in r_blob.
r_blob may be NULL to simply skip the current block */ r_blob may be NULL to simply skip the current block */
int int
_keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp) _keybox_read_blob2 (KEYBOXBLOB *r_blob, FILE *fp, int *skipped_deleted)
{ {
char *image; char *image;
size_t imagelen = 0; size_t imagelen = 0;
@ -37,6 +38,7 @@ _keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp)
int rc; int rc;
off_t off; off_t off;
*skipped_deleted = 0;
again: again:
*r_blob = NULL; *r_blob = NULL;
off = ftello (fp); off = ftello (fp);
@ -55,7 +57,7 @@ _keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp)
} }
imagelen = (c1 << 24) | (c2 << 16) | (c3 << 8 ) | c4; imagelen = (c1 << 24) | (c2 << 16) | (c3 << 8 ) | c4;
if (imagelen > 500000) /* sanity check */ if (imagelen > 500000) /* Sanity check. */
return gpg_error (GPG_ERR_TOO_LARGE); return gpg_error (GPG_ERR_TOO_LARGE);
if (imagelen < 5) if (imagelen < 5)
@ -63,9 +65,10 @@ _keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp)
if (!type) if (!type)
{ {
/* special treatment for empty blobs. */ /* Special treatment for empty blobs. */
if (fseek (fp, imagelen-5, SEEK_CUR)) if (fseek (fp, imagelen-5, SEEK_CUR))
return gpg_error (gpg_err_code_from_errno (errno)); return gpg_error (gpg_err_code_from_errno (errno));
*skipped_deleted = 1;
goto again; goto again;
} }
@ -87,6 +90,13 @@ _keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp)
return rc; return rc;
} }
int
_keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp)
{
int dummy;
return _keybox_read_blob2 (r_blob, fp, &dummy);
}
/* Write the block to the current file position */ /* Write the block to the current file position */
int int
@ -100,3 +110,37 @@ _keybox_write_blob (KEYBOXBLOB blob, FILE *fp)
return gpg_error (gpg_err_code_from_errno (errno)); return gpg_error (gpg_err_code_from_errno (errno));
return 0; return 0;
} }
/* Write a fresh header type blob. */
int
_keybox_write_header_blob (FILE *fp)
{
unsigned char image[32];
u32 val;
memset (image, 0, sizeof image);
/* Length of this blob. */
image[3] = 32;
image[4] = BLOBTYPE_HEADER;
image[5] = 1; /* Version */
memcpy (image+8, "KBXf", 4);
val = time (NULL);
/* created_at and last maintenance run. */
image[16] = (val >> 24);
image[16+1] = (val >> 16);
image[16+2] = (val >> 8);
image[16+3] = (val );
image[20] = (val >> 24);
image[20+1] = (val >> 16);
image[20+2] = (val >> 8);
image[20+3] = (val );
if (fwrite (image, 32, 1, fp) != 1)
return gpg_error (gpg_err_code_from_errno (errno));
return 0;
}

View File

@ -42,7 +42,7 @@ struct sn_array_s {
static ulong static inline ulong
get32 (const byte *buffer) get32 (const byte *buffer)
{ {
ulong a; ulong a;
@ -53,7 +53,7 @@ get32 (const byte *buffer)
return a; return a;
} }
static ulong static inline ulong
get16 (const byte *buffer) get16 (const byte *buffer)
{ {
ulong a; ulong a;
@ -64,20 +64,20 @@ get16 (const byte *buffer)
static int static inline int
blob_get_type (KEYBOXBLOB blob) blob_get_type (KEYBOXBLOB blob)
{ {
const unsigned char *buffer; const unsigned char *buffer;
size_t length; size_t length;
buffer = _keybox_get_blob_image (blob, &length); buffer = _keybox_get_blob_image (blob, &length);
if (length < 40) if (length < 32)
return -1; /* blob too short */ return -1; /* blob too short */
return buffer[4]; return buffer[4];
} }
static unsigned int static inline unsigned int
blob_get_blob_flags (KEYBOXBLOB blob) blob_get_blob_flags (KEYBOXBLOB blob)
{ {
const unsigned char *buffer; const unsigned char *buffer;
@ -113,8 +113,9 @@ _keybox_get_flag_location (const unsigned char *buffer, size_t length,
*flag_size = 2; *flag_size = 2;
break; break;
case KEYBOX_FLAG_VALIDITY:
case KEYBOX_FLAG_OWNERTRUST: case KEYBOX_FLAG_OWNERTRUST:
case KEYBOX_FLAG_VALIDITY:
case KEYBOX_FLAG_CREATED_AT:
if (length < 20) if (length < 20)
return GPG_ERR_INV_OBJ; return GPG_ERR_INV_OBJ;
/* Key info. */ /* Key info. */
@ -148,8 +149,18 @@ _keybox_get_flag_location (const unsigned char *buffer, size_t length,
return GPG_ERR_INV_OBJ ; /* Out of bounds. */ return GPG_ERR_INV_OBJ ; /* Out of bounds. */
*flag_size = 1; *flag_size = 1;
*flag_off = pos; *flag_off = pos;
if (what == KEYBOX_FLAG_VALIDITY) switch (what)
++*flag_off; {
case KEYBOX_FLAG_VALIDITY:
*flag_off += 1;
break;
case KEYBOX_FLAG_CREATED_AT:
*flag_size = 4;
*flag_off += 1+2+4+4+4;
break;
default:
break;
}
break; break;
default: default:
@ -158,6 +169,8 @@ _keybox_get_flag_location (const unsigned char *buffer, size_t length,
return 0; return 0;
} }
/* Return one of the flags WHAT in VALUE from teh blob BUFFER of /* Return one of the flags WHAT in VALUE from teh blob BUFFER of
LENGTH bytes. Return 0 on success or an raw error code. */ LENGTH bytes. Return 0 on success or an raw error code. */
static gpg_err_code_t static gpg_err_code_t
@ -447,26 +460,26 @@ blob_cmp_mail (KEYBOXBLOB blob, const char *name, size_t namelen, int substr)
/* /*
The has_foo functions are used as helpers for search The has_foo functions are used as helpers for search
*/ */
static int static inline int
has_short_kid (KEYBOXBLOB blob, const unsigned char *kid) has_short_kid (KEYBOXBLOB blob, const unsigned char *kid)
{ {
return blob_cmp_fpr_part (blob, kid+4, 16, 4); return blob_cmp_fpr_part (blob, kid+4, 16, 4);
} }
static int static inline int
has_long_kid (KEYBOXBLOB blob, const unsigned char *kid) has_long_kid (KEYBOXBLOB blob, const unsigned char *kid)
{ {
return blob_cmp_fpr_part (blob, kid, 12, 8); return blob_cmp_fpr_part (blob, kid, 12, 8);
} }
static int static inline int
has_fingerprint (KEYBOXBLOB blob, const unsigned char *fpr) has_fingerprint (KEYBOXBLOB blob, const unsigned char *fpr)
{ {
return blob_cmp_fpr (blob, fpr); return blob_cmp_fpr (blob, fpr);
} }
static int static inline int
has_issuer (KEYBOXBLOB blob, const char *name) has_issuer (KEYBOXBLOB blob, const char *name)
{ {
size_t namelen; size_t namelen;
@ -480,7 +493,7 @@ has_issuer (KEYBOXBLOB blob, const char *name)
return blob_cmp_name (blob, 0 /* issuer */, name, namelen, 0); return blob_cmp_name (blob, 0 /* issuer */, name, namelen, 0);
} }
static int static inline int
has_issuer_sn (KEYBOXBLOB blob, const char *name, has_issuer_sn (KEYBOXBLOB blob, const char *name,
const unsigned char *sn, int snlen) const unsigned char *sn, int snlen)
{ {
@ -498,7 +511,7 @@ has_issuer_sn (KEYBOXBLOB blob, const char *name,
&& blob_cmp_name (blob, 0 /* issuer */, name, namelen, 0)); && blob_cmp_name (blob, 0 /* issuer */, name, namelen, 0));
} }
static int static inline int
has_sn (KEYBOXBLOB blob, const unsigned char *sn, int snlen) has_sn (KEYBOXBLOB blob, const unsigned char *sn, int snlen)
{ {
return_val_if_fail (sn, 0); return_val_if_fail (sn, 0);
@ -508,7 +521,7 @@ has_sn (KEYBOXBLOB blob, const unsigned char *sn, int snlen)
return blob_cmp_sn (blob, sn, snlen); return blob_cmp_sn (blob, sn, snlen);
} }
static int static inline int
has_subject (KEYBOXBLOB blob, const char *name) has_subject (KEYBOXBLOB blob, const char *name)
{ {
size_t namelen; size_t namelen;
@ -522,7 +535,7 @@ has_subject (KEYBOXBLOB blob, const char *name)
return blob_cmp_name (blob, 1 /* subject */, name, namelen, 0); return blob_cmp_name (blob, 1 /* subject */, name, namelen, 0);
} }
static int static inline int
has_subject_or_alt (KEYBOXBLOB blob, const char *name, int substr) has_subject_or_alt (KEYBOXBLOB blob, const char *name, int substr)
{ {
size_t namelen; size_t namelen;
@ -538,7 +551,7 @@ has_subject_or_alt (KEYBOXBLOB blob, const char *name, int substr)
} }
static int static inline int
has_mail (KEYBOXBLOB blob, const char *name, int substr) has_mail (KEYBOXBLOB blob, const char *name, int substr)
{ {
size_t namelen; size_t namelen;
@ -728,6 +741,10 @@ keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc)
if (rc) if (rc)
break; break;
if (blob_get_type (blob) == BLOBTYPE_HEADER)
continue;
blobflags = blob_get_blob_flags (blob); blobflags = blob_get_blob_flags (blob);
if (!hd->ephemeral && (blobflags & 2)) if (!hd->ephemeral && (blobflags & 2))
continue; /* not in ephemeral mode but blob is flagged ephemeral */ continue; /* not in ephemeral mode but blob is flagged ephemeral */
@ -906,7 +923,7 @@ keybox_get_cert (KEYBOX_HANDLE hd, ksba_cert_t *r_cert)
#endif /*KEYBOX_WITH_X509*/ #endif /*KEYBOX_WITH_X509*/
/* Return the flags named WHAT iat the address of VALUE. IDX is used /* Return the flags named WHAT at the address of VALUE. IDX is used
only for certain flags and should be 0 if not required. */ only for certain flags and should be 0 if not required. */
int int
keybox_get_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int *value) keybox_get_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int *value)

View File

@ -1,5 +1,5 @@
/* keybox-update.c - keybox update operations /* keybox-update.c - keybox update operations
* Copyright (C) 2001, 2003 Free Software Foundation, Inc. * Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -23,6 +23,7 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <time.h>
#include <unistd.h> #include <unistd.h>
#include "keybox-defs.h" #include "keybox-defs.h"
@ -193,29 +194,30 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
fp = fopen (fname, "rb"); fp = fopen (fname, "rb");
if (mode == 1 && !fp && errno == ENOENT) if (mode == 1 && !fp && errno == ENOENT)
{ /* insert mode but file does not exist: create a new keybox file */ {
/* Insert mode but file does not exist:
Create a new keybox file. */
newfp = fopen (fname, "wb"); newfp = fopen (fname, "wb");
if (!newfp ) if (!newfp )
{ return gpg_error (gpg_err_code_from_errno (errno));
return gpg_error (gpg_err_code_from_errno (errno));
} rc = _keybox_write_header_blob (newfp);
if (rc)
return rc;
rc = _keybox_write_blob (blob, newfp); rc = _keybox_write_blob (blob, newfp);
if (rc) if (rc)
{ return rc;
return rc;
}
if ( fclose (newfp) ) if ( fclose (newfp) )
{ return gpg_error (gpg_err_code_from_errno (errno));
return gpg_error (gpg_err_code_from_errno (errno));
}
/* if (chmod( fname, S_IRUSR | S_IWUSR )) */ /* if (chmod( fname, S_IRUSR | S_IWUSR )) */
/* { */ /* { */
/* log_debug ("%s: chmod failed: %s\n", fname, strerror(errno) ); */ /* log_debug ("%s: chmod failed: %s\n", fname, strerror(errno) ); */
/* return KEYBOX_File_Error; */ /* return KEYBOX_File_Error; */
/* } */ /* } */
return 0; /* ready */ return 0; /* Ready. */
} }
if (!fp) if (!fp)
@ -224,7 +226,7 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
goto leave; goto leave;
} }
/* create the new file */ /* Create the new file. */
rc = create_tmp_file (fname, &bakfname, &tmpfname, &newfp); rc = create_tmp_file (fname, &bakfname, &tmpfname, &newfp);
if (rc) if (rc)
{ {
@ -235,7 +237,7 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
/* prepare for insert */ /* prepare for insert */
if (mode == 1) if (mode == 1)
{ {
/* copy everything to the new file */ /* Copy everything to the new file. */
while ( (nread = fread (buffer, 1, DIM(buffer), fp)) > 0 ) while ( (nread = fread (buffer, 1, DIM(buffer), fp)) > 0 )
{ {
if (fwrite (buffer, nread, 1, newfp) != 1) if (fwrite (buffer, nread, 1, newfp) != 1)
@ -251,19 +253,19 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
} }
} }
/* prepare for delete or update */ /* Prepare for delete or update. */
if ( mode == 2 || mode == 3 ) if ( mode == 2 || mode == 3 )
{ {
off_t current = 0; off_t current = 0;
/* copy first part to the new file */ /* Copy first part to the new file. */
while ( current < start_offset ) while ( current < start_offset )
{ {
nbytes = DIM(buffer); nbytes = DIM(buffer);
if (current + nbytes > start_offset) if (current + nbytes > start_offset)
nbytes = start_offset - current; nbytes = start_offset - current;
nread = fread (buffer, 1, nbytes, fp); nread = fread (buffer, 1, nbytes, fp);
if (!fread) if (!nread)
break; break;
current += nread; current += nread;
@ -279,13 +281,13 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
goto leave; goto leave;
} }
/* skip this blob */ /* Skip this blob. */
rc = _keybox_read_blob (NULL, fp); rc = _keybox_read_blob (NULL, fp);
if (rc) if (rc)
return rc; return rc;
} }
/* Do an insert or update */ /* Do an insert or update. */
if ( mode == 1 || mode == 3 ) if ( mode == 1 || mode == 3 )
{ {
rc = _keybox_write_blob (blob, newfp); rc = _keybox_write_blob (blob, newfp);
@ -293,7 +295,7 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
return rc; return rc;
} }
/* copy the rest of the packet for an delete or update */ /* Copy the rest of the packet for an delete or update. */
if (mode == 2 || mode == 3) if (mode == 2 || mode == 3)
{ {
while ( (nread = fread (buffer, 1, DIM(buffer), fp)) > 0 ) while ( (nread = fread (buffer, 1, DIM(buffer), fp)) > 0 )
@ -311,7 +313,7 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
} }
} }
/* close both files */ /* Close both files. */
if (fclose(fp)) if (fclose(fp))
{ {
rc = gpg_error (gpg_err_code_from_errno (errno)); rc = gpg_error (gpg_err_code_from_errno (errno));
@ -334,7 +336,6 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
#ifdef KEYBOX_WITH_X509 #ifdef KEYBOX_WITH_X509
int int
keybox_insert_cert (KEYBOX_HANDLE hd, ksba_cert_t cert, keybox_insert_cert (KEYBOX_HANDLE hd, ksba_cert_t cert,
@ -352,7 +353,7 @@ keybox_insert_cert (KEYBOX_HANDLE hd, ksba_cert_t cert,
if (!fname) if (!fname)
return gpg_error (GPG_ERR_INV_HANDLE); return gpg_error (GPG_ERR_INV_HANDLE);
/* close this one otherwise we will mess up the position for a next /* Close this one otherwise we will mess up the position for a next
search. Fixme: it would be better to adjust the position after search. Fixme: it would be better to adjust the position after
the write opertions. */ the write opertions. */
if (hd->fp) if (hd->fp)
@ -517,3 +518,181 @@ keybox_delete (KEYBOX_HANDLE hd)
} }
/* Compress the keybox file. This should be run with the file
locked. */
int
keybox_compress (KEYBOX_HANDLE hd)
{
int read_rc, rc;
const char *fname;
FILE *fp, *newfp;
char *bakfname = NULL;
char *tmpfname = NULL;
int first_blob;
KEYBOXBLOB blob = NULL;
u32 cut_time;
int any_changes = 0;
int skipped_deleted;
if (!hd)
return gpg_error (GPG_ERR_INV_HANDLE);
if (!hd->kb)
return gpg_error (GPG_ERR_INV_HANDLE);
if (hd->secret)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
fname = hd->kb->fname;
if (!fname)
return gpg_error (GPG_ERR_INV_HANDLE);
if (hd->fp)
{
fclose (hd->fp);
hd->fp = NULL;
}
/* 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 (!fp && errno == ENOENT)
return 0; /* Ready. File has been deleted right after the access above. */
if (!fp)
{
rc = gpg_error (gpg_err_code_from_errno (errno));
return rc;
}
/* A quick test to see if we need to compress the file at all. We
schedule a compress run after 3 hours. */
if ( !_keybox_read_blob (&blob, fp) )
{
const unsigned char *buffer;
size_t length;
buffer = _keybox_get_blob_image (blob, &length);
if (length > 4 && buffer[4] == BLOBTYPE_HEADER)
{
u32 last_maint = ((buffer[20] << 24) | (buffer[20+1] << 16)
| (buffer[20+2] << 8) | (buffer[20+3]));
if ( (last_maint + 3*3600) > time (NULL) )
{
fclose (fp);
_keybox_release_blob (blob);
return 0; /* Compress run not yet needed. */
}
}
_keybox_release_blob (blob);
rewind (fp);
}
/* Create the new file. */
rc = create_tmp_file (fname, &bakfname, &tmpfname, &newfp);
if (rc)
{
fclose(fp);
return rc;;
}
/* Processing loop. By reading using _keybox_read_blob we
automagically skip and blobs flagged as deleted. Thus what we
only have to do is to check all ephemeral flagged blocks whether
their time has come and write out all other blobs. */
cut_time = time(NULL) - 86400;
first_blob = 1;
skipped_deleted = 0;
for (rc=0; !(read_rc = _keybox_read_blob2 (&blob, fp, &skipped_deleted));
_keybox_release_blob (blob), blob = NULL )
{
unsigned int blobflags;
const unsigned char *buffer;
size_t length, pos, size;
u32 created_at;
if (skipped_deleted)
any_changes = 1;
buffer = _keybox_get_blob_image (blob, &length);
if (first_blob)
{
first_blob = 0;
if (length > 4 && buffer[4] == BLOBTYPE_HEADER)
{
/* Write out the blob with an updated maintenance time stamp. */
_keybox_update_header_blob (blob);
rc = _keybox_write_blob (blob, newfp);
if (rc)
break;
continue;
}
/* The header blob is missing. Insert it. */
rc = _keybox_write_header_blob (newfp);
if (rc)
break;
any_changes = 1;
}
else if (length > 4 && buffer[4] == BLOBTYPE_HEADER)
{
/* Oops: There is another header record - remove it. */
any_changes = 1;
continue;
}
if (_keybox_get_flag_location (buffer, length,
KEYBOX_FLAG_BLOB, &pos, &size)
|| size != 2)
{
rc = gpg_error (GPG_ERR_BUG);
break;
}
blobflags = ((buffer[pos] << 8) | (buffer[pos+1]));
if ((blobflags & 2))
{
/* This is an ephemeral blob. */
if (_keybox_get_flag_location (buffer, length,
KEYBOX_FLAG_CREATED_AT, &pos, &size)
|| size != 4)
created_at = 0; /* oops. */
else
created_at = ((buffer[pos] << 24) | (buffer[pos+1] << 16)
| (buffer[pos+2] << 8) | (buffer[pos+3]));
if (created_at && created_at < cut_time)
{
any_changes = 1;
continue; /* Skip this blob. */
}
}
rc = _keybox_write_blob (blob, newfp);
if (rc)
break;
}
if (skipped_deleted)
any_changes = 1;
_keybox_release_blob (blob); blob = NULL;
if (!rc && read_rc == -1)
rc = 0;
else if (!rc)
rc = read_rc;
/* Close both files. */
if (fclose(fp) && !rc)
rc = gpg_error (gpg_err_code_from_errno (errno));
if (fclose(newfp) && !rc)
rc = gpg_error (gpg_err_code_from_errno (errno));
/* Rename or remove the temporary file. */
if (rc || !any_changes)
remove (tmpfname);
else
rc = rename_tmp_file (bakfname, tmpfname, fname, hd->secret);
xfree(bakfname);
xfree(tmpfname);
return rc;
}

View File

@ -52,9 +52,10 @@ typedef enum
KEYBOX_FLAG_OWNERTRUST, /* The assigned ownertrust. */ KEYBOX_FLAG_OWNERTRUST, /* The assigned ownertrust. */
KEYBOX_FLAG_KEY, /* The key flags; requires a key index. */ KEYBOX_FLAG_KEY, /* The key flags; requires a key index. */
KEYBOX_FLAG_UID, /* The user ID flags; requires an uid index. */ KEYBOX_FLAG_UID, /* The user ID flags; requires an uid index. */
KEYBOX_FLAG_UID_VALIDITY/* The validity of a specific uid, requires KEYBOX_FLAG_UID_VALIDITY,/* The validity of a specific uid, requires
an uid index. */ an uid index. */
} keyxox_flag_t; KEYBOX_FLAG_CREATED_AT /* The date the block was created. */
} keybox_flag_t;
/*-- keybox-init.c --*/ /*-- keybox-init.c --*/
@ -87,6 +88,7 @@ int keybox_update_cert (KEYBOX_HANDLE hd, ksba_cert_t cert,
int keybox_set_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int value); int keybox_set_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int value);
int keybox_delete (KEYBOX_HANDLE hd); int keybox_delete (KEYBOX_HANDLE hd);
int keybox_compress (KEYBOX_HANDLE hd);
/*-- --*/ /*-- --*/

View File

@ -1,5 +1,7 @@
2004-04-23 Werner Koch <wk@gnupg.org> 2004-04-23 Werner Koch <wk@gnupg.org>
* keydb.c (keydb_add_resource): Try to compress the file on init.
* keylist.c (oidtranstbl): New. OIDs collected from several sources. * keylist.c (oidtranstbl): New. OIDs collected from several sources.
(print_name_raw, print_names_raw, list_cert_raw): New. (print_name_raw, print_names_raw, list_cert_raw): New.
(gpgsm_list_keys): Check the dump mode and pass it down as (gpgsm_list_keys): Check the dump mode and pass it down as

View File

@ -218,10 +218,25 @@ keydb_add_resource (const char *url, int force, int secret)
= create_dotlock (filename); = create_dotlock (filename);
if (!all_resources[used_resources].lockhandle) if (!all_resources[used_resources].lockhandle)
log_fatal ( _("can't create lock for `%s'\n"), filename); log_fatal ( _("can't create lock for `%s'\n"), filename);
/* Do a compress run if needed and the file is not locked. */
if (!make_dotlock (all_resources[used_resources].lockhandle, 0))
{
KEYBOX_HANDLE kbxhd = keybox_new (token, secret);
if (kbxhd)
{
keybox_compress (kbxhd);
keybox_release (kbxhd);
}
release_dotlock (all_resources[used_resources].lockhandle);
}
used_resources++; used_resources++;
} }
} }
break; break;
default: default:
log_error ("resource type of `%s' not supported\n", url); log_error ("resource type of `%s' not supported\n", url);