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_.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 + + * 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 + + * 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 * 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 #include #include +#include #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 #include #include +#include #include #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 + * 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);