Rocco Rutte:
[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 "sha1.h"
21 #include "lib.h"
22 #include "pgplib.h"
23 #include "pgppacket.h"
24
25 #define CHUNKSIZE 1024
26
27 static unsigned char *pbuf = NULL;
28 static size_t plen = 0;
29
30 static int read_material (size_t material, size_t * used, FILE * fp)
31 {
32   if (*used + material >= plen) {
33     unsigned char *p;
34     size_t nplen;
35
36     nplen = *used + material + CHUNKSIZE;
37
38     if (!(p = realloc (pbuf, nplen))) { /* __MEM_CHECKED__ */
39       perror ("realloc");
40       return -1;
41     }
42     plen = nplen;
43     pbuf = p;
44   }
45
46   if (fread (pbuf + *used, 1, material, fp) < material) {
47     perror ("fread");
48     return -1;
49   }
50
51   *used += material;
52   return 0;
53 }
54
55 unsigned char *pgp_read_packet (FILE * fp, size_t * len)
56 {
57   size_t used = 0;
58   long startpos;
59   unsigned char ctb;
60   unsigned char b;
61   size_t material;
62
63   startpos = ftell (fp);
64
65   if (!plen) {
66     plen = CHUNKSIZE;
67     pbuf = safe_malloc (plen);
68   }
69
70   if (fread (&ctb, 1, 1, fp) < 1) {
71     if (!feof (fp))
72       perror ("fread");
73     goto bail;
74   }
75
76   if (!(ctb & 0x80)) {
77     goto bail;
78   }
79
80   if (ctb & 0x40) {             /* handle PGP 5.0 packets. */
81     int partial = 0;
82
83     pbuf[0] = ctb;
84     used++;
85
86     do {
87       if (fread (&b, 1, 1, fp) < 1) {
88         perror ("fread");
89         goto bail;
90       }
91
92       if (b < 192) {
93         material = b;
94         partial = 0;
95         /* material -= 1; */
96       }
97       else if (192 <= b && b <= 223) {
98         material = (b - 192) * 256;
99         if (fread (&b, 1, 1, fp) < 1) {
100           perror ("fread");
101           goto bail;
102         }
103         material += b + 192;
104         partial = 0;
105         /* material -= 2; */
106       }
107       else if (b < 255) {
108         material = 1 << (b & 0x1f);
109         partial = 1;
110         /* material -= 1; */
111       }
112       else
113         /* b == 255 */
114       {
115         unsigned char buf[4];
116
117         if (fread (buf, 4, 1, fp) < 1) {
118           perror ("fread");
119           goto bail;
120         }
121         /*assert( sizeof(material) >= 4 ); */
122         material = buf[0] << 24;
123         material |= buf[1] << 16;
124         material |= buf[2] << 8;
125         material |= buf[3];
126         partial = 0;
127         /* material -= 5; */
128       }
129
130       if (read_material (material, &used, fp) == -1)
131         goto bail;
132
133     }
134     while (partial);
135   }
136   else
137     /* Old-Style PGP */
138   {
139     int bytes = 0;
140
141     pbuf[0] = 0x80 | ((ctb >> 2) & 0x0f);
142     used++;
143
144     switch (ctb & 0x03) {
145     case 0:
146       {
147         if (fread (&b, 1, 1, fp) < 1) {
148           perror ("fread");
149           goto bail;
150         }
151
152         material = b;
153         break;
154       }
155
156     case 1:
157       bytes = 2;
158
159     case 2:
160       {
161         int i;
162
163         if (!bytes)
164           bytes = 4;
165
166         material = 0;
167
168         for (i = 0; i < bytes; i++) {
169           if (fread (&b, 1, 1, fp) < 1) {
170             perror ("fread");
171             goto bail;
172           }
173
174           material = (material << 8) + b;
175         }
176         break;
177       }
178
179     default:
180       goto bail;
181     }
182
183     if (read_material (material, &used, fp) == -1)
184       goto bail;
185   }
186
187   if (len)
188     *len = used;
189
190   return pbuf;
191
192 bail:
193
194   fseek (fp, startpos, SEEK_SET);
195   return NULL;
196 }
197
198 void pgp_release_packet (void)
199 {
200   plen = 0;
201   FREE (&pbuf);
202 }