diff options
Diffstat (limited to 'kbx/keybox-update.c')
-rw-r--r-- | kbx/keybox-update.c | 698 |
1 files changed, 0 insertions, 698 deletions
diff --git a/kbx/keybox-update.c b/kbx/keybox-update.c deleted file mode 100644 index 16955502f..000000000 --- a/kbx/keybox-update.c +++ /dev/null @@ -1,698 +0,0 @@ -/* keybox-update.c - keybox update operations - * Copyright (C) 2001, 2003, 2004 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 <time.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_header_blob (newfp); - if (rc) - return rc; - - 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 (!nread) - 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, ksba_cert_t 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, ksba_cert_t cert, - unsigned char *sha1_digest) -{ - return -1; -} - - -#endif /*KEYBOX_WITH_X509*/ - -/* Note: We assume that the keybox has been locked before the current - search was executed. This is needed so that we can depend on the - offset information of the flags. */ -int -keybox_set_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int value) -{ - off_t off; - const char *fname; - FILE *fp; - gpg_err_code_t ec; - size_t flag_pos, flag_size; - const unsigned char *buffer; - size_t length; - - 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); - if (!hd->found.blob) - return gpg_error (GPG_ERR_NOTHING_FOUND); - 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); - - buffer = _keybox_get_blob_image (hd->found.blob, &length); - ec = _keybox_get_flag_location (buffer, length, what, &flag_pos, &flag_size); - if (ec) - return gpg_error (ec); - - off += flag_pos; - - 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)); - - ec = 0; - if (fseeko (fp, off, SEEK_SET)) - ec = gpg_error (gpg_err_code_from_errno (errno)); - else - { - unsigned char tmp[4]; - - tmp[0] = value >> 24; - tmp[1] = value >> 16; - tmp[2] = value >> 8; - tmp[3] = value; - - switch (flag_size) - { - case 1: - case 2: - case 4: - if (fwrite (tmp+4-flag_size, flag_size, 1, fp) != 1) - ec = gpg_err_code_from_errno (errno); - break; - default: - ec = GPG_ERR_BUG; - break; - } - } - - if (fclose (fp)) - { - if (!ec) - ec = gpg_err_code_from_errno (errno); - } - - return gpg_error (ec); -} - - - -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; -} - - -/* 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; -} - |