1 /* gpgsplit.c - An OpenPGP packet splitting tool
2 * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
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.
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.
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/>.
28 #include <sys/types.h>
29 #ifdef HAVE_DOSISH_SYSTEM
30 # include <fcntl.h> /* for setmode() */
35 #endif /* HAVE_BZIP2 */
36 #if defined(__riscos__) && defined(USE_ZLIBRISCOS)
37 # include "zlib-riscos.h"
40 #define INCLUDED_BY_MAIN_MODULE 1
42 #include "openpgpdefs.h"
44 static int opt_verbose
;
45 static const char *opt_prefix
= "";
46 static int opt_uncompress
;
47 static int opt_secret_to_public
;
48 static int opt_no_split
;
50 static void g10_exit( int rc
);
51 static void split_packets (const char *fname
);
54 enum cmd_and_opt_values
{
66 static ARGPARSE_OPTS opts
[] = {
68 { 301, NULL
, 0, "@Options:\n " },
70 { oVerbose
, "verbose", 0, "verbose" },
71 { oPrefix
, "prefix", 2, "|STRING|Prepend filenames with STRING" },
72 { oUncompress
, "uncompress", 0, "uncompress a packet"},
73 { oSecretToPublic
, "secret-to-public", 0, "convert secret keys to public keys"},
74 { oNoSplit
, "no-split", 0, "write to stdout and don't actually split"},
79 my_strusage (int level
)
84 case 11: p
= "gpgsplit (GnuPG)";
86 case 13: p
= VERSION
; break;
87 case 17: p
= PRINTABLE_OS_NAME
; break;
88 case 19: p
= "Please report bugs to <@EMAIL@>.\n"; break;
92 "Usage: gpgsplit [options] [files] (-h for help)";
95 "Syntax: gpgsplit [options] [files]\n"
96 "Split an OpenPGP message into packets\n";
107 main (int argc
, char **argv
)
111 #ifdef HAVE_DOSISH_SYSTEM
112 setmode( fileno(stdin
), O_BINARY
);
113 setmode( fileno(stdout
), O_BINARY
);
115 log_set_prefix ("gpgsplit", JNLIB_LOG_WITH_PREFIX
);
116 set_strusage (my_strusage
);
120 pargs
.flags
= 1; /* do not remove the args */
121 while (optfile_parse( NULL
, NULL
, NULL
, &pargs
, opts
))
125 case oVerbose
: opt_verbose
= 1; break;
126 case oPrefix
: opt_prefix
= pargs
.r
.ret_str
; break;
127 case oUncompress
: opt_uncompress
= 1; break;
128 case oSecretToPublic
: opt_secret_to_public
= 1; break;
129 case oNoSplit
: opt_no_split
= 1; break;
130 default : pargs
.err
= 2; break;
134 if (log_get_errorcount(0))
138 split_packets (NULL
);
141 for ( ;argc
; argc
--, argv
++)
142 split_packets (*argv
);
153 rc
= rc
? rc
: log_get_errorcount(0)? 2 : 0;
158 pkttype_to_string (int pkttype
)
164 case PKT_PUBKEY_ENC
: s
= "pk_enc"; break;
165 case PKT_SIGNATURE
: s
= "sig"; break;
166 case PKT_SYMKEY_ENC
: s
= "sym_enc"; break;
167 case PKT_ONEPASS_SIG
: s
= "onepass_sig"; break;
168 case PKT_SECRET_KEY
: s
= "secret_key"; break;
169 case PKT_PUBLIC_KEY
: s
= "public_key"; break;
170 case PKT_SECRET_SUBKEY
: s
= "secret_subkey"; break;
171 case PKT_COMPRESSED
:
172 s
= opt_uncompress
? "uncompressed":"compressed";
174 case PKT_ENCRYPTED
: s
= "encrypted"; break;
175 case PKT_MARKER
: s
= "marker"; break;
176 case PKT_PLAINTEXT
: s
= "plaintext"; break;
177 case PKT_RING_TRUST
: s
= "ring_trust"; break;
178 case PKT_USER_ID
: s
= "user_id"; break;
179 case PKT_PUBLIC_SUBKEY
: s
= "public_subkey"; break;
180 case PKT_OLD_COMMENT
: s
= "old_comment"; break;
181 case PKT_ATTRIBUTE
: s
= "attribute"; break;
182 case PKT_ENCRYPTED_MDC
: s
= "encrypted_mdc"; break;
183 case PKT_MDC
: s
= "mdc"; break;
184 case PKT_COMMENT
: s
= "comment"; break;
185 case PKT_GPG_CONTROL
: s
= "gpg_control"; break;
186 default: s
= "unknown"; break;
193 * Create a new filename and a return a pointer to a statically
197 create_filename (int pkttype
)
199 static unsigned int partno
= 0;
203 name
= xmalloc (strlen (opt_prefix
) + 100 );
205 assert (pkttype
< 1000 && pkttype
>= 0 );
207 sprintf (name
, "%s%06u-%03d" EXTSEP_S
"%.40s",
208 opt_prefix
, partno
, pkttype
, pkttype_to_string (pkttype
));
213 read_u16 (FILE *fp
, size_t *rn
)
217 if ( (c
= getc (fp
)) == EOF
)
220 if ( (c
= getc (fp
)) == EOF
)
227 read_u32 (FILE *fp
, unsigned long *rn
)
231 if (read_u16 (fp
, &tmp
))
234 if (read_u16 (fp
, &tmp
))
241 write_old_header (FILE *fp
, int pkttype
, unsigned int len
)
243 int ctb
= (0x80 | ((pkttype
& 15)<<2));
247 else if (len
< 65536)
252 if ( putc ( ctb
, fp
) == EOF
)
257 if (putc ((len
>>24), fp
) == EOF
)
259 if (putc ((len
>>16), fp
) == EOF
)
264 if (putc ((len
>>8), fp
) == EOF
)
267 if (putc ((len
&0xff), fp
) == EOF
)
273 write_new_header (FILE *fp
, int pkttype
, unsigned int len
)
275 if ( putc ((0xc0 | (pkttype
& 0x3f)), fp
) == EOF
)
280 if (putc (len
, fp
) == EOF
)
286 if (putc ((len
/256)+192, fp
) == EOF
)
288 if (putc ((len
%256), fp
) == EOF
)
293 if (putc ( 0xff, fp
) == EOF
)
295 if (putc ( (len
>> 24), fp
) == EOF
)
297 if (putc ( (len
>> 16), fp
) == EOF
)
299 if (putc ( (len
>> 8), fp
) == EOF
)
301 if (putc ( (len
& 0xff), fp
) == EOF
)
307 /* Return the length of the public key given BUF of BUFLEN with a
310 public_key_length (const unsigned char *buf
, size_t buflen
)
312 const unsigned char *s
;
315 /* byte version number (3 or 4)
317 [u16 valid days (version 3 only)]
322 if (buf
[0] < 2 || buf
[0] > 4)
323 return 0; /* wrong version number */
324 if (buflen
< (buf
[0] == 4? 6:8))
326 s
= buf
+ (buf
[0] == 4? 6:8);
327 buflen
-= (buf
[0] == 4? 6:8);
346 for (; nmpis
; nmpis
--)
348 unsigned int nbits
, nbytes
;
352 nbits
= (s
[0] << 8) | s
[1];
354 nbytes
= (nbits
+7) / 8;
357 s
+= nbytes
; buflen
-= nbytes
;
364 handle_zlib(int algo
,FILE *fpin
,FILE *fpout
)
367 byte
*inbuf
, *outbuf
;
368 unsigned int inbufsize
, outbufsize
;
369 int c
,zinit_done
, zrc
, nread
, count
;
372 memset (&zs
, 0, sizeof zs
);
374 inbuf
= xmalloc (inbufsize
);
376 outbuf
= xmalloc (outbufsize
);
382 if (zs
.avail_in
< inbufsize
)
386 zs
.next_in
= (Bytef
*) inbuf
;
387 count
= inbufsize
- n
;
389 nread
< count
&& (c
=getc (fpin
)) != EOF
;
394 if (nread
< count
&& algo
== 1)
396 inbuf
[n
] = 0xFF; /* chew dummy byte */
401 zs
.next_out
= (Bytef
*) outbuf
;
402 zs
.avail_out
= outbufsize
;
406 zrc
= (algo
== 1? inflateInit2 ( &zs
, -13)
407 : inflateInit ( &zs
));
410 log_fatal ("zlib problem: %s\n", zs
.msg
? zs
.msg
:
411 zrc
== Z_MEM_ERROR
? "out of core" :
412 zrc
== Z_VERSION_ERROR
?
413 "invalid lib version" :
421 zrc
= inflate (&zs
, Z_SYNC_FLUSH
);
423 zrc
= inflate (&zs
, Z_PARTIAL_FLUSH
);
425 if (zrc
== Z_STREAM_END
)
427 else if (zrc
!= Z_OK
&& zrc
!= Z_BUF_ERROR
)
430 log_fatal ("zlib inflate problem: %s\n", zs
.msg
);
432 log_fatal ("zlib inflate problem: rc=%d\n", zrc
);
434 for (n
=0; n
< outbufsize
- zs
.avail_out
; n
++)
436 if (putc (outbuf
[n
], fpout
) == EOF
)
441 while (zrc
!= Z_STREAM_END
&& zrc
!= Z_BUF_ERROR
);
445 fputs ("Left over bytes:", stderr
);
446 for (i
=0; i
< zs
.avail_in
; i
++)
447 fprintf (stderr
, " %02X", zs
.next_in
[i
]);
458 handle_bzip2(int algo
,FILE *fpin
,FILE *fpout
)
461 byte
*inbuf
, *outbuf
;
462 unsigned int inbufsize
, outbufsize
;
463 int c
,zinit_done
, zrc
, nread
, count
;
466 memset (&bzs
, 0, sizeof bzs
);
468 inbuf
= xmalloc (inbufsize
);
470 outbuf
= xmalloc (outbufsize
);
476 if (bzs
.avail_in
< inbufsize
)
481 count
= inbufsize
- n
;
483 nread
< count
&& (c
=getc (fpin
)) != EOF
;
488 if (nread
< count
&& algo
== 1)
490 inbuf
[n
] = 0xFF; /* chew dummy byte */
495 bzs
.next_out
= outbuf
;
496 bzs
.avail_out
= outbufsize
;
500 zrc
= BZ2_bzDecompressInit(&bzs
,0,0);
502 log_fatal ("bz2lib problem: %d\n",zrc
);
507 zrc
= BZ2_bzDecompress(&bzs
);
508 if (zrc
== BZ_STREAM_END
)
510 else if (zrc
!= BZ_OK
&& zrc
!= BZ_PARAM_ERROR
)
511 log_fatal ("bz2lib inflate problem: %d\n", zrc
);
512 for (n
=0; n
< outbufsize
- bzs
.avail_out
; n
++)
514 if (putc (outbuf
[n
], fpout
) == EOF
)
519 while (zrc
!= BZ_STREAM_END
&& zrc
!= BZ_PARAM_ERROR
);
520 BZ2_bzDecompressEnd(&bzs
);
524 #endif /* HAVE_BZIP2 */
526 /* hdr must point to a buffer large enough to hold all header bytes */
528 write_part (FILE *fpin
, unsigned long pktlen
,
529 int pkttype
, int partial
, unsigned char *hdr
, size_t hdrlen
)
534 const char *outname
= create_filename (pkttype
);
536 #if defined(__riscos__) && defined(USE_ZLIBRISCOS)
537 static int initialized
= 0;
540 initialized
= riscos_load_module("ZLib", zlib_path
, 1);
547 log_info ("writing `%s'\n", outname
);
548 fpout
= fopen (outname
, "wb");
551 log_error ("error creating `%s': %s\n", outname
, strerror(errno
));
552 /* stop right now, otherwise we would mess up the sequence
553 of the part numbers */
558 if (opt_secret_to_public
559 && (pkttype
== PKT_SECRET_KEY
|| pkttype
== PKT_SECRET_SUBKEY
))
561 unsigned char *blob
= xmalloc (pktlen
);
564 pkttype
= pkttype
== PKT_SECRET_KEY
? PKT_PUBLIC_KEY
:PKT_PUBLIC_SUBKEY
;
566 for (i
=0; i
< pktlen
; i
++)
573 len
= public_key_length (blob
, pktlen
);
576 log_error ("error calcualting public key length\n");
579 if ( (hdr
[0] & 0x40) )
581 if (write_new_header (fpout
, pkttype
, len
))
586 if (write_old_header (fpout
, pkttype
, len
))
590 for (i
=0; i
< len
; i
++)
592 if ( putc (blob
[i
], fpout
) == EOF
)
602 for (p
=hdr
; hdrlen
; p
++, hdrlen
--)
604 if ( putc (*p
, fpout
) == EOF
)
619 assert( c
>= 224 && c
< 255 );
622 else if ((c
= getc (fpin
)) == EOF
)
630 partial
= 0; /* (last segment may follow) */
634 pktlen
= (c
- 192) * 256;
635 if ((c
= getc (fpin
)) == EOF
)
643 if (read_u32 (fpin
, &pktlen
))
645 hdr
[hdrlen
++] = pktlen
>> 24;
646 hdr
[hdrlen
++] = pktlen
>> 16;
647 hdr
[hdrlen
++] = pktlen
>> 8;
648 hdr
[hdrlen
++] = pktlen
;
652 { /* next partial body length */
653 for (p
=hdr
; hdrlen
; p
++, hdrlen
--)
655 if ( putc (*p
, fpout
) == EOF
)
658 partlen
= 1 << (c
& 0x1f);
659 for (; partlen
; partlen
--)
661 if ((c
= getc (fpin
)) == EOF
)
663 if ( putc (c
, fpout
) == EOF
)
668 else if (partial
== 2)
671 if ( read_u16 (fpin
, &partlen
) )
673 hdr
[hdrlen
++] = partlen
>> 8;
674 hdr
[hdrlen
++] = partlen
;
675 for (p
=hdr
; hdrlen
; p
++, hdrlen
--)
677 if ( putc (*p
, fpout
) == EOF
)
681 partial
= 0; /* end of packet */
682 for (; partlen
; partlen
--)
687 if ( putc (c
, fpout
) == EOF
)
692 { /* compressed: read to end */
698 if ((c
= getc (fpin
)) == EOF
)
703 if(handle_zlib(c
,fpin
,fpout
))
709 if(handle_bzip2(c
,fpin
,fpout
))
712 #endif /* HAVE_BZIP2 */
715 log_error("invalid compression algorithm (%d)\n",c
);
721 while ( (c
=getc (fpin
)) != EOF
)
723 if ( putc (c
, fpout
) == EOF
)
732 for (p
=hdr
; hdrlen
; p
++, hdrlen
--)
734 if ( putc (*p
, fpout
) == EOF
)
738 /* standard packet or last segment of partial length encoded packet */
739 for (; pktlen
; pktlen
--)
744 if ( putc (c
, fpout
) == EOF
)
749 if ( !opt_no_split
&& fclose (fpout
) )
750 log_error ("error closing `%s': %s\n", outname
, strerror (errno
));
754 log_error ("error writing `%s': %s\n", outname
, strerror (errno
));
775 unsigned long pktlen
= 0;
777 unsigned char header
[20];
782 return 3; /* ready */
783 header
[header_idx
++] = ctb
;
787 log_error("invalid CTB %02x\n", ctb
);
792 pkttype
= (ctb
& 0x3f);
793 if( (c
= getc (fp
)) == EOF
)
795 header
[header_idx
++] = c
;
801 pktlen
= (c
- 192) * 256;
802 if( (c
= getc (fp
)) == EOF
)
804 header
[header_idx
++] = c
;
809 if (read_u32 (fp
, &pktlen
))
811 header
[header_idx
++] = pktlen
>> 24;
812 header
[header_idx
++] = pktlen
>> 16;
813 header
[header_idx
++] = pktlen
>> 8;
814 header
[header_idx
++] = pktlen
;
817 { /* partial body length */
826 pkttype
= (ctb
>>2)&0xf;
827 lenbytes
= ((ctb
&3)==3)? 0 : (1<<(ctb
& 3));
830 pktlen
= 0; /* don't know the value */
831 if( pkttype
== PKT_COMPRESSED
)
834 partial
= 2; /* the old GnuPG partial length encoding */
838 for ( ; lenbytes
; lenbytes
-- )
841 if( (c
= getc (fp
)) == EOF
)
843 header
[header_idx
++] = c
;
850 return write_part (fp
, pktlen
, pkttype
, partial
, header
, header_idx
);
855 split_packets (const char *fname
)
860 if (!fname
|| !strcmp (fname
, "-"))
865 else if ( !(fp
= fopen (fname
,"rb")) )
867 log_error ("can't open `%s': %s\n", fname
, strerror (errno
));
871 while ( !(rc
= do_split (fp
)) )
874 ; /* error already handled */
875 else if ( ferror (fp
) )
876 log_error ("error reading `%s': %s\n", fname
, strerror (errno
));
878 log_error ("premature EOF while reading `%s'\n", fname
);