Line data Source code
1 : /* keybox-file.c - File operations
2 : * Copyright (C) 2001, 2003 Free Software Foundation, Inc.
3 : *
4 : * This file is part of GnuPG.
5 : *
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.
10 : *
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.
15 : *
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/>.
18 : */
19 :
20 : #include <config.h>
21 : #include <stdlib.h>
22 : #include <stdio.h>
23 : #include <string.h>
24 : #include <errno.h>
25 : #include <time.h>
26 :
27 : #include "keybox-defs.h"
28 :
29 :
30 : #define IMAGELEN_LIMIT (5*1024*1024)
31 :
32 :
33 : #if !defined(HAVE_FTELLO) && !defined(ftello)
34 : static off_t
35 : ftello (FILE *stream)
36 : {
37 : long int off;
38 :
39 : off = ftell (stream);
40 : if (off == -1)
41 : return (off_t)-1;
42 : return off;
43 : }
44 : #endif /* !defined(HAVE_FTELLO) && !defined(ftello) */
45 :
46 :
47 :
48 : /* Read a block at the current postion and return it in r_blob.
49 : r_blob may be NULL to simply skip the current block. */
50 : int
51 83914 : _keybox_read_blob2 (KEYBOXBLOB *r_blob, FILE *fp, int *skipped_deleted)
52 : {
53 : unsigned char *image;
54 83914 : size_t imagelen = 0;
55 : int c1, c2, c3, c4, type;
56 : int rc;
57 : off_t off;
58 :
59 83914 : *skipped_deleted = 0;
60 : again:
61 84553 : if (r_blob)
62 84551 : *r_blob = NULL;
63 84553 : off = ftello (fp);
64 84553 : if (off == (off_t)-1)
65 0 : return gpg_error_from_syserror ();
66 :
67 84553 : if ((c1 = getc (fp)) == EOF
68 84342 : || (c2 = getc (fp)) == EOF
69 84342 : || (c3 = getc (fp)) == EOF
70 84342 : || (c4 = getc (fp)) == EOF
71 84342 : || (type = getc (fp)) == EOF)
72 : {
73 211 : if ( c1 == EOF && !ferror (fp) )
74 211 : return -1; /* eof */
75 0 : if (!ferror (fp))
76 0 : return gpg_error (GPG_ERR_TOO_SHORT);
77 0 : return gpg_error_from_syserror ();
78 : }
79 :
80 84342 : imagelen = (c1 << 24) | (c2 << 16) | (c3 << 8 ) | c4;
81 84342 : if (imagelen < 5)
82 0 : return gpg_error (GPG_ERR_TOO_SHORT);
83 :
84 84342 : if (!type)
85 : {
86 : /* Special treatment for empty blobs. */
87 639 : if (fseek (fp, imagelen-5, SEEK_CUR))
88 0 : return gpg_error_from_syserror ();
89 639 : *skipped_deleted = 1;
90 639 : goto again;
91 : }
92 :
93 83703 : if (imagelen > IMAGELEN_LIMIT) /* Sanity check. */
94 : {
95 : /* Seek forward so that the caller may choose to ignore this
96 : record. */
97 0 : if (fseek (fp, imagelen-5, SEEK_CUR))
98 0 : return gpg_error_from_syserror ();
99 0 : return gpg_error (GPG_ERR_TOO_LARGE);
100 : }
101 :
102 83703 : image = xtrymalloc (imagelen);
103 83703 : if (!image)
104 0 : return gpg_error_from_syserror ();
105 :
106 83703 : image[0] = c1; image[1] = c2; image[2] = c3; image[3] = c4; image[4] = type;
107 83703 : if (fread (image+5, imagelen-5, 1, fp) != 1)
108 : {
109 0 : gpg_error_t tmperr = gpg_error_from_syserror ();
110 0 : xfree (image);
111 0 : return tmperr;
112 : }
113 :
114 83703 : rc = r_blob? _keybox_new_blob (r_blob, image, imagelen, off) : 0;
115 83703 : if (rc || !r_blob)
116 2 : xfree (image);
117 83703 : return rc;
118 : }
119 :
120 : int
121 83911 : _keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp)
122 : {
123 : int dummy;
124 83911 : return _keybox_read_blob2 (r_blob, fp, &dummy);
125 : }
126 :
127 :
128 : /* Write the block to the current file position */
129 : int
130 65 : _keybox_write_blob (KEYBOXBLOB blob, FILE *fp)
131 : {
132 : const unsigned char *image;
133 : size_t length;
134 :
135 65 : image = _keybox_get_blob_image (blob, &length);
136 :
137 65 : if (length > IMAGELEN_LIMIT)
138 0 : return gpg_error (GPG_ERR_TOO_LARGE);
139 :
140 65 : if (fwrite (image, length, 1, fp) != 1)
141 0 : return gpg_error_from_syserror ();
142 65 : return 0;
143 : }
144 :
145 :
146 : /* Write a fresh header type blob. */
147 : int
148 2 : _keybox_write_header_blob (FILE *fp, int for_openpgp)
149 : {
150 : unsigned char image[32];
151 : u32 val;
152 :
153 2 : memset (image, 0, sizeof image);
154 : /* Length of this blob. */
155 2 : image[3] = 32;
156 :
157 2 : image[4] = KEYBOX_BLOBTYPE_HEADER;
158 2 : image[5] = 1; /* Version */
159 2 : if (for_openpgp)
160 1 : image[7] = 0x02; /* OpenPGP data may be available. */
161 :
162 2 : memcpy (image+8, "KBXf", 4);
163 2 : val = time (NULL);
164 : /* created_at and last maintenance run. */
165 2 : image[16] = (val >> 24);
166 2 : image[16+1] = (val >> 16);
167 2 : image[16+2] = (val >> 8);
168 2 : image[16+3] = (val );
169 2 : image[20] = (val >> 24);
170 2 : image[20+1] = (val >> 16);
171 2 : image[20+2] = (val >> 8);
172 2 : image[20+3] = (val );
173 :
174 2 : if (fwrite (image, 32, 1, fp) != 1)
175 0 : return gpg_error_from_syserror ();
176 2 : return 0;
177 : }
|