~ubuntu-branches/ubuntu/feisty/gnupg2/feisty

« back to all changes in this revision

Viewing changes to tools/gpgsplit.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2006-11-24 18:48:23 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20061124184823-17ir9m46tl09n9k4
Tags: 2.0.0-4ubuntu1
* Synchronize to Debian, reapply remaining Ubuntu changes to pristine Debian
  version:
  - Remove libpcsclite-dev, libopensc2-dev build dependencies (they are in
    universe).

Show diffs side-by-side

added added

removed removed

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