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 2 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, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
23 * TODO: Add an option to uncompress packets. This should come quite handy.
34 #ifdef HAVE_DOSISH_SYSTEM
35 # include <fcntl.h> /* for setmode() */
40 #endif /* HAVE_BZIP2 */
41 #if defined(__riscos__) && defined(USE_ZLIBRISCOS)
42 # include "zlib-riscos.h"
45 #define INCLUDED_BY_MAIN_MODULE 1
46 #include "../g10/packet.h"
49 static int opt_verbose
;
50 static const char *opt_prefix
= "";
51 static int opt_uncompress
;
52 static int opt_secret_to_public
;
53 static int opt_no_split
;
55 static void g10_exit( int rc
);
56 static void split_packets (const char *fname
);
59 enum cmd_and_opt_values
{
71 static ARGPARSE_OPTS opts
[] = {
73 { 301, NULL
, 0, "@Options:\n " },
75 { oVerbose
, "verbose", 0, "verbose" },
76 { oPrefix
, "prefix", 2, "|STRING|Prepend filenames with STRING" },
77 { oUncompress
, "uncompress", 0, "uncompress a packet"},
78 { oSecretToPublic
, "secret-to-public", 0, "convert secret keys to public keys"},
79 { oNoSplit
, "no-split", 0, "write to stdout and don't actually split"},
89 case 11: p
= "gpgsplit (GnuPG)";
91 case 13: p
= VERSION
; break;
92 case 17: p
= PRINTABLE_OS_NAME
; break;
94 "Please report bugs to <bug-gnupg@gnu.org>.\n";
98 "Usage: gpgsplit [options] [files] (-h for help)";
101 "Syntax: gpgsplit [options] [files]\n"
102 "Split an OpenPGP message into packets\n";
105 default: p
= default_strusage(level
);
113 main( int argc
, char **argv
)
117 #ifdef HAVE_DOSISH_SYSTEM
118 setmode( fileno(stdin
), O_BINARY
);
119 setmode( fileno(stdout
), O_BINARY
);
121 log_set_name("gpgsplit");
125 pargs
.flags
= 1; /* do not remove the args */
126 while (optfile_parse( NULL
, NULL
, NULL
, &pargs
, opts
))
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;
139 if (log_get_errorcount(0))
143 split_packets (NULL
);
146 for ( ;argc
; argc
--, argv
++)
147 split_packets (*argv
);
158 rc
= rc
? rc
: log_get_errorcount(0)? 2 : 0;
163 pkttype_to_string (int pkttype
)
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";
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;
198 * Create a new filename and a return a pointer to a statically
202 create_filename (int pkttype
)
204 static unsigned int partno
= 0;
208 name
= xmalloc (strlen (opt_prefix
) + 100 );
210 assert (pkttype
< 1000 && pkttype
>= 0 );
212 sprintf (name
, "%s%06u-%03d" EXTSEP_S
"%.40s",
213 opt_prefix
, partno
, pkttype
, pkttype_to_string (pkttype
));
218 read_u16 (FILE *fp
, size_t *rn
)
222 if ( (c
= getc (fp
)) == EOF
)
225 if ( (c
= getc (fp
)) == EOF
)
232 read_u32 (FILE *fp
, unsigned long *rn
)
236 if (read_u16 (fp
, &tmp
))
239 if (read_u16 (fp
, &tmp
))
246 write_old_header (FILE *fp
, int pkttype
, unsigned int len
)
248 int ctb
= (0x80 | ((pkttype
& 15)<<2));
252 else if (len
< 65536)
257 if ( putc ( ctb
, fp
) == EOF
)
262 if (putc ((len
>>24), fp
) == EOF
)
264 if (putc ((len
>>16), fp
) == EOF
)
269 if (putc ((len
>>8), fp
) == EOF
)
272 if (putc ((len
&0xff), fp
) == EOF
)
278 write_new_header (FILE *fp
, int pkttype
, unsigned int len
)
280 if ( putc ((0xc0 | (pkttype
& 0x3f)), fp
) == EOF
)
285 if (putc (len
, fp
) == EOF
)
291 if (putc ((len
/256)+192, fp
) == EOF
)
293 if (putc ((len
%256), fp
) == EOF
)
298 if (putc ( 0xff, fp
) == EOF
)
300 if (putc ( (len
>> 24), fp
) == EOF
)
302 if (putc ( (len
>> 16), fp
) == EOF
)
304 if (putc ( (len
>> 8), fp
) == EOF
)
306 if (putc ( (len
& 0xff), fp
) == EOF
)
312 /* Return the length of the public key given BUF of BUFLEN with a
315 public_key_length (const unsigned char *buf
, size_t buflen
)
317 const unsigned char *s
;
320 /* byte version number (3 or 4)
322 [u16 valid days (version 3 only)]
327 if (buf
[0] < 2 || buf
[0] > 4)
328 return 0; /* wrong version number */
329 if (buflen
< (buf
[0] == 4? 6:8))
331 s
= buf
+ (buf
[0] == 4? 6:8);
332 buflen
-= (buf
[0] == 4? 6:8);
351 for (; nmpis
; nmpis
--)
353 unsigned int nbits
, nbytes
;
357 nbits
= (s
[0] << 8) | s
[1];
359 nbytes
= (nbits
+7) / 8;
362 s
+= nbytes
; buflen
-= nbytes
;
369 handle_zlib(int algo
,FILE *fpin
,FILE *fpout
)
372 byte
*inbuf
, *outbuf
;
373 unsigned int inbufsize
, outbufsize
;
374 int c
,zinit_done
, zrc
, nread
, count
;
377 memset (&zs
, 0, sizeof zs
);
379 inbuf
= xmalloc (inbufsize
);
381 outbuf
= xmalloc (outbufsize
);
387 if (zs
.avail_in
< inbufsize
)
391 zs
.next_in
= (Bytef
*) inbuf
;
392 count
= inbufsize
- n
;
394 nread
< count
&& (c
=getc (fpin
)) != EOF
;
399 if (nread
< count
&& algo
== 1)
401 inbuf
[n
] = 0xFF; /* chew dummy byte */
406 zs
.next_out
= (Bytef
*) outbuf
;
407 zs
.avail_out
= outbufsize
;
411 zrc
= (algo
== 1? inflateInit2 ( &zs
, -13)
412 : inflateInit ( &zs
));
415 log_fatal ("zlib problem: %s\n", zs
.msg
? zs
.msg
:
416 zrc
== Z_MEM_ERROR
? "out of core" :
417 zrc
== Z_VERSION_ERROR
?
418 "invalid lib version" :
426 zrc
= inflate (&zs
, Z_SYNC_FLUSH
);
428 zrc
= inflate (&zs
, Z_PARTIAL_FLUSH
);
430 if (zrc
== Z_STREAM_END
)
432 else if (zrc
!= Z_OK
&& zrc
!= Z_BUF_ERROR
)
435 log_fatal ("zlib inflate problem: %s\n", zs
.msg
);
437 log_fatal ("zlib inflate problem: rc=%d\n", zrc
);
439 for (n
=0; n
< outbufsize
- zs
.avail_out
; n
++)
441 if (putc (outbuf
[n
], fpout
) == EOF
)
446 while (zrc
!= Z_STREAM_END
&& zrc
!= Z_BUF_ERROR
);
454 handle_bzip2(int algo
,FILE *fpin
,FILE *fpout
)
457 byte
*inbuf
, *outbuf
;
458 unsigned int inbufsize
, outbufsize
;
459 int c
,zinit_done
, zrc
, nread
, count
;
462 memset (&bzs
, 0, sizeof bzs
);
464 inbuf
= xmalloc (inbufsize
);
466 outbuf
= xmalloc (outbufsize
);
472 if (bzs
.avail_in
< inbufsize
)
477 count
= inbufsize
- n
;
479 nread
< count
&& (c
=getc (fpin
)) != EOF
;
484 if (nread
< count
&& algo
== 1)
486 inbuf
[n
] = 0xFF; /* chew dummy byte */
491 bzs
.next_out
= outbuf
;
492 bzs
.avail_out
= outbufsize
;
496 zrc
= BZ2_bzDecompressInit(&bzs
,0,0);
498 log_fatal ("bz2lib problem: %d\n",zrc
);
503 zrc
= BZ2_bzDecompress(&bzs
);
504 if (zrc
== BZ_STREAM_END
)
506 else if (zrc
!= BZ_OK
&& zrc
!= BZ_PARAM_ERROR
)
507 log_fatal ("bz2lib inflate problem: %d\n", zrc
);
508 for (n
=0; n
< outbufsize
- bzs
.avail_out
; n
++)
510 if (putc (outbuf
[n
], fpout
) == EOF
)
515 while (zrc
!= BZ_STREAM_END
&& zrc
!= BZ_PARAM_ERROR
);
516 BZ2_bzDecompressEnd(&bzs
);
520 #endif /* HAVE_BZIP2 */
522 /* hdr must point to a buffer large enough to hold all header bytes */
524 write_part ( const char *fname
, FILE *fpin
, unsigned long pktlen
,
525 int pkttype
, int partial
, unsigned char *hdr
, size_t hdrlen
)
530 const char *outname
= create_filename (pkttype
);
532 #if defined(__riscos__) && defined(USE_ZLIBRISCOS)
533 static int initialized
= 0;
536 initialized
= riscos_load_module("ZLib", zlib_path
, 1);
543 log_info ("writing `%s'\n", outname
);
544 fpout
= fopen (outname
, "wb");
547 log_error ("error creating `%s': %s\n", outname
, strerror(errno
));
548 /* stop right now, otherwise we would mess up the sequence
549 of the part numbers */
554 if (opt_secret_to_public
555 && (pkttype
== PKT_SECRET_KEY
|| pkttype
== PKT_SECRET_SUBKEY
))
557 unsigned char *blob
= xmalloc (pktlen
);
560 pkttype
= pkttype
== PKT_SECRET_KEY
? PKT_PUBLIC_KEY
:PKT_PUBLIC_SUBKEY
;
562 for (i
=0; i
< pktlen
; i
++)
569 len
= public_key_length (blob
, pktlen
);
572 log_error ("error calcualting public key length\n");
575 if ( (hdr
[0] & 0x40) )
577 if (write_new_header (fpout
, pkttype
, len
))
582 if (write_old_header (fpout
, pkttype
, len
))
586 for (i
=0; i
< len
; i
++)
588 if ( putc (blob
[i
], fpout
) == EOF
)
598 for (p
=hdr
; hdrlen
; p
++, hdrlen
--)
600 if ( putc (*p
, fpout
) == EOF
)
615 assert( c
>= 224 && c
< 255 );
618 else if ((c
= getc (fpin
)) == EOF
)
626 partial
= 0; /* (last segment may follow) */
630 pktlen
= (c
- 192) * 256;
631 if ((c
= getc (fpin
)) == EOF
)
639 if (read_u32 (fpin
, &pktlen
))
641 hdr
[hdrlen
++] = pktlen
>> 24;
642 hdr
[hdrlen
++] = pktlen
>> 16;
643 hdr
[hdrlen
++] = pktlen
>> 8;
644 hdr
[hdrlen
++] = pktlen
;
648 { /* next partial body length */
649 for (p
=hdr
; hdrlen
; p
++, hdrlen
--)
651 if ( putc (*p
, fpout
) == EOF
)
654 partlen
= 1 << (c
& 0x1f);
655 for (; partlen
; partlen
--)
657 if ((c
= getc (fpin
)) == EOF
)
659 if ( putc (c
, fpout
) == EOF
)
664 else if (partial
== 2)
667 if ( read_u16 (fpin
, &partlen
) )
669 hdr
[hdrlen
++] = partlen
>> 8;
670 hdr
[hdrlen
++] = partlen
;
671 for (p
=hdr
; hdrlen
; p
++, hdrlen
--)
673 if ( putc (*p
, fpout
) == EOF
)
677 partial
= 0; /* end of packet */
678 for (; partlen
; partlen
--)
683 if ( putc (c
, fpout
) == EOF
)
688 { /* compressed: read to end */
694 if ((c
= getc (fpin
)) == EOF
)
699 if(handle_zlib(c
,fpin
,fpout
))
705 if(handle_bzip2(c
,fpin
,fpout
))
708 #endif /* HAVE_BZIP2 */
711 log_error("invalid compression algorithm (%d)\n",c
);
717 while ( (c
=getc (fpin
)) != EOF
)
719 if ( putc (c
, fpout
) == EOF
)
728 for (p
=hdr
; hdrlen
; p
++, hdrlen
--)
730 if ( putc (*p
, fpout
) == EOF
)
734 /* standard packet or last segment of partial length encoded packet */
735 for (; pktlen
; pktlen
--)
740 if ( putc (c
, fpout
) == EOF
)
745 if ( !opt_no_split
&& fclose (fpout
) )
746 log_error ("error closing `%s': %s\n", outname
, strerror (errno
));
750 log_error ("error writing `%s': %s\n", outname
, strerror (errno
));
768 do_split (const char *fname
, FILE *fp
)
771 unsigned long pktlen
= 0;
773 unsigned char header
[20];
778 return 3; /* ready */
779 header
[header_idx
++] = ctb
;
783 log_error("invalid CTB %02x\n", ctb
);
788 pkttype
= (ctb
& 0x3f);
789 if( (c
= getc (fp
)) == EOF
)
791 header
[header_idx
++] = c
;
797 pktlen
= (c
- 192) * 256;
798 if( (c
= getc (fp
)) == EOF
)
800 header
[header_idx
++] = c
;
805 if (read_u32 (fp
, &pktlen
))
807 header
[header_idx
++] = pktlen
>> 24;
808 header
[header_idx
++] = pktlen
>> 16;
809 header
[header_idx
++] = pktlen
>> 8;
810 header
[header_idx
++] = pktlen
;
813 { /* partial body length */
822 pkttype
= (ctb
>>2)&0xf;
823 lenbytes
= ((ctb
&3)==3)? 0 : (1<<(ctb
& 3));
826 pktlen
= 0; /* don't know the value */
827 if( pkttype
== PKT_COMPRESSED
)
830 partial
= 2; /* the old GnuPG partial length encoding */
834 for ( ; lenbytes
; lenbytes
-- )
837 if( (c
= getc (fp
)) == EOF
)
839 header
[header_idx
++] = c
;
846 return write_part (fname
, fp
, pktlen
, pkttype
, partial
,
852 split_packets (const char *fname
)
857 if (!fname
|| !strcmp (fname
, "-"))
862 else if ( !(fp
= fopen (fname
,"rb")) )
864 log_error ("can't open `%s': %s\n", fname
, strerror (errno
));
868 while ( !(rc
= do_split (fname
, fp
)) )
871 ; /* error already handled */
872 else if ( ferror (fp
) )
873 log_error ("error reading `%s': %s\n", fname
, strerror (errno
));
875 log_error ("premature EOF while reading `%s'\n", fname
);