Line data Source code
1 : /* gpgsplit.c - An OpenPGP packet splitting tool
2 : * Copyright (C) 2001, 2002, 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 <errno.h>
22 : #include <stdio.h>
23 : #include <stdlib.h>
24 : #include <string.h>
25 : #include <ctype.h>
26 : #include <unistd.h>
27 : #include <assert.h>
28 : #include <sys/types.h>
29 : #ifdef HAVE_DOSISH_SYSTEM
30 : # include <fcntl.h> /* for setmode() */
31 : #endif
32 : #ifdef HAVE_ZIP
33 : # include <zlib.h>
34 : #endif
35 : #ifdef HAVE_BZIP2
36 : # include <bzlib.h>
37 : #endif /* HAVE_BZIP2 */
38 : #if defined(__riscos__) && defined(USE_ZLIBRISCOS)
39 : # include "zlib-riscos.h"
40 : #endif
41 :
42 : #define INCLUDED_BY_MAIN_MODULE 1
43 : #include "util.h"
44 : #include "openpgpdefs.h"
45 :
46 : static int opt_verbose;
47 : static const char *opt_prefix = "";
48 : static int opt_uncompress;
49 : static int opt_secret_to_public;
50 : static int opt_no_split;
51 :
52 : static void g10_exit( int rc );
53 : static void split_packets (const char *fname);
54 :
55 :
56 : enum cmd_and_opt_values {
57 : aNull = 0,
58 : oVerbose = 'v',
59 : oPrefix = 'p',
60 : oUncompress = 500,
61 : oSecretToPublic,
62 : oNoSplit,
63 :
64 : aTest
65 : };
66 :
67 :
68 : static ARGPARSE_OPTS opts[] = {
69 :
70 : { 301, NULL, 0, "@Options:\n " },
71 :
72 : { oVerbose, "verbose", 0, "verbose" },
73 : { oPrefix, "prefix", 2, "|STRING|Prepend filenames with STRING" },
74 : { oUncompress, "uncompress", 0, "uncompress a packet"},
75 : { oSecretToPublic, "secret-to-public", 0, "convert secret keys to public keys"},
76 : { oNoSplit, "no-split", 0, "write to stdout and don't actually split"},
77 : {0} };
78 :
79 :
80 : static const char *
81 0 : my_strusage (int level)
82 : {
83 : const char *p;
84 0 : switch (level)
85 : {
86 0 : case 11: p = "gpgsplit (@GNUPG@)";
87 0 : break;
88 0 : case 13: p = VERSION; break;
89 0 : case 17: p = PRINTABLE_OS_NAME; break;
90 0 : case 19: p = "Please report bugs to <@EMAIL@>.\n"; break;
91 :
92 : case 1:
93 0 : case 40: p =
94 : "Usage: gpgsplit [options] [files] (-h for help)";
95 0 : break;
96 0 : case 41: p =
97 : "Syntax: gpgsplit [options] [files]\n"
98 : "Split an OpenPGP message into packets\n";
99 0 : break;
100 :
101 0 : default: p = NULL;
102 : }
103 0 : return p;
104 : }
105 :
106 :
107 :
108 : int
109 0 : main (int argc, char **argv)
110 : {
111 : ARGPARSE_ARGS pargs;
112 :
113 : #ifdef HAVE_DOSISH_SYSTEM
114 : setmode( fileno(stdin), O_BINARY );
115 : setmode( fileno(stdout), O_BINARY );
116 : #endif
117 0 : log_set_prefix ("gpgsplit", GPGRT_LOG_WITH_PREFIX);
118 0 : set_strusage (my_strusage);
119 :
120 0 : pargs.argc = &argc;
121 0 : pargs.argv = &argv;
122 0 : pargs.flags= 1; /* do not remove the args */
123 0 : while (optfile_parse( NULL, NULL, NULL, &pargs, opts))
124 : {
125 0 : switch (pargs.r_opt)
126 : {
127 0 : case oVerbose: opt_verbose = 1; break;
128 0 : case oPrefix: opt_prefix = pargs.r.ret_str; break;
129 0 : case oUncompress: opt_uncompress = 1; break;
130 0 : case oSecretToPublic: opt_secret_to_public = 1; break;
131 0 : case oNoSplit: opt_no_split = 1; break;
132 0 : default : pargs.err = 2; break;
133 : }
134 : }
135 :
136 0 : if (log_get_errorcount(0))
137 0 : g10_exit (2);
138 :
139 0 : if (!argc)
140 0 : split_packets (NULL);
141 : else
142 : {
143 0 : for ( ;argc; argc--, argv++)
144 0 : split_packets (*argv);
145 : }
146 :
147 0 : g10_exit (0);
148 0 : return 0;
149 : }
150 :
151 :
152 : static void
153 0 : g10_exit (int rc)
154 : {
155 0 : rc = rc? rc : log_get_errorcount(0)? 2 : 0;
156 0 : exit(rc );
157 : }
158 :
159 : static const char *
160 0 : pkttype_to_string (int pkttype)
161 : {
162 : const char *s;
163 :
164 0 : switch (pkttype)
165 : {
166 0 : case PKT_PUBKEY_ENC : s = "pk_enc"; break;
167 0 : case PKT_SIGNATURE : s = "sig"; break;
168 0 : case PKT_SYMKEY_ENC : s = "sym_enc"; break;
169 0 : case PKT_ONEPASS_SIG : s = "onepass_sig"; break;
170 0 : case PKT_SECRET_KEY : s = "secret_key"; break;
171 0 : case PKT_PUBLIC_KEY : s = "public_key"; break;
172 0 : case PKT_SECRET_SUBKEY : s = "secret_subkey"; break;
173 : case PKT_COMPRESSED :
174 0 : s = opt_uncompress? "uncompressed":"compressed";
175 0 : break;
176 0 : case PKT_ENCRYPTED : s = "encrypted"; break;
177 0 : case PKT_MARKER : s = "marker"; break;
178 0 : case PKT_PLAINTEXT : s = "plaintext"; break;
179 0 : case PKT_RING_TRUST : s = "ring_trust"; break;
180 0 : case PKT_USER_ID : s = "user_id"; break;
181 0 : case PKT_PUBLIC_SUBKEY : s = "public_subkey"; break;
182 0 : case PKT_OLD_COMMENT : s = "old_comment"; break;
183 0 : case PKT_ATTRIBUTE : s = "attribute"; break;
184 0 : case PKT_ENCRYPTED_MDC : s = "encrypted_mdc"; break;
185 0 : case PKT_MDC : s = "mdc"; break;
186 0 : case PKT_COMMENT : s = "comment"; break;
187 0 : case PKT_GPG_CONTROL : s = "gpg_control"; break;
188 0 : default: s = "unknown"; break;
189 : }
190 0 : return s;
191 : }
192 :
193 :
194 : /*
195 : * Create a new filename and a return a pointer to a statically
196 : * allocated buffer
197 : */
198 : static char *
199 0 : create_filename (int pkttype)
200 : {
201 : static unsigned int partno = 0;
202 : static char *name;
203 :
204 0 : if (!name)
205 0 : name = xmalloc (strlen (opt_prefix) + 100 );
206 :
207 0 : assert (pkttype < 1000 && pkttype >= 0 );
208 0 : partno++;
209 0 : sprintf (name, "%s%06u-%03d" EXTSEP_S "%.40s",
210 : opt_prefix, partno, pkttype, pkttype_to_string (pkttype));
211 0 : return name;
212 : }
213 :
214 : static int
215 0 : read_u16 (FILE *fp, size_t *rn)
216 : {
217 : int c;
218 :
219 0 : if ( (c = getc (fp)) == EOF )
220 0 : return -1;
221 0 : *rn = c << 8;
222 0 : if ( (c = getc (fp)) == EOF )
223 0 : return -1;
224 0 : *rn |= c;
225 0 : return 0;
226 : }
227 :
228 : static int
229 0 : read_u32 (FILE *fp, unsigned long *rn)
230 : {
231 : size_t tmp;
232 :
233 0 : if (read_u16 (fp, &tmp))
234 0 : return -1;
235 0 : *rn = tmp << 16;
236 0 : if (read_u16 (fp, &tmp))
237 0 : return -1;
238 0 : *rn |= tmp;
239 0 : return 0;
240 : }
241 :
242 : static int
243 0 : write_old_header (FILE *fp, int pkttype, unsigned int len)
244 : {
245 0 : int ctb = (0x80 | ((pkttype & 15)<<2));
246 :
247 0 : if (len < 256)
248 : ;
249 0 : else if (len < 65536)
250 0 : ctb |= 1;
251 : else
252 0 : ctb |= 2;
253 :
254 0 : if ( putc ( ctb, fp) == EOF )
255 0 : return -1;
256 :
257 0 : if ( (ctb & 2) )
258 : {
259 0 : if (putc ((len>>24), fp) == EOF)
260 0 : return -1;
261 0 : if (putc ((len>>16), fp) == EOF)
262 0 : return -1;
263 : }
264 0 : if ( (ctb & 3) )
265 : {
266 0 : if (putc ((len>>8), fp) == EOF)
267 0 : return -1;
268 : }
269 0 : if (putc ((len&0xff), fp) == EOF)
270 0 : return -1;
271 0 : return 0;
272 : }
273 :
274 : static int
275 0 : write_new_header (FILE *fp, int pkttype, unsigned int len)
276 : {
277 0 : if ( putc ((0xc0 | (pkttype & 0x3f)), fp) == EOF )
278 0 : return -1;
279 :
280 0 : if (len < 192)
281 : {
282 0 : if (putc (len, fp) == EOF)
283 0 : return -1;
284 : }
285 0 : else if (len < 8384)
286 : {
287 0 : len -= 192;
288 0 : if (putc ((len/256)+192, fp) == EOF)
289 0 : return -1;
290 0 : if (putc ((len%256), fp) == EOF)
291 0 : return -1;
292 : }
293 : else
294 : {
295 0 : if (putc ( 0xff, fp) == EOF)
296 0 : return -1;
297 0 : if (putc ( (len >> 24), fp) == EOF)
298 0 : return -1;
299 0 : if (putc ( (len >> 16), fp) == EOF)
300 0 : return -1;
301 0 : if (putc ( (len >> 8), fp) == EOF)
302 0 : return -1;
303 0 : if (putc ( (len & 0xff), fp) == EOF)
304 0 : return -1;
305 : }
306 0 : return 0;
307 : }
308 :
309 : /* Return the length of the public key given BUF of BUFLEN with a
310 : secret key. */
311 : static int
312 0 : public_key_length (const unsigned char *buf, size_t buflen)
313 : {
314 : const unsigned char *s;
315 : int nmpis;
316 :
317 : /* byte version number (3 or 4)
318 : u32 creation time
319 : [u16 valid days (version 3 only)]
320 : byte algorithm
321 : n MPIs (n and e) */
322 0 : if (!buflen)
323 0 : return 0;
324 0 : if (buf[0] < 2 || buf[0] > 4)
325 0 : return 0; /* wrong version number */
326 0 : if (buflen < (buf[0] == 4? 6:8))
327 0 : return 0;
328 0 : s = buf + (buf[0] == 4? 6:8);
329 0 : buflen -= (buf[0] == 4? 6:8);
330 0 : switch (s[-1])
331 : {
332 : case 1:
333 : case 2:
334 : case 3:
335 0 : nmpis = 2;
336 0 : break;
337 : case 16:
338 : case 20:
339 0 : nmpis = 3;
340 0 : break;
341 : case 17:
342 0 : nmpis = 4;
343 0 : break;
344 : default:
345 0 : return 0;
346 : }
347 :
348 0 : for (; nmpis; nmpis--)
349 : {
350 : unsigned int nbits, nbytes;
351 :
352 0 : if (buflen < 2)
353 0 : return 0;
354 0 : nbits = (s[0] << 8) | s[1];
355 0 : s += 2; buflen -= 2;
356 0 : nbytes = (nbits+7) / 8;
357 0 : if (buflen < nbytes)
358 0 : return 0;
359 0 : s += nbytes; buflen -= nbytes;
360 : }
361 :
362 0 : return s - buf;
363 : }
364 :
365 : #ifdef HAVE_ZIP
366 : static int
367 0 : handle_zlib(int algo,FILE *fpin,FILE *fpout)
368 : {
369 : z_stream zs;
370 : byte *inbuf, *outbuf;
371 : unsigned int inbufsize, outbufsize;
372 : int c,zinit_done, zrc, nread, count;
373 : size_t n;
374 :
375 0 : memset (&zs, 0, sizeof zs);
376 0 : inbufsize = 2048;
377 0 : inbuf = xmalloc (inbufsize);
378 0 : outbufsize = 8192;
379 0 : outbuf = xmalloc (outbufsize);
380 0 : zs.avail_in = 0;
381 0 : zinit_done = 0;
382 :
383 : do
384 : {
385 0 : if (zs.avail_in < inbufsize)
386 : {
387 0 : n = zs.avail_in;
388 0 : if (!n)
389 0 : zs.next_in = (Bytef *) inbuf;
390 0 : count = inbufsize - n;
391 0 : for (nread=0;
392 0 : nread < count && (c=getc (fpin)) != EOF;
393 0 : nread++)
394 0 : inbuf[n+nread] = c;
395 :
396 0 : n += nread;
397 0 : if (nread < count && algo == 1)
398 : {
399 0 : inbuf[n] = 0xFF; /* chew dummy byte */
400 0 : n++;
401 : }
402 0 : zs.avail_in = n;
403 : }
404 0 : zs.next_out = (Bytef *) outbuf;
405 0 : zs.avail_out = outbufsize;
406 :
407 0 : if (!zinit_done)
408 : {
409 0 : zrc = (algo == 1? inflateInit2 ( &zs, -13)
410 0 : : inflateInit ( &zs ));
411 0 : if (zrc != Z_OK)
412 : {
413 0 : log_fatal ("zlib problem: %s\n", zs.msg? zs.msg :
414 0 : zrc == Z_MEM_ERROR ? "out of core" :
415 : zrc == Z_VERSION_ERROR ?
416 0 : "invalid lib version" :
417 : "unknown error" );
418 : }
419 0 : zinit_done = 1;
420 : }
421 : else
422 : {
423 : #ifdef Z_SYNC_FLUSH
424 0 : zrc = inflate (&zs, Z_SYNC_FLUSH);
425 : #else
426 : zrc = inflate (&zs, Z_PARTIAL_FLUSH);
427 : #endif
428 0 : if (zrc == Z_STREAM_END)
429 : ; /* eof */
430 0 : else if (zrc != Z_OK && zrc != Z_BUF_ERROR)
431 : {
432 0 : if (zs.msg)
433 0 : log_fatal ("zlib inflate problem: %s\n", zs.msg );
434 : else
435 0 : log_fatal ("zlib inflate problem: rc=%d\n", zrc );
436 : }
437 0 : for (n=0; n < outbufsize - zs.avail_out; n++)
438 : {
439 0 : if (putc (outbuf[n], fpout) == EOF )
440 0 : return 1;
441 : }
442 : }
443 : }
444 0 : while (zrc != Z_STREAM_END && zrc != Z_BUF_ERROR);
445 : {
446 : int i;
447 :
448 0 : fputs ("Left over bytes:", stderr);
449 0 : for (i=0; i < zs.avail_in; i++)
450 0 : fprintf (stderr, " %02X", zs.next_in[i]);
451 0 : putc ('\n', stderr);
452 :
453 : }
454 0 : inflateEnd (&zs);
455 :
456 0 : return 0;
457 : }
458 : #endif /*HAVE_ZIP*/
459 :
460 : #ifdef HAVE_BZIP2
461 : static int
462 0 : handle_bzip2(int algo,FILE *fpin,FILE *fpout)
463 : {
464 : bz_stream bzs;
465 : byte *inbuf, *outbuf;
466 : unsigned int inbufsize, outbufsize;
467 : int c,zinit_done, zrc, nread, count;
468 : size_t n;
469 :
470 0 : memset (&bzs, 0, sizeof bzs);
471 0 : inbufsize = 2048;
472 0 : inbuf = xmalloc (inbufsize);
473 0 : outbufsize = 8192;
474 0 : outbuf = xmalloc (outbufsize);
475 0 : bzs.avail_in = 0;
476 0 : zinit_done = 0;
477 :
478 : do
479 : {
480 0 : if (bzs.avail_in < inbufsize)
481 : {
482 0 : n = bzs.avail_in;
483 0 : if (!n)
484 0 : bzs.next_in = inbuf;
485 0 : count = inbufsize - n;
486 0 : for (nread=0;
487 0 : nread < count && (c=getc (fpin)) != EOF;
488 0 : nread++)
489 0 : inbuf[n+nread] = c;
490 :
491 0 : n += nread;
492 0 : if (nread < count && algo == 1)
493 : {
494 0 : inbuf[n] = 0xFF; /* chew dummy byte */
495 0 : n++;
496 : }
497 0 : bzs.avail_in = n;
498 : }
499 0 : bzs.next_out = outbuf;
500 0 : bzs.avail_out = outbufsize;
501 :
502 0 : if (!zinit_done)
503 : {
504 0 : zrc = BZ2_bzDecompressInit(&bzs,0,0);
505 0 : if (zrc != BZ_OK)
506 0 : log_fatal ("bz2lib problem: %d\n",zrc);
507 0 : zinit_done = 1;
508 : }
509 : else
510 : {
511 0 : zrc = BZ2_bzDecompress(&bzs);
512 0 : if (zrc == BZ_STREAM_END)
513 : ; /* eof */
514 0 : else if (zrc != BZ_OK && zrc != BZ_PARAM_ERROR)
515 0 : log_fatal ("bz2lib inflate problem: %d\n", zrc );
516 0 : for (n=0; n < outbufsize - bzs.avail_out; n++)
517 : {
518 0 : if (putc (outbuf[n], fpout) == EOF )
519 0 : return 1;
520 : }
521 : }
522 : }
523 0 : while (zrc != BZ_STREAM_END && zrc != BZ_PARAM_ERROR);
524 0 : BZ2_bzDecompressEnd(&bzs);
525 :
526 0 : return 0;
527 : }
528 : #endif /* HAVE_BZIP2 */
529 :
530 : /* hdr must point to a buffer large enough to hold all header bytes */
531 : static int
532 0 : write_part (FILE *fpin, unsigned long pktlen,
533 : int pkttype, int partial, unsigned char *hdr, size_t hdrlen)
534 : {
535 : FILE *fpout;
536 : int c, first;
537 : unsigned char *p;
538 0 : const char *outname = create_filename (pkttype);
539 :
540 : #if defined(__riscos__) && defined(USE_ZLIBRISCOS)
541 : static int initialized = 0;
542 :
543 : if (!initialized)
544 : initialized = riscos_load_module("ZLib", zlib_path, 1);
545 : #endif
546 0 : if (opt_no_split)
547 0 : fpout = stdout;
548 : else
549 : {
550 0 : if (opt_verbose)
551 0 : log_info ("writing '%s'\n", outname);
552 0 : fpout = fopen (outname, "wb");
553 0 : if (!fpout)
554 : {
555 0 : log_error ("error creating '%s': %s\n", outname, strerror(errno));
556 : /* stop right now, otherwise we would mess up the sequence
557 : of the part numbers */
558 0 : g10_exit (1);
559 : }
560 : }
561 :
562 0 : if (opt_secret_to_public
563 0 : && (pkttype == PKT_SECRET_KEY || pkttype == PKT_SECRET_SUBKEY))
564 : {
565 0 : unsigned char *blob = xmalloc (pktlen);
566 : int i, len;
567 :
568 0 : pkttype = pkttype == PKT_SECRET_KEY? PKT_PUBLIC_KEY:PKT_PUBLIC_SUBKEY;
569 :
570 0 : for (i=0; i < pktlen; i++)
571 : {
572 0 : c = getc (fpin);
573 0 : if (c == EOF)
574 0 : goto read_error;
575 0 : blob[i] = c;
576 : }
577 0 : len = public_key_length (blob, pktlen);
578 0 : if (!len)
579 : {
580 0 : log_error ("error calculating public key length\n");
581 0 : g10_exit (1);
582 : }
583 0 : if ( (hdr[0] & 0x40) )
584 : {
585 0 : if (write_new_header (fpout, pkttype, len))
586 0 : goto write_error;
587 : }
588 : else
589 : {
590 0 : if (write_old_header (fpout, pkttype, len))
591 0 : goto write_error;
592 : }
593 :
594 0 : for (i=0; i < len; i++)
595 : {
596 0 : if ( putc (blob[i], fpout) == EOF )
597 0 : goto write_error;
598 : }
599 :
600 0 : goto ready;
601 : }
602 :
603 :
604 0 : if (!opt_uncompress)
605 : {
606 0 : for (p=hdr; hdrlen; p++, hdrlen--)
607 : {
608 0 : if ( putc (*p, fpout) == EOF )
609 0 : goto write_error;
610 : }
611 : }
612 :
613 0 : first = 1;
614 0 : while (partial)
615 : {
616 : size_t partlen;
617 :
618 0 : if (partial == 1)
619 : { /* openpgp */
620 0 : if (first )
621 : {
622 0 : c = pktlen;
623 0 : assert( c >= 224 && c < 255 );
624 0 : first = 0;
625 : }
626 0 : else if ((c = getc (fpin)) == EOF )
627 0 : goto read_error;
628 : else
629 0 : hdr[hdrlen++] = c;
630 :
631 0 : if (c < 192)
632 : {
633 0 : pktlen = c;
634 0 : partial = 0; /* (last segment may follow) */
635 : }
636 0 : else if (c < 224 )
637 : {
638 0 : pktlen = (c - 192) * 256;
639 0 : if ((c = getc (fpin)) == EOF)
640 0 : goto read_error;
641 0 : hdr[hdrlen++] = c;
642 0 : pktlen += c + 192;
643 0 : partial = 0;
644 : }
645 0 : else if (c == 255)
646 : {
647 0 : if (read_u32 (fpin, &pktlen))
648 0 : goto read_error;
649 0 : hdr[hdrlen++] = pktlen >> 24;
650 0 : hdr[hdrlen++] = pktlen >> 16;
651 0 : hdr[hdrlen++] = pktlen >> 8;
652 0 : hdr[hdrlen++] = pktlen;
653 0 : partial = 0;
654 : }
655 : else
656 : { /* next partial body length */
657 0 : for (p=hdr; hdrlen; p++, hdrlen--)
658 : {
659 0 : if ( putc (*p, fpout) == EOF )
660 0 : goto write_error;
661 : }
662 0 : partlen = 1 << (c & 0x1f);
663 0 : for (; partlen; partlen--)
664 : {
665 0 : if ((c = getc (fpin)) == EOF)
666 0 : goto read_error;
667 0 : if ( putc (c, fpout) == EOF )
668 0 : goto write_error;
669 : }
670 : }
671 : }
672 0 : else if (partial == 2)
673 : { /* old gnupg */
674 0 : assert (!pktlen);
675 0 : if ( read_u16 (fpin, &partlen) )
676 0 : goto read_error;
677 0 : hdr[hdrlen++] = partlen >> 8;
678 0 : hdr[hdrlen++] = partlen;
679 0 : for (p=hdr; hdrlen; p++, hdrlen--)
680 : {
681 0 : if ( putc (*p, fpout) == EOF )
682 0 : goto write_error;
683 : }
684 0 : if (!partlen)
685 0 : partial = 0; /* end of packet */
686 0 : for (; partlen; partlen--)
687 : {
688 0 : c = getc (fpin);
689 0 : if (c == EOF)
690 0 : goto read_error;
691 0 : if ( putc (c, fpout) == EOF )
692 0 : goto write_error;
693 : }
694 : }
695 : else
696 : { /* compressed: read to end */
697 0 : pktlen = 0;
698 0 : partial = 0;
699 0 : hdrlen = 0;
700 0 : if (opt_uncompress)
701 : {
702 0 : if ((c = getc (fpin)) == EOF)
703 0 : goto read_error;
704 :
705 : if (0)
706 : ;
707 : #ifdef HAVE_ZIP
708 0 : else if(c==1 || c==2)
709 : {
710 0 : if(handle_zlib(c,fpin,fpout))
711 0 : goto write_error;
712 : }
713 : #endif /* HAVE_ZIP */
714 : #ifdef HAVE_BZIP2
715 0 : else if(c==3)
716 : {
717 0 : if(handle_bzip2(c,fpin,fpout))
718 0 : goto write_error;
719 : }
720 : #endif /* HAVE_BZIP2 */
721 : else
722 : {
723 0 : log_error("invalid compression algorithm (%d)\n",c);
724 0 : goto read_error;
725 : }
726 : }
727 : else
728 : {
729 0 : while ( (c=getc (fpin)) != EOF )
730 : {
731 0 : if ( putc (c, fpout) == EOF )
732 0 : goto write_error;
733 : }
734 : }
735 0 : if (!feof (fpin))
736 0 : goto read_error;
737 : }
738 : }
739 :
740 0 : for (p=hdr; hdrlen; p++, hdrlen--)
741 : {
742 0 : if ( putc (*p, fpout) == EOF )
743 0 : goto write_error;
744 : }
745 :
746 : /* standard packet or last segment of partial length encoded packet */
747 0 : for (; pktlen; pktlen--)
748 : {
749 0 : c = getc (fpin);
750 0 : if (c == EOF)
751 0 : goto read_error;
752 0 : if ( putc (c, fpout) == EOF )
753 0 : goto write_error;
754 : }
755 :
756 : ready:
757 0 : if ( !opt_no_split && fclose (fpout) )
758 0 : log_error ("error closing '%s': %s\n", outname, strerror (errno));
759 0 : return 0;
760 :
761 : write_error:
762 0 : log_error ("error writing '%s': %s\n", outname, strerror (errno));
763 0 : if (!opt_no_split)
764 0 : fclose (fpout);
765 0 : return 2;
766 :
767 : read_error:
768 0 : if (!opt_no_split)
769 : {
770 0 : int save = errno;
771 0 : fclose (fpout);
772 0 : errno = save;
773 : }
774 0 : return -1;
775 : }
776 :
777 :
778 :
779 : static int
780 0 : do_split (FILE *fp)
781 : {
782 : int c, ctb, pkttype;
783 0 : unsigned long pktlen = 0;
784 0 : int partial = 0;
785 : unsigned char header[20];
786 0 : int header_idx = 0;
787 :
788 0 : ctb = getc (fp);
789 0 : if (ctb == EOF)
790 0 : return 3; /* ready */
791 0 : header[header_idx++] = ctb;
792 :
793 0 : if (!(ctb & 0x80))
794 : {
795 0 : log_error("invalid CTB %02x\n", ctb );
796 0 : return 1;
797 : }
798 0 : if ( (ctb & 0x40) )
799 : { /* new CTB */
800 0 : pkttype = (ctb & 0x3f);
801 0 : if( (c = getc (fp)) == EOF )
802 0 : return -1;
803 0 : header[header_idx++] = c;
804 :
805 0 : if ( c < 192 )
806 0 : pktlen = c;
807 0 : else if ( c < 224 )
808 : {
809 0 : pktlen = (c - 192) * 256;
810 0 : if( (c = getc (fp)) == EOF )
811 0 : return -1;
812 0 : header[header_idx++] = c;
813 0 : pktlen += c + 192;
814 : }
815 0 : else if ( c == 255 )
816 : {
817 0 : if (read_u32 (fp, &pktlen))
818 0 : return -1;
819 0 : header[header_idx++] = pktlen >> 24;
820 0 : header[header_idx++] = pktlen >> 16;
821 0 : header[header_idx++] = pktlen >> 8;
822 0 : header[header_idx++] = pktlen;
823 : }
824 : else
825 : { /* partial body length */
826 0 : pktlen = c;
827 0 : partial = 1;
828 : }
829 : }
830 : else
831 : {
832 : int lenbytes;
833 :
834 0 : pkttype = (ctb>>2)&0xf;
835 0 : lenbytes = ((ctb&3)==3)? 0 : (1<<(ctb & 3));
836 0 : if (!lenbytes )
837 : {
838 0 : pktlen = 0; /* don't know the value */
839 0 : if( pkttype == PKT_COMPRESSED )
840 0 : partial = 3;
841 : else
842 0 : partial = 2; /* the old GnuPG partial length encoding */
843 : }
844 : else
845 : {
846 0 : for ( ; lenbytes; lenbytes-- )
847 : {
848 0 : pktlen <<= 8;
849 0 : if( (c = getc (fp)) == EOF )
850 0 : return -1;
851 0 : header[header_idx++] = c;
852 :
853 0 : pktlen |= c;
854 : }
855 : }
856 : }
857 :
858 0 : return write_part (fp, pktlen, pkttype, partial, header, header_idx);
859 : }
860 :
861 :
862 : static void
863 0 : split_packets (const char *fname)
864 : {
865 : FILE *fp;
866 : int rc;
867 :
868 0 : if (!fname || !strcmp (fname, "-"))
869 : {
870 0 : fp = stdin;
871 0 : fname = "-";
872 : }
873 0 : else if ( !(fp = fopen (fname,"rb")) )
874 : {
875 0 : log_error ("can't open '%s': %s\n", fname, strerror (errno));
876 0 : return;
877 : }
878 :
879 0 : while ( !(rc = do_split (fp)) )
880 : ;
881 0 : if ( rc > 0 )
882 : ; /* error already handled */
883 0 : else if ( ferror (fp) )
884 0 : log_error ("error reading '%s': %s\n", fname, strerror (errno));
885 : else
886 0 : log_error ("premature EOF while reading '%s'\n", fname );
887 :
888 0 : if ( fp != stdin )
889 0 : fclose (fp);
890 : }
|