2002-04-24 Marcus Brinkmann <marcus@g10code.de>
[gnupg.git] / kbx / keybox-update.c
blobd49c3d0272181245090bea36a35c731d8852a19f
1 /* keybox-update.c - keybox update operations
2 * Copyright (C) 2001 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 2 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, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
21 #include <config.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <unistd.h>
28 #include "keybox-defs.h"
30 #define EXTSEP_S "."
33 static int
34 create_tmp_file (const char *template,
35 char **r_bakfname, char **r_tmpfname, FILE **r_fp)
37 char *bakfname, *tmpfname;
39 *r_bakfname = NULL;
40 *r_tmpfname = NULL;
42 # ifdef USE_ONLY_8DOT3
43 /* Here is another Windoze bug?:
44 * you cant rename("pubring.kbx.tmp", "pubring.kbx");
45 * but rename("pubring.kbx.tmp", "pubring.aaa");
46 * works. So we replace .kbx by .bak or .tmp
48 if (strlen (template) > 4
49 && !strcmp (template+strlen(template)-4, EXTSEP_S "kbx") )
51 bakfname = xtrymalloc (strlen (template) + 1);
52 if (!bakfname)
53 return KEYBOX_Out_Of_Core;
54 strcpy (bakfname, template);
55 strcpy (bakfname+strlen(template)-4, EXTSEP_S "bak");
57 tmpfname = xtrymalloc (strlen (template) + 1);
58 if (!tmpfname)
60 xfree (bakfname);
61 return KEYBOX_Out_Of_Core;
63 strcpy (tmpfname,template);
64 strcpy (tmpfname + strlen (template)-4, EXTSEP_S "tmp");
66 else
67 { /* file does not end with kbx; hmmm */
68 bakfname = xtrymalloc ( strlen (template) + 5);
69 if (!bakfname)
70 return KEYBOX_Out_Of_Core;
71 strcpy (stpcpy (bakfname, template), EXTSEP_S "bak");
73 tmpfname = xtrymalloc ( strlen (template) + 5);
74 if (!tmpfname)
76 xfree (bakfname);
77 return KEYBOX_Out_Of_Core;
79 strcpy (stpcpy (tmpfname, template), EXTSEP_S "tmp");
81 # else /* Posix file names */
82 bakfname = xtrymalloc (strlen (template) + 2);
83 if (!bakfname)
84 return KEYBOX_Out_Of_Core;
85 strcpy (stpcpy (bakfname,template),"~");
87 tmpfname = xtrymalloc ( strlen (template) + 5);
88 if (!tmpfname)
90 xfree (bakfname);
91 return KEYBOX_Out_Of_Core;
93 strcpy (stpcpy (tmpfname,template), EXTSEP_S "tmp");
94 # endif /* Posix filename */
96 *r_fp = fopen (tmpfname, "wb");
97 if (!*r_fp)
99 xfree (tmpfname);
100 xfree (bakfname);
101 return KEYBOX_File_Create_Error;
104 *r_bakfname = bakfname;
105 *r_tmpfname = tmpfname;
106 return 0;
110 static int
111 rename_tmp_file (const char *bakfname, const char *tmpfname,
112 const char *fname, int secret )
114 int rc=0;
116 /* restrict the permissions for secret keyboxs */
117 #ifndef HAVE_DOSISH_SYSTEM
118 /* if (secret && !opt.preserve_permissions) */
119 /* { */
120 /* if (chmod (tmpfname, S_IRUSR | S_IWUSR) ) */
121 /* { */
122 /* log_debug ("chmod of `%s' failed: %s\n", */
123 /* tmpfname, strerror(errno) ); */
124 /* return KEYBOX_Write_File; */
125 /* } */
126 /* } */
127 #endif
129 /* fixme: invalidate close caches (not used with stdio)*/
130 /* iobuf_ioctl (NULL, 2, 0, (char*)tmpfname ); */
131 /* iobuf_ioctl (NULL, 2, 0, (char*)bakfname ); */
132 /* iobuf_ioctl (NULL, 2, 0, (char*)fname ); */
134 /* first make a backup file except for secret keyboxs */
135 if (!secret)
137 #if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
138 remove (bakfname);
139 #endif
140 if (rename (fname, bakfname) )
142 return KEYBOX_File_Error;
146 /* then rename the file */
147 #if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
148 remove (fname);
149 #endif
150 if (rename (tmpfname, fname) )
152 rc = KEYBOX_File_Error;
153 if (secret)
155 /* log_info ("WARNING: 2 files with confidential" */
156 /* " information exists.\n"); */
157 /* log_info ("%s is the unchanged one\n", fname ); */
158 /* log_info ("%s is the new one\n", tmpfname ); */
159 /* log_info ("Please fix this possible security flaw\n"); */
161 return rc;
164 return 0;
169 /* Perform insert/delete/update operation.
170 mode 1 = insert
171 2 = delete
172 3 = update
174 static int
175 blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
176 int secret, off_t start_offset, unsigned int n_packets )
178 FILE *fp, *newfp;
179 int rc=0;
180 char *bakfname = NULL;
181 char *tmpfname = NULL;
182 char buffer[4096];
183 int nread, nbytes;
185 /* Open the source file. Because we do a rename, we have to check the
186 permissions of the file */
187 if (access (fname, W_OK))
188 return KEYBOX_Write_Error;
190 fp = fopen (fname, "rb");
191 if (mode == 1 && !fp && errno == ENOENT)
192 { /* insert mode but file does not exist: create a new keybox file */
193 newfp = fopen (fname, "wb");
194 if (!newfp )
196 return KEYBOX_File_Create_Error;
199 rc = _keybox_write_blob (blob, newfp);
200 if (rc)
202 return rc;
204 if ( fclose (newfp) )
206 return KEYBOX_File_Create_Error;
209 /* if (chmod( fname, S_IRUSR | S_IWUSR )) */
210 /* { */
211 /* log_debug ("%s: chmod failed: %s\n", fname, strerror(errno) ); */
212 /* return KEYBOX_File_Error; */
213 /* } */
214 return 0; /* ready */
217 if (!fp)
219 rc = KEYBOX_File_Open_Error;
220 goto leave;
223 /* create the new file */
224 rc = create_tmp_file (fname, &bakfname, &tmpfname, &newfp);
225 if (rc)
227 fclose(fp);
228 goto leave;
231 /* prepare for insert */
232 if (mode == 1)
234 /* copy everything to the new file */
235 while ( (nread = fread (buffer, 1, DIM(buffer), fp)) > 0 )
237 if (fwrite (buffer, nread, 1, newfp) != 1)
239 rc = KEYBOX_Write_Error;
240 goto leave;
243 if (ferror (fp))
245 rc = KEYBOX_Read_Error;
246 goto leave;
250 /* prepare for delete or update */
251 if ( mode == 2 || mode == 3 )
253 off_t current = 0;
255 /* copy first part to the new file */
256 while ( current < start_offset )
258 nbytes = DIM(buffer);
259 if (current + nbytes > start_offset)
260 nbytes = start_offset - current;
261 nread = fread (buffer, 1, nbytes, fp);
262 if (!fread)
263 break;
264 current += nread;
266 if (fwrite (buffer, nread, 1, newfp) != 1)
268 rc = KEYBOX_Write_Error;
269 goto leave;
272 if (ferror (fp))
274 rc = KEYBOX_Read_Error;
275 goto leave;
278 /* skip this blob */
279 rc = _keybox_read_blob (NULL, fp);
280 if (rc)
281 return rc;
284 /* Do an insert or update */
285 if ( mode == 1 || mode == 3 )
287 rc = _keybox_write_blob (blob, newfp);
288 if (rc)
289 return rc;
292 /* copy the rest of the packet for an delete or update */
293 if (mode == 2 || mode == 3)
295 while ( (nread = fread (buffer, 1, DIM(buffer), fp)) > 0 )
297 if (fwrite (buffer, nread, 1, newfp) != 1)
299 rc = KEYBOX_Write_Error;
300 goto leave;
303 if (ferror (fp))
305 rc = KEYBOX_Read_Error;
306 goto leave;
310 /* close both files */
311 if (fclose(fp))
313 rc = KEYBOX_File_Close_Error;
314 fclose (newfp);
315 goto leave;
317 if (fclose(newfp))
319 rc = KEYBOX_File_Close_Error;
320 goto leave;
323 rc = rename_tmp_file (bakfname, tmpfname, fname, secret);
325 leave:
326 xfree(bakfname);
327 xfree(tmpfname);
328 return rc;
334 #ifdef KEYBOX_WITH_X509
336 keybox_insert_cert (KEYBOX_HANDLE hd, KsbaCert cert,
337 unsigned char *sha1_digest)
339 int rc;
340 const char *fname;
341 KEYBOXBLOB blob;
343 if (!hd)
344 return KEYBOX_Invalid_Handle;
345 if (!hd->kb)
346 return KEYBOX_Invalid_Handle;
347 fname = hd->kb->fname;
348 if (!fname)
349 return KEYBOX_Invalid_Handle;
351 /* close this one otherwise we will mess up the position for a next
352 search. Fixme: it would be better to adjust the position after
353 the write opertions. */
354 if (hd->fp)
356 fclose (hd->fp);
357 hd->fp = NULL;
360 rc = _keybox_create_x509_blob (&blob, cert, sha1_digest);
361 if (!rc)
363 rc = blob_filecopy (1, fname, blob, hd->secret, 0, 0 );
364 _keybox_release_blob (blob);
365 /* if (!rc && !hd->secret && kb_offtbl) */
366 /* { */
367 /* update_offset_hash_table_from_kb (kb_offtbl, kb, 0); */
368 /* } */
370 return rc;
374 keybox_update_cert (KEYBOX_HANDLE hd, KsbaCert cert,
375 unsigned char *sha1_digest)
377 return -1;
381 #endif /*KEYBOX_WITH_X509*/
385 keybox_delete (KEYBOX_HANDLE hd)
387 return -1;