fix regressions
[apps/madmutt.git] / pgppacket.c
1 /*
2  * Copyright notice from original mutt:
3  * Copyright (C) 2001 Thomas Roessler <roessler@does-not-exist.org>
4  *
5  * This file is part of mutt-ng, see http://www.muttng.org/.
6  * It's licensed under the GNU General Public License,
7  * please see the file GPL in the top level source directory.
8  */
9
10 #if HAVE_CONFIG_H
11 # include "config.h"
12 #endif
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <unistd.h>
18 #include <time.h>
19
20 #include <lib-lib/mem.h>
21
22 #include "sha1.h"
23 #include "lib.h"
24 #include "pgplib.h"
25 #include "pgppacket.h"
26
27 #include "lib/mem.h"
28
29 #define CHUNKSIZE 1024
30
31 static unsigned char *pbuf = NULL;
32 static size_t plen = 0;
33
34 static int read_material (size_t material, size_t * used, FILE * fp)
35 {
36   if (*used + material >= plen) {
37     unsigned char *p;
38     size_t nplen;
39
40     nplen = *used + material + CHUNKSIZE;
41
42     if (!(p = realloc (pbuf, nplen))) { /* __MEM_CHECKED__ */
43       perror ("realloc");
44       return -1;
45     }
46     plen = nplen;
47     pbuf = p;
48   }
49
50   if (fread (pbuf + *used, 1, material, fp) < material) {
51     perror ("fread");
52     return -1;
53   }
54
55   *used += material;
56   return 0;
57 }
58
59 unsigned char *pgp_read_packet (FILE * fp, size_t * len)
60 {
61   size_t used = 0;
62   off_t startpos;
63   unsigned char ctb;
64   unsigned char b;
65   size_t material;
66
67   startpos = ftello (fp);
68
69   if (!plen) {
70     pbuf = p_new(char, plen = CHUNKSIZE);
71   }
72
73   if (fread (&ctb, 1, 1, fp) < 1) {
74     if (!feof (fp))
75       perror ("fread");
76     goto bail;
77   }
78
79   if (!(ctb & 0x80)) {
80     goto bail;
81   }
82
83   if (ctb & 0x40) {             /* handle PGP 5.0 packets. */
84     int partial = 0;
85
86     pbuf[0] = ctb;
87     used++;
88
89     do {
90       if (fread (&b, 1, 1, fp) < 1) {
91         perror ("fread");
92         goto bail;
93       }
94
95       if (b < 192) {
96         material = b;
97         partial = 0;
98         /* material -= 1; */
99       }
100       else if (192 <= b && b <= 223) {
101         material = (b - 192) * 256;
102         if (fread (&b, 1, 1, fp) < 1) {
103           perror ("fread");
104           goto bail;
105         }
106         material += b + 192;
107         partial = 0;
108         /* material -= 2; */
109       }
110       else if (b < 255) {
111         material = 1 << (b & 0x1f);
112         partial = 1;
113         /* material -= 1; */
114       }
115       else
116         /* b == 255 */
117       {
118         unsigned char buf[4];
119
120         if (fread (buf, 4, 1, fp) < 1) {
121           perror ("fread");
122           goto bail;
123         }
124         /*assert( sizeof(material) >= 4 ); */
125         material = buf[0] << 24;
126         material |= buf[1] << 16;
127         material |= buf[2] << 8;
128         material |= buf[3];
129         partial = 0;
130         /* material -= 5; */
131       }
132
133       if (read_material (material, &used, fp) == -1)
134         goto bail;
135
136     }
137     while (partial);
138   }
139   else
140     /* Old-Style PGP */
141   {
142     int bytes = 0;
143
144     pbuf[0] = 0x80 | ((ctb >> 2) & 0x0f);
145     used++;
146
147     switch (ctb & 0x03) {
148     case 0:
149       {
150         if (fread (&b, 1, 1, fp) < 1) {
151           perror ("fread");
152           goto bail;
153         }
154
155         material = b;
156         break;
157       }
158
159     case 1:
160       bytes = 2;
161
162     case 2:
163       {
164         int i;
165
166         if (!bytes)
167           bytes = 4;
168
169         material = 0;
170
171         for (i = 0; i < bytes; i++) {
172           if (fread (&b, 1, 1, fp) < 1) {
173             perror ("fread");
174             goto bail;
175           }
176
177           material = (material << 8) + b;
178         }
179         break;
180       }
181
182     default:
183       goto bail;
184     }
185
186     if (read_material (material, &used, fp) == -1)
187       goto bail;
188   }
189
190   if (len)
191     *len = used;
192
193   return pbuf;
194
195 bail:
196
197   fseeko (fp, startpos, SEEK_SET);
198   return NULL;
199 }
200
201 void pgp_release_packet (void)
202 {
203   plen = 0;
204   p_delete(&pbuf);
205 }