1 /* keybox-update.c - keybox update operations
2 * Copyright (C) 2001, 2003, 2004, 2012 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
29 #include "keybox-defs.h"
30 #include "../common/sysutils.h"
31 #include "../common/host2net.h"
35 #define FILECOPY_INSERT 1
36 #define FILECOPY_DELETE 2
37 #define FILECOPY_UPDATE 3
40 #if !defined(HAVE_FSEEKO) && !defined(fseeko)
46 # define LONG_MAX ((long) ((unsigned long) -1 >> 1))
49 # define LONG_MIN (-1 - LONG_MAX)
53 * A substitute for fseeko, for hosts that don't have it.
56 fseeko (FILE * stream, off_t newpos, int whence)
58 while (newpos != (long) newpos)
60 long pos = newpos < 0 ? LONG_MIN : LONG_MAX;
61 if (fseek (stream, pos, whence) != 0)
66 return fseek (stream, (long) newpos, whence);
68 #endif /* !defined(HAVE_FSEEKO) && !defined(fseeko) */
73 create_tmp_file (const char *template,
74 char **r_bakfname, char **r_tmpfname, FILE **r_fp)
76 char *bakfname, *tmpfname;
81 # ifdef USE_ONLY_8DOT3
82 /* Here is another Windoze bug?:
83 * you cant rename("pubring.kbx.tmp", "pubring.kbx");
84 * but rename("pubring.kbx.tmp", "pubring.aaa");
85 * works. So we replace ".kbx" by ".kb_" or ".k__". Note that we
86 * can't use ".bak" and ".tmp", because these suffixes are used by
87 * gpg and would lead to a sharing violation or data corruption.
89 if (strlen (template) > 4
90 && !strcmp (template+strlen(template)-4, EXTSEP_S "kbx") )
92 bakfname = xtrymalloc (strlen (template) + 1);
94 return gpg_error_from_syserror ();
95 strcpy (bakfname, template);
96 strcpy (bakfname+strlen(template)-4, EXTSEP_S "kb_");
98 tmpfname = xtrymalloc (strlen (template) + 1);
101 gpg_error_t tmperr = gpg_error_from_syserror ();
105 strcpy (tmpfname,template);
106 strcpy (tmpfname + strlen (template)-4, EXTSEP_S "k__");
109 { /* File does not end with kbx, thus we hope we are working on a
110 modern file system and appending a suffix works. */
111 bakfname = xtrymalloc ( strlen (template) + 5);
113 return gpg_error_from_syserror ();
114 strcpy (stpcpy (bakfname, template), EXTSEP_S "kb_");
116 tmpfname = xtrymalloc ( strlen (template) + 5);
119 gpg_error_t tmperr = gpg_error_from_syserror ();
123 strcpy (stpcpy (tmpfname, template), EXTSEP_S "k__");
125 # else /* Posix file names */
126 bakfname = xtrymalloc (strlen (template) + 2);
128 return gpg_error_from_syserror ();
129 strcpy (stpcpy (bakfname,template),"~");
131 tmpfname = xtrymalloc ( strlen (template) + 5);
134 gpg_error_t tmperr = gpg_error_from_syserror ();
138 strcpy (stpcpy (tmpfname,template), EXTSEP_S "tmp");
139 # endif /* Posix filename */
141 *r_fp = fopen (tmpfname, "wb");
144 gpg_error_t tmperr = gpg_error_from_syserror ();
150 *r_bakfname = bakfname;
151 *r_tmpfname = tmpfname;
157 rename_tmp_file (const char *bakfname, const char *tmpfname,
158 const char *fname, int secret )
162 /* restrict the permissions for secret keyboxs */
163 #ifndef HAVE_DOSISH_SYSTEM
164 /* if (secret && !opt.preserve_permissions) */
166 /* if (chmod (tmpfname, S_IRUSR | S_IWUSR) ) */
168 /* log_debug ("chmod of '%s' failed: %s\n", */
169 /* tmpfname, strerror(errno) ); */
170 /* return KEYBOX_Write_File; */
175 /* fixme: invalidate close caches (not used with stdio)*/
176 /* iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, (char*)tmpfname ); */
177 /* iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, (char*)bakfname ); */
178 /* iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, (char*)fname ); */
180 /* First make a backup file except for secret keyboxes. */
183 #if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
184 gnupg_remove (bakfname);
186 if (rename (fname, bakfname) )
188 return gpg_error_from_syserror ();
192 /* Then rename the file. */
193 #if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
194 gnupg_remove (fname);
196 if (rename (tmpfname, fname) )
198 rc = gpg_error_from_syserror ();
201 /* log_info ("WARNING: 2 files with confidential" */
202 /* " information exists.\n"); */
203 /* log_info ("%s is the unchanged one\n", fname ); */
204 /* log_info ("%s is the new one\n", tmpfname ); */
205 /* log_info ("Please fix this possible security flaw\n"); */
215 /* Perform insert/delete/update operation. MODE is one of
216 FILECOPY_INSERT, FILECOPY_DELETE, FILECOPY_UPDATE. FOR_OPENPGP
217 indicates that this is called due to an OpenPGP keyblock change. */
219 blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
220 int secret, int for_openpgp, off_t start_offset)
224 char *bakfname = NULL;
225 char *tmpfname = NULL;
226 char buffer[4096]; /* (Must be at least 32 bytes) */
229 /* Open the source file. Because we do a rename, we have to check the
230 permissions of the file */
231 if (access (fname, W_OK))
232 return gpg_error_from_syserror ();
234 fp = fopen (fname, "rb");
235 if (mode == FILECOPY_INSERT && !fp && errno == ENOENT)
237 /* Insert mode but file does not exist:
238 Create a new keybox file. */
239 newfp = fopen (fname, "wb");
241 return gpg_error_from_syserror ();
243 rc = _keybox_write_header_blob (newfp, for_openpgp);
250 rc = _keybox_write_blob (blob, newfp);
257 if ( fclose (newfp) )
258 return gpg_error_from_syserror ();
260 /* if (chmod( fname, S_IRUSR | S_IWUSR )) */
262 /* log_debug ("%s: chmod failed: %s\n", fname, strerror(errno) ); */
263 /* return KEYBOX_File_Error; */
265 return 0; /* Ready. */
270 rc = gpg_error_from_syserror ();
274 /* Create the new file. */
275 rc = create_tmp_file (fname, &bakfname, &tmpfname, &newfp);
283 /* prepare for insert */
284 if (mode == FILECOPY_INSERT)
286 int first_record = 1;
288 /* Copy everything to the new file. If this is for OpenPGP, we
289 make sure that the openpgp flag is set in the header. (We
290 failsafe the blob type.) */
291 while ( (nread = fread (buffer, 1, DIM(buffer), fp)) > 0 )
293 if (first_record && for_openpgp
294 && buffer[4] == KEYBOX_BLOBTYPE_HEADER)
297 buffer[7] |= 0x02; /* OpenPGP data may be available. */
300 if (fwrite (buffer, nread, 1, newfp) != 1)
302 rc = gpg_error_from_syserror ();
310 rc = gpg_error_from_syserror ();
317 /* Prepare for delete or update. */
318 if ( mode == FILECOPY_DELETE || mode == FILECOPY_UPDATE )
322 /* Copy first part to the new file. */
323 while ( current < start_offset )
325 nbytes = DIM(buffer);
326 if (current + nbytes > start_offset)
327 nbytes = start_offset - current;
328 nread = fread (buffer, 1, nbytes, fp);
333 if (fwrite (buffer, nread, 1, newfp) != 1)
335 rc = gpg_error_from_syserror ();
343 rc = gpg_error_from_syserror ();
349 /* Skip this blob. */
350 rc = _keybox_read_blob (NULL, fp);
359 /* Do an insert or update. */
360 if ( mode == FILECOPY_INSERT || mode == FILECOPY_UPDATE )
362 rc = _keybox_write_blob (blob, newfp);
371 /* Copy the rest of the packet for an delete or update. */
372 if (mode == FILECOPY_DELETE || mode == FILECOPY_UPDATE)
374 while ( (nread = fread (buffer, 1, DIM(buffer), fp)) > 0 )
376 if (fwrite (buffer, nread, 1, newfp) != 1)
378 rc = gpg_error_from_syserror ();
386 rc = gpg_error_from_syserror ();
393 /* Close both files. */
396 rc = gpg_error_from_syserror ();
402 rc = gpg_error_from_syserror ();
406 rc = rename_tmp_file (bakfname, tmpfname, fname, secret);
415 /* Insert the OpenPGP keyblock {IMAGE,IMAGELEN} into HD. SIGSTATUS is
416 a vector describing the status of the signatures; its first element
417 gives the number of following elements. */
419 keybox_insert_keyblock (KEYBOX_HANDLE hd, const void *image, size_t imagelen,
426 struct _keybox_openpgp_info info;
429 return gpg_error (GPG_ERR_INV_HANDLE);
431 return gpg_error (GPG_ERR_INV_HANDLE);
432 fname = hd->kb->fname;
434 return gpg_error (GPG_ERR_INV_HANDLE);
437 /* Close this one otherwise we will mess up the position for a next
438 search. Fixme: it would be better to adjust the position after
439 the write operation. */
440 _keybox_close_file (hd);
442 err = _keybox_parse_openpgp (image, imagelen, &nparsed, &info);
445 assert (nparsed <= imagelen);
446 err = _keybox_create_openpgp_blob (&blob, &info, image, imagelen,
447 sigstatus, hd->ephemeral);
448 _keybox_destroy_openpgp_info (&info);
451 err = blob_filecopy (FILECOPY_INSERT, fname, blob, hd->secret, 1, 0);
452 _keybox_release_blob (blob);
453 /* if (!rc && !hd->secret && kb_offtbl) */
455 /* update_offset_hash_table_from_kb (kb_offtbl, kb, 0); */
462 /* Update the current key at HD with the given OpenPGP keyblock in
465 keybox_update_keyblock (KEYBOX_HANDLE hd, const void *image, size_t imagelen)
472 struct _keybox_openpgp_info info;
474 if (!hd || !image || !imagelen)
475 return gpg_error (GPG_ERR_INV_VALUE);
477 return gpg_error (GPG_ERR_NOTHING_FOUND);
478 if (blob_get_type (hd->found.blob) != KEYBOX_BLOBTYPE_PGP)
479 return gpg_error (GPG_ERR_WRONG_BLOB_TYPE);
480 fname = hd->kb->fname;
482 return gpg_error (GPG_ERR_INV_HANDLE);
484 off = _keybox_get_blob_fileoffset (hd->found.blob);
485 if (off == (off_t)-1)
486 return gpg_error (GPG_ERR_GENERAL);
488 /* Close this the file so that we do no mess up the position for a
490 _keybox_close_file (hd);
492 /* Build a new blob. */
493 err = _keybox_parse_openpgp (image, imagelen, &nparsed, &info);
496 assert (nparsed <= imagelen);
497 err = _keybox_create_openpgp_blob (&blob, &info, image, imagelen,
498 NULL, hd->ephemeral);
499 _keybox_destroy_openpgp_info (&info);
501 /* Update the keyblock. */
504 err = blob_filecopy (FILECOPY_UPDATE, fname, blob, hd->secret, 1, off);
505 _keybox_release_blob (blob);
512 #ifdef KEYBOX_WITH_X509
514 keybox_insert_cert (KEYBOX_HANDLE hd, ksba_cert_t cert,
515 unsigned char *sha1_digest)
522 return gpg_error (GPG_ERR_INV_HANDLE);
524 return gpg_error (GPG_ERR_INV_HANDLE);
525 fname = hd->kb->fname;
527 return gpg_error (GPG_ERR_INV_HANDLE);
529 /* Close this one otherwise we will mess up the position for a next
530 search. Fixme: it would be better to adjust the position after
531 the write operation. */
532 _keybox_close_file (hd);
534 rc = _keybox_create_x509_blob (&blob, cert, sha1_digest, hd->ephemeral);
537 rc = blob_filecopy (FILECOPY_INSERT, fname, blob, hd->secret, 0, 0);
538 _keybox_release_blob (blob);
539 /* if (!rc && !hd->secret && kb_offtbl) */
541 /* update_offset_hash_table_from_kb (kb_offtbl, kb, 0); */
548 keybox_update_cert (KEYBOX_HANDLE hd, ksba_cert_t cert,
549 unsigned char *sha1_digest)
558 #endif /*KEYBOX_WITH_X509*/
560 /* Note: We assume that the keybox has been locked before the current
561 search was executed. This is needed so that we can depend on the
562 offset information of the flags. */
564 keybox_set_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int value)
570 size_t flag_pos, flag_size;
571 const unsigned char *buffer;
574 (void)idx; /* Not yet used. */
577 return gpg_error (GPG_ERR_INV_VALUE);
579 return gpg_error (GPG_ERR_NOTHING_FOUND);
581 return gpg_error (GPG_ERR_INV_HANDLE);
583 return gpg_error (GPG_ERR_NOTHING_FOUND);
584 fname = hd->kb->fname;
586 return gpg_error (GPG_ERR_INV_HANDLE);
588 off = _keybox_get_blob_fileoffset (hd->found.blob);
589 if (off == (off_t)-1)
590 return gpg_error (GPG_ERR_GENERAL);
592 buffer = _keybox_get_blob_image (hd->found.blob, &length);
593 ec = _keybox_get_flag_location (buffer, length, what, &flag_pos, &flag_size);
595 return gpg_error (ec);
599 _keybox_close_file (hd);
600 fp = fopen (hd->kb->fname, "r+b");
602 return gpg_error_from_syserror ();
605 if (fseeko (fp, off, SEEK_SET))
606 ec = gpg_error_from_syserror ();
609 unsigned char tmp[4];
611 tmp[0] = value >> 24;
612 tmp[1] = value >> 16;
621 if (fwrite (tmp+4-flag_size, flag_size, 1, fp) != 1)
622 ec = gpg_err_code_from_syserror ();
633 ec = gpg_err_code_from_syserror ();
636 return gpg_error (ec);
642 keybox_delete (KEYBOX_HANDLE hd)
650 return gpg_error (GPG_ERR_INV_VALUE);
652 return gpg_error (GPG_ERR_NOTHING_FOUND);
654 return gpg_error (GPG_ERR_INV_HANDLE);
655 fname = hd->kb->fname;
657 return gpg_error (GPG_ERR_INV_HANDLE);
659 off = _keybox_get_blob_fileoffset (hd->found.blob);
660 if (off == (off_t)-1)
661 return gpg_error (GPG_ERR_GENERAL);
664 _keybox_close_file (hd);
665 fp = fopen (hd->kb->fname, "r+b");
667 return gpg_error_from_syserror ();
669 if (fseeko (fp, off, SEEK_SET))
670 rc = gpg_error_from_syserror ();
671 else if (putc (0, fp) == EOF)
672 rc = gpg_error_from_syserror ();
679 rc = gpg_error_from_syserror ();
686 /* Compress the keybox file. This should be run with the file
689 keybox_compress (KEYBOX_HANDLE hd)
694 char *bakfname = NULL;
695 char *tmpfname = NULL;
697 KEYBOXBLOB blob = NULL;
703 return gpg_error (GPG_ERR_INV_HANDLE);
705 return gpg_error (GPG_ERR_INV_HANDLE);
707 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
708 fname = hd->kb->fname;
710 return gpg_error (GPG_ERR_INV_HANDLE);
712 _keybox_close_file (hd);
714 /* Open the source file. Because we do a rename, we have to check the
715 permissions of the file */
716 if (access (fname, W_OK))
717 return gpg_error_from_syserror ();
719 fp = fopen (fname, "rb");
720 if (!fp && errno == ENOENT)
721 return 0; /* Ready. File has been deleted right after the access above. */
724 rc = gpg_error_from_syserror ();
728 /* A quick test to see if we need to compress the file at all. We
729 schedule a compress run after 3 hours. */
730 if ( !_keybox_read_blob (&blob, fp) )
732 const unsigned char *buffer;
735 buffer = _keybox_get_blob_image (blob, &length);
736 if (length > 4 && buffer[4] == KEYBOX_BLOBTYPE_HEADER)
738 u32 last_maint = buf32_to_u32 (buffer+20);
740 if ( (last_maint + 3*3600) > time (NULL) )
743 _keybox_release_blob (blob);
744 return 0; /* Compress run not yet needed. */
747 _keybox_release_blob (blob);
748 fseek (fp, 0, SEEK_SET);
752 /* Create the new file. */
753 rc = create_tmp_file (fname, &bakfname, &tmpfname, &newfp);
761 /* Processing loop. By reading using _keybox_read_blob we
762 automagically skip any blobs flagged as deleted. Thus what we
763 only have to do is to check all ephemeral flagged blocks whether
764 their time has come and write out all other blobs. */
765 cut_time = time(NULL) - 86400;
768 for (rc=0; !(read_rc = _keybox_read_blob2 (&blob, fp, &skipped_deleted));
769 _keybox_release_blob (blob), blob = NULL )
771 unsigned int blobflags;
772 const unsigned char *buffer;
773 size_t length, pos, size;
778 buffer = _keybox_get_blob_image (blob, &length);
782 if (length > 4 && buffer[4] == KEYBOX_BLOBTYPE_HEADER)
784 /* Write out the blob with an updated maintenance time
785 stamp and if needed (ie. used by gpg) set the openpgp
787 _keybox_update_header_blob (blob, hd->for_openpgp);
788 rc = _keybox_write_blob (blob, newfp);
794 /* The header blob is missing. Insert it. */
795 rc = _keybox_write_header_blob (newfp, hd->for_openpgp);
800 else if (length > 4 && buffer[4] == KEYBOX_BLOBTYPE_HEADER)
802 /* Oops: There is another header record - remove it. */
807 if (_keybox_get_flag_location (buffer, length,
808 KEYBOX_FLAG_BLOB, &pos, &size)
811 rc = gpg_error (GPG_ERR_BUG);
814 blobflags = buf16_to_uint (buffer+pos);
815 if ((blobflags & KEYBOX_FLAG_BLOB_EPHEMERAL))
817 /* This is an ephemeral blob. */
818 if (_keybox_get_flag_location (buffer, length,
819 KEYBOX_FLAG_CREATED_AT, &pos, &size)
821 created_at = 0; /* oops. */
823 created_at = buf32_to_u32 (buffer+pos);
825 if (created_at && created_at < cut_time)
828 continue; /* Skip this blob. */
832 rc = _keybox_write_blob (blob, newfp);
838 _keybox_release_blob (blob); blob = NULL;
839 if (!rc && read_rc == -1)
844 /* Close both files. */
845 if (fclose(fp) && !rc)
846 rc = gpg_error_from_syserror ();
847 if (fclose(newfp) && !rc)
848 rc = gpg_error_from_syserror ();
850 /* Rename or remove the temporary file. */
851 if (rc || !any_changes)
852 gnupg_remove (tmpfname);
854 rc = rename_tmp_file (bakfname, tmpfname, fname, hd->secret);