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 position and return it in r_blob.
49 : r_blob may be NULL to simply skip the current block. */
50 : int
51 81227 : _keybox_read_blob2 (KEYBOXBLOB *r_blob, FILE *fp, int *skipped_deleted)
52 : {
53 : unsigned char *image;
54 81227 : size_t imagelen = 0;
55 : int c1, c2, c3, c4, type;
56 : int rc;
57 : off_t off;
58 :
59 81227 : *skipped_deleted = 0;
60 : again:
61 81260 : if (r_blob)
62 81258 : *r_blob = NULL;
63 81260 : off = ftello (fp);
64 81260 : if (off == (off_t)-1)
65 0 : return gpg_error_from_syserror ();
66 :
67 81260 : if ((c1 = getc (fp)) == EOF
68 81076 : || (c2 = getc (fp)) == EOF
69 81076 : || (c3 = getc (fp)) == EOF
70 81076 : || (c4 = getc (fp)) == EOF
71 81076 : || (type = getc (fp)) == EOF)
72 : {
73 184 : if ( c1 == EOF && !ferror (fp) )
74 184 : 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 81076 : imagelen = ((unsigned int) c1 << 24) | (c2 << 16) | (c3 << 8 ) | c4;
81 81076 : if (imagelen < 5)
82 0 : return gpg_error (GPG_ERR_TOO_SHORT);
83 :
84 81076 : if (!type)
85 : {
86 : /* Special treatment for empty blobs. */
87 33 : if (fseek (fp, imagelen-5, SEEK_CUR))
88 0 : return gpg_error_from_syserror ();
89 33 : *skipped_deleted = 1;
90 33 : goto again;
91 : }
92 :
93 81043 : 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 81043 : image = xtrymalloc (imagelen);
103 81043 : if (!image)
104 0 : return gpg_error_from_syserror ();
105 :
106 81043 : image[0] = c1; image[1] = c2; image[2] = c3; image[3] = c4; image[4] = type;
107 81043 : 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 81043 : rc = r_blob? _keybox_new_blob (r_blob, image, imagelen, off) : 0;
115 81043 : if (rc || !r_blob)
116 2 : xfree (image);
117 81043 : return rc;
118 : }
119 :
120 : int
121 81227 : _keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp)
122 : {
123 : int dummy;
124 81227 : return _keybox_read_blob2 (r_blob, fp, &dummy);
125 : }
126 :
127 :
128 : /* Write the block to the current file position */
129 : int
130 69 : _keybox_write_blob (KEYBOXBLOB blob, FILE *fp)
131 : {
132 : const unsigned char *image;
133 : size_t length;
134 :
135 69 : image = _keybox_get_blob_image (blob, &length);
136 :
137 69 : if (length > IMAGELEN_LIMIT)
138 0 : return gpg_error (GPG_ERR_TOO_LARGE);
139 :
140 69 : if (fwrite (image, length, 1, fp) != 1)
141 0 : return gpg_error_from_syserror ();
142 69 : return 0;
143 : }
144 :
145 :
146 : /* Write a fresh header type blob. */
147 : int
148 3 : _keybox_write_header_blob (FILE *fp, int for_openpgp)
149 : {
150 : unsigned char image[32];
151 : u32 val;
152 :
153 3 : memset (image, 0, sizeof image);
154 : /* Length of this blob. */
155 3 : image[3] = 32;
156 :
157 3 : image[4] = KEYBOX_BLOBTYPE_HEADER;
158 3 : image[5] = 1; /* Version */
159 3 : if (for_openpgp)
160 2 : image[7] = 0x02; /* OpenPGP data may be available. */
161 :
162 3 : memcpy (image+8, "KBXf", 4);
163 3 : val = time (NULL);
164 : /* created_at and last maintenance run. */
165 3 : image[16] = (val >> 24);
166 3 : image[16+1] = (val >> 16);
167 3 : image[16+2] = (val >> 8);
168 3 : image[16+3] = (val );
169 3 : image[20] = (val >> 24);
170 3 : image[20+1] = (val >> 16);
171 3 : image[20+2] = (val >> 8);
172 3 : image[20+3] = (val );
173 :
174 3 : if (fwrite (image, 32, 1, fp) != 1)
175 0 : return gpg_error_from_syserror ();
176 3 : return 0;
177 : }
|