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