NeoMutt  2018-07-16 +2481-68dcde
Teaching an old dog new tricks
DOXYGEN
pgppacket.c
Go to the documentation of this file.
1 
29 #include "config.h"
30 #include <stdbool.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include "mutt/mutt.h"
34 
35 #define CHUNK_SIZE 1024
37 static unsigned char *pbuf = NULL;
38 static size_t plen = 0;
50 static int read_material(size_t material, size_t *used, FILE *fp)
51 {
52  if (*used + material >= plen)
53  {
54  size_t nplen = *used + material + CHUNK_SIZE;
55 
56  unsigned char *p = realloc(pbuf, nplen);
57  if (!p)
58  {
59  perror("realloc");
60  return -1;
61  }
62  plen = nplen;
63  pbuf = p;
64  }
65 
66  if (fread(pbuf + *used, 1, material, fp) < material)
67  {
68  perror("fread");
69  return -1;
70  }
71 
72  *used += material;
73  return 0;
74 }
75 
83 unsigned char *pgp_read_packet(FILE *fp, size_t *len)
84 {
85  size_t used = 0;
86  LOFF_T startpos;
87  unsigned char ctb;
88  unsigned char b;
89  size_t material;
90 
91  startpos = ftello(fp);
92  if (startpos < 0)
93  return NULL;
94 
95  if (plen == 0)
96  {
97  plen = CHUNK_SIZE;
99  }
100 
101  if (fread(&ctb, 1, 1, fp) < 1)
102  {
103  if (!feof(fp))
104  perror("fread");
105  goto bail;
106  }
107 
108  if (!(ctb & 0x80))
109  {
110  goto bail;
111  }
112 
113  if (ctb & 0x40) /* handle PGP 5.0 packets. */
114  {
115  bool partial = false;
116  pbuf[0] = ctb;
117  used++;
118 
119  do
120  {
121  if (fread(&b, 1, 1, fp) < 1)
122  {
123  perror("fread");
124  goto bail;
125  }
126 
127  if (b < 192)
128  {
129  material = b;
130  partial = false;
131  }
132  else if (b <= 223)
133  {
134  material = (b - 192) * 256;
135  if (fread(&b, 1, 1, fp) < 1)
136  {
137  perror("fread");
138  goto bail;
139  }
140  material += b + 192;
141  partial = false;
142  }
143  else if (b < 255)
144  {
145  material = 1 << (b & 0x1f);
146  partial = true;
147  }
148  else
149  /* b == 255 */
150  {
151  unsigned char buf[4];
152  if (fread(buf, 4, 1, fp) < 1)
153  {
154  perror("fread");
155  goto bail;
156  }
157  material = (size_t) buf[0] << 24;
158  material |= buf[1] << 16;
159  material |= buf[2] << 8;
160  material |= buf[3];
161  partial = false;
162  }
163 
164  if (read_material(material, &used, fp) == -1)
165  goto bail;
166 
167  } while (partial);
168  }
169  else
170  /* Old-Style PGP */
171  {
172  int bytes = 0;
173  pbuf[0] = 0x80 | ((ctb >> 2) & 0x0f);
174  used++;
175 
176  switch (ctb & 0x03)
177  {
178  case 0:
179  {
180  if (fread(&b, 1, 1, fp) < 1)
181  {
182  perror("fread");
183  goto bail;
184  }
185 
186  material = b;
187  break;
188  }
189 
190  case 1:
191  bytes = 2;
192  /* fallthrough */
193 
194  case 2:
195  {
196  if (!bytes)
197  bytes = 4;
198 
199  material = 0;
200 
201  for (int i = 0; i < bytes; i++)
202  {
203  if (fread(&b, 1, 1, fp) < 1)
204  {
205  perror("fread");
206  goto bail;
207  }
208 
209  material = (material << 8) + b;
210  }
211  break;
212  }
213 
214  default:
215  goto bail;
216  }
217 
218  if (read_material(material, &used, fp) == -1)
219  goto bail;
220  }
221 
222  if (len)
223  *len = used;
224 
225  return pbuf;
226 
227 bail:
228 
229  fseeko(fp, startpos, SEEK_SET);
230  return NULL;
231 }
232 
239 {
240  plen = 0;
241  FREE(&pbuf);
242 }
static size_t plen
Length of cached packet.
Definition: pgppacket.c:38
void pgp_release_packet(void)
Free the cached PGP packet.
Definition: pgppacket.c:238
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
#define CHUNK_SIZE
Amount of data to read at once.
Definition: pgppacket.c:35
#define FREE(x)
Definition: memory.h:40
static int read_material(size_t material, size_t *used, FILE *fp)
Read PGP data into a buffer.
Definition: pgppacket.c:50
unsigned char * pgp_read_packet(FILE *fp, size_t *len)
Read a PGP packet from a file.
Definition: pgppacket.c:83
static unsigned char * pbuf
Cache PGP data packet.
Definition: pgppacket.c:37