mutt stable branch with some hacks
1/*
2 * Copyright (C) 2001-2002,2007 Thomas Roessler <roessler@does-not-exist.org>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of
7 * the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public
15 * License along with this program; if not, write to the Free
16 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 * MA 02110-1301, USA.
18 */
19
20#if HAVE_CONFIG_H
21# include "config.h"
22#endif
23
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include <unistd.h>
28#include <time.h>
29
30
31
32/* yuck, we were including this one somewhere below. */
33#include "mutt.h"
34
35#include "lib.h"
36#include "pgppacket.h"
37
38#define CHUNKSIZE 1024
39
40static unsigned char *pbuf = NULL;
41static size_t plen = 0;
42
43static int read_material (size_t material, size_t * used, FILE * fp)
44{
45 if (*used + material >= plen)
46 {
47 unsigned char *p;
48 size_t nplen;
49
50 nplen = *used + material + CHUNKSIZE;
51
52 if (!(p = realloc (pbuf, nplen))) /* __MEM_CHECKED__ */
53 {
54 perror ("realloc");
55 return -1;
56 }
57 plen = nplen;
58 pbuf = p;
59 }
60
61 if (fread (pbuf + *used, 1, material, fp) < material)
62 {
63 perror ("fread");
64 return -1;
65 }
66
67 *used += material;
68 return 0;
69}
70
71unsigned char *pgp_read_packet (FILE * fp, size_t * len)
72{
73 size_t used = 0;
74 LOFF_T startpos;
75 unsigned char ctb;
76 unsigned char b;
77 size_t material;
78
79 startpos = ftello (fp);
80
81 if (!plen)
82 {
83 plen = CHUNKSIZE;
84 pbuf = safe_malloc (plen);
85 }
86
87 if (fread (&ctb, 1, 1, fp) < 1)
88 {
89 if (!feof (fp))
90 perror ("fread");
91 goto bail;
92 }
93
94 if (!(ctb & 0x80))
95 {
96 goto bail;
97 }
98
99 if (ctb & 0x40) /* handle PGP 5.0 packets. */
100 {
101 int partial = 0;
102 pbuf[0] = ctb;
103 used++;
104
105 do
106 {
107 if (fread (&b, 1, 1, fp) < 1)
108 {
109 perror ("fread");
110 goto bail;
111 }
112
113 if (b < 192)
114 {
115 material = b;
116 partial = 0;
117 /* material -= 1; */
118 }
119 else if (192 <= b && b <= 223)
120 {
121 material = (b - 192) * 256;
122 if (fread (&b, 1, 1, fp) < 1)
123 {
124 perror ("fread");
125 goto bail;
126 }
127 material += b + 192;
128 partial = 0;
129 /* material -= 2; */
130 }
131 else if (b < 255)
132 {
133 material = 1 << (b & 0x1f);
134 partial = 1;
135 /* material -= 1; */
136 }
137 else
138 /* b == 255 */
139 {
140 unsigned char buf[4];
141 if (fread (buf, 4, 1, fp) < 1)
142 {
143 perror ("fread");
144 goto bail;
145 }
146 /*assert( sizeof(material) >= 4 ); */
147 material = buf[0] << 24;
148 material |= buf[1] << 16;
149 material |= buf[2] << 8;
150 material |= buf[3];
151 partial = 0;
152 /* material -= 5; */
153 }
154
155 if (read_material (material, &used, fp) == -1)
156 goto bail;
157
158 }
159 while (partial);
160 }
161 else
162 /* Old-Style PGP */
163 {
164 int bytes = 0;
165 pbuf[0] = 0x80 | ((ctb >> 2) & 0x0f);
166 used++;
167
168 switch (ctb & 0x03)
169 {
170 case 0:
171 {
172 if (fread (&b, 1, 1, fp) < 1)
173 {
174 perror ("fread");
175 goto bail;
176 }
177
178 material = b;
179 break;
180 }
181
182 case 1:
183 bytes = 2;
184 /* fall through */
185
186 case 2:
187 {
188 int i;
189
190 if (!bytes)
191 bytes = 4;
192
193 material = 0;
194
195 for (i = 0; i < bytes; i++)
196 {
197 if (fread (&b, 1, 1, fp) < 1)
198 {
199 perror ("fread");
200 goto bail;
201 }
202
203 material = (material << 8) + b;
204 }
205 break;
206 }
207
208 default:
209 goto bail;
210 }
211
212 if (read_material (material, &used, fp) == -1)
213 goto bail;
214 }
215
216 if (len)
217 *len = used;
218
219 return pbuf;
220
221bail:
222
223 fseeko (fp, startpos, SEEK_SET);
224 return NULL;
225}
226
227void pgp_release_packet (void)
228{
229 plen = 0;
230 FREE (&pbuf);
231}