aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS6
-rw-r--r--TODO1
-rw-r--r--doc/gpgsm.texi23
-rw-r--r--kbx/ChangeLog24
-rw-r--r--kbx/Manifest8
-rw-r--r--kbx/keybox-blob.c27
-rw-r--r--kbx/keybox-defs.h3
-rw-r--r--kbx/keybox-dump.c27
-rw-r--r--kbx/keybox-file.c50
-rw-r--r--kbx/keybox-search.c53
-rw-r--r--kbx/keybox-update.c225
-rw-r--r--kbx/keybox.h6
-rw-r--r--sm/ChangeLog2
-rw-r--r--sm/keydb.c15
14 files changed, 413 insertions, 57 deletions
diff --git a/NEWS b/NEWS
index 31f76b6c8..4e246f6d6 100644
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,12 @@ Noteworthy changes in version 1.9.8
* [scdaemon] Status files named ~/.gnupg/reader_<n>.status are now
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)
------------------------------------------------
diff --git a/TODO b/TODO
index 1d12b7446..21c44a925 100644
--- a/TODO
+++ b/TODO
@@ -41,7 +41,6 @@ might want to have an agent context for each service request
* sm/keydb.c
** Check file permissions
-** Write a keybox header and check for that magic value.
** Check that all error code mapping is done.
** Remove the inter-module dependencies between gpgsm and keybox
** Add an source_of_key field
diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi
index 977fe3c37..a0da96d56 100644
--- a/doc/gpgsm.texi
+++ b/doc/gpgsm.texi
@@ -130,17 +130,36 @@ use @samp{--help} to get a list of supported operations.
Generate a new key and a certificate request.
@item --list-keys
+@itemx -k
@opindex list-keys
List all available certificates stored in the local key database.
@item --list-secret-keys
+@itemx -K
@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}
@opindex list-keys
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}
@opindex delete-keys
diff --git a/kbx/ChangeLog b/kbx/ChangeLog
index d6c75025e..aa39df815 100644
--- a/kbx/ChangeLog
+++ b/kbx/ChangeLog
@@ -1,3 +1,27 @@
+2004-04-23 Werner Koch <[email protected]>
+
+ * 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 <[email protected]>
+
+ * 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 <[email protected]>
* keybox-defs.h: Include jnlib/types.h and remove our own
diff --git a/kbx/Manifest b/kbx/Manifest
new file mode 100644
index 000000000..95f48d73f
--- /dev/null
+++ b/kbx/Manifest
@@ -0,0 +1,8 @@
+
+keybox-update.c
+keybox-file.c
+
+
+
+
+$names$
diff --git a/kbx/keybox-blob.c b/kbx/keybox-blob.c
index 96595436c..48bce28e2 100644
--- a/kbx/keybox-blob.c
+++ b/kbx/keybox-blob.c
@@ -35,9 +35,11 @@ The first record of a plain KBX file has a special format:
byte reserved
byte reserved
u32 magic 'KBXf'
- byte pgp_marginals used for validity calculation of this file
- byte pgp_completes ditto.
- byte pgp_cert_depth ditto.
+ u32 reserved
+ u32 file_created_at
+ u32 last_maintenance_run
+ u32 reserved
+ u32 reserved
The OpenPGP and X.509 blob are very similiar, things which are
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 all_validity
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
u16 reserved
u32 recheck_after
@@ -978,6 +980,7 @@ _keybox_new_blob (KEYBOXBLOB *r_blob, char *image, size_t imagelen, off_t off)
return 0;
}
+
void
_keybox_release_blob (KEYBOXBLOB blob)
{
@@ -1010,3 +1013,19 @@ _keybox_get_blob_fileoffset (KEYBOXBLOB blob)
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 );
+ }
+}
diff --git a/kbx/keybox-defs.h b/kbx/keybox-defs.h
index d7e132d6b..705762c41 100644
--- a/kbx/keybox-defs.h
+++ b/kbx/keybox-defs.h
@@ -106,10 +106,13 @@ int _keybox_new_blob (KEYBOXBLOB *r_blob, char *image, size_t imagelen,
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);
+void _keybox_update_header_blob (KEYBOXBLOB blob);
/*-- keybox-file.c --*/
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_header_blob (FILE *fp);
/*-- keybox-search.c --*/
gpg_err_code_t _keybox_get_flag_location (const unsigned char *buffer,
diff --git a/kbx/keybox-dump.c b/kbx/keybox-dump.c
index 2177bedae..2fb0984c0 100644
--- a/kbx/keybox-dump.c
+++ b/kbx/keybox-dump.c
@@ -78,9 +78,22 @@ print_string (FILE *fp, const byte *p, size_t n, int delim)
static int
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]);
if ( memcmp (buffer+8, "KBXf", 4))
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;
}
@@ -101,7 +114,7 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
buffer = _keybox_get_blob_image (blob, &length);
- if (length < 40)
+ if (length < 32)
{
fprintf (fp, "[blob too short]\n");
return -1;
@@ -136,6 +149,12 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
return 0;
}
fprintf (fp, "Version: %d\n", buffer[5]);
+
+ if (length < 40)
+ {
+ fprintf (fp, "[blob too short]\n");
+ return -1;
+ }
n = get16 (buffer + 6);
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] );
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;
- fprintf( fp, "Latest-Timestamp: %s\n", "0"/*strtimestamp(n)*/ );
+ fprintf( fp, "Latest-Timestamp: %lu\n", n );
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;
fprintf (fp, "Reserved-Space: %lu\n", n );
diff --git a/kbx/keybox-file.c b/kbx/keybox-file.c
index fc9321478..db3164fef 100644
--- a/kbx/keybox-file.c
+++ b/kbx/keybox-file.c
@@ -23,13 +23,14 @@
#include <stdio.h>
#include <string.h>
#include <errno.h>
+#include <time.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)
+_keybox_read_blob2 (KEYBOXBLOB *r_blob, FILE *fp, int *skipped_deleted)
{
char *image;
size_t imagelen = 0;
@@ -37,6 +38,7 @@ _keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp)
int rc;
off_t off;
+ *skipped_deleted = 0;
again:
*r_blob = NULL;
off = ftello (fp);
@@ -55,7 +57,7 @@ _keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp)
}
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);
if (imagelen < 5)
@@ -63,9 +65,10 @@ _keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp)
if (!type)
{
- /* special treatment for empty blobs. */
+ /* Special treatment for empty blobs. */
if (fseek (fp, imagelen-5, SEEK_CUR))
return gpg_error (gpg_err_code_from_errno (errno));
+ *skipped_deleted = 1;
goto again;
}
@@ -87,6 +90,13 @@ _keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp)
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 */
int
@@ -100,3 +110,37 @@ _keybox_write_blob (KEYBOXBLOB blob, FILE *fp)
return gpg_error (gpg_err_code_from_errno (errno));
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;
+}
+
+
diff --git a/kbx/keybox-search.c b/kbx/keybox-search.c
index f23bfdada..2ce3c1923 100644
--- a/kbx/keybox-search.c
+++ b/kbx/keybox-search.c
@@ -42,7 +42,7 @@ struct sn_array_s {
-static ulong
+static inline ulong
get32 (const byte *buffer)
{
ulong a;
@@ -53,7 +53,7 @@ get32 (const byte *buffer)
return a;
}
-static ulong
+static inline ulong
get16 (const byte *buffer)
{
ulong a;
@@ -64,20 +64,20 @@ get16 (const byte *buffer)
-static int
+static inline int
blob_get_type (KEYBOXBLOB blob)
{
const unsigned char *buffer;
size_t length;
buffer = _keybox_get_blob_image (blob, &length);
- if (length < 40)
+ if (length < 32)
return -1; /* blob too short */
return buffer[4];
}
-static unsigned int
+static inline unsigned int
blob_get_blob_flags (KEYBOXBLOB blob)
{
const unsigned char *buffer;
@@ -113,8 +113,9 @@ _keybox_get_flag_location (const unsigned char *buffer, size_t length,
*flag_size = 2;
break;
- case KEYBOX_FLAG_VALIDITY:
case KEYBOX_FLAG_OWNERTRUST:
+ case KEYBOX_FLAG_VALIDITY:
+ case KEYBOX_FLAG_CREATED_AT:
if (length < 20)
return GPG_ERR_INV_OBJ;
/* 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. */
*flag_size = 1;
*flag_off = pos;
- if (what == KEYBOX_FLAG_VALIDITY)
- ++*flag_off;
+ switch (what)
+ {
+ 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;
default:
@@ -158,6 +169,8 @@ _keybox_get_flag_location (const unsigned char *buffer, size_t length,
return 0;
}
+
+
/* Return one of the flags WHAT in VALUE from teh blob BUFFER of
LENGTH bytes. Return 0 on success or an raw error code. */
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
*/
-static int
+static inline int
has_short_kid (KEYBOXBLOB blob, const unsigned char *kid)
{
return blob_cmp_fpr_part (blob, kid+4, 16, 4);
}
-static int
+static inline int
has_long_kid (KEYBOXBLOB blob, const unsigned char *kid)
{
return blob_cmp_fpr_part (blob, kid, 12, 8);
}
-static int
+static inline int
has_fingerprint (KEYBOXBLOB blob, const unsigned char *fpr)
{
return blob_cmp_fpr (blob, fpr);
}
-static int
+static inline int
has_issuer (KEYBOXBLOB blob, const char *name)
{
size_t namelen;
@@ -480,7 +493,7 @@ has_issuer (KEYBOXBLOB blob, const char *name)
return blob_cmp_name (blob, 0 /* issuer */, name, namelen, 0);
}
-static int
+static inline int
has_issuer_sn (KEYBOXBLOB blob, const char *name,
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));
}
-static int
+static inline int
has_sn (KEYBOXBLOB blob, const unsigned char *sn, int snlen)
{
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);
}
-static int
+static inline int
has_subject (KEYBOXBLOB blob, const char *name)
{
size_t namelen;
@@ -522,7 +535,7 @@ has_subject (KEYBOXBLOB blob, const char *name)
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)
{
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)
{
size_t namelen;
@@ -728,6 +741,10 @@ keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc)
if (rc)
break;
+ if (blob_get_type (blob) == BLOBTYPE_HEADER)
+ continue;
+
+
blobflags = blob_get_blob_flags (blob);
if (!hd->ephemeral && (blobflags & 2))
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*/
-/* 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. */
int
keybox_get_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int *value)
diff --git a/kbx/keybox-update.c b/kbx/keybox-update.c
index 47e53966a..16955502f 100644
--- a/kbx/keybox-update.c
+++ b/kbx/keybox-update.c
@@ -1,5 +1,5 @@
/* 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.
*
@@ -23,6 +23,7 @@
#include <stdio.h>
#include <string.h>
#include <errno.h>
+#include <time.h>
#include <unistd.h>
#include "keybox-defs.h"
@@ -193,29 +194,30 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
fp = fopen (fname, "rb");
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");
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);
if (rc)
- {
- return rc;
- }
+ return rc;
+
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 )) */
/* { */
/* log_debug ("%s: chmod failed: %s\n", fname, strerror(errno) ); */
/* return KEYBOX_File_Error; */
/* } */
- return 0; /* ready */
+ return 0; /* Ready. */
}
if (!fp)
@@ -224,7 +226,7 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
goto leave;
}
- /* create the new file */
+ /* Create the new file. */
rc = create_tmp_file (fname, &bakfname, &tmpfname, &newfp);
if (rc)
{
@@ -235,7 +237,7 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
/* prepare for insert */
if (mode == 1)
{
- /* copy everything to the new file */
+ /* Copy everything to the new file. */
while ( (nread = fread (buffer, 1, DIM(buffer), fp)) > 0 )
{
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 )
{
off_t current = 0;
- /* copy first part to the new file */
+ /* 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)
+ if (!nread)
break;
current += nread;
@@ -279,13 +281,13 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
goto leave;
}
- /* skip this blob */
+ /* Skip this blob. */
rc = _keybox_read_blob (NULL, fp);
if (rc)
return rc;
}
- /* Do an insert or update */
+ /* Do an insert or update. */
if ( mode == 1 || mode == 3 )
{
rc = _keybox_write_blob (blob, newfp);
@@ -293,7 +295,7 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
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)
{
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))
{
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
int
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)
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
the write opertions. */
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;
+}
+
diff --git a/kbx/keybox.h b/kbx/keybox.h
index e4dc9d642..af1fc4516 100644
--- a/kbx/keybox.h
+++ b/kbx/keybox.h
@@ -52,9 +52,10 @@ typedef enum
KEYBOX_FLAG_OWNERTRUST, /* The assigned ownertrust. */
KEYBOX_FLAG_KEY, /* The key flags; requires a key 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. */
- } keyxox_flag_t;
+ KEYBOX_FLAG_CREATED_AT /* The date the block was created. */
+ } keybox_flag_t;
/*-- 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_delete (KEYBOX_HANDLE hd);
+int keybox_compress (KEYBOX_HANDLE hd);
/*-- --*/
diff --git a/sm/ChangeLog b/sm/ChangeLog
index 28171b963..8c0297d28 100644
--- a/sm/ChangeLog
+++ b/sm/ChangeLog
@@ -1,5 +1,7 @@
2004-04-23 Werner Koch <[email protected]>
+ * keydb.c (keydb_add_resource): Try to compress the file on init.
+
* keylist.c (oidtranstbl): New. OIDs collected from several sources.
(print_name_raw, print_names_raw, list_cert_raw): New.
(gpgsm_list_keys): Check the dump mode and pass it down as
diff --git a/sm/keydb.c b/sm/keydb.c
index 858baf242..322307553 100644
--- a/sm/keydb.c
+++ b/sm/keydb.c
@@ -218,10 +218,25 @@ keydb_add_resource (const char *url, int force, int secret)
= create_dotlock (filename);
if (!all_resources[used_resources].lockhandle)
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++;
}
}
+
+
break;
default:
log_error ("resource type of `%s' not supported\n", url);