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