diff options
author | Werner Koch <[email protected]> | 2004-04-26 08:09:25 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2004-04-26 08:09:25 +0000 |
commit | 6aaceac7fec0b98b60ab1259bda5f97465817ce6 (patch) | |
tree | da7228afd0a40e47f7ca15ca4bacd2594979601a /kbx/keybox-update.c | |
parent | (oidtranstbl): New. OIDs collected from several sources. (diff) | |
download | gnupg-6aaceac7fec0b98b60ab1259bda5f97465817ce6.tar.gz gnupg-6aaceac7fec0b98b60ab1259bda5f97465817ce6.zip |
The keybox gets now compressed after 3 hours and ephemeral
stored certificates are deleted after about a day.
Diffstat (limited to 'kbx/keybox-update.c')
-rw-r--r-- | kbx/keybox-update.c | 225 |
1 files changed, 202 insertions, 23 deletions
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; +} + |