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;
89 "Please report bugs to <bug-gnupg@gnu.org>.\n";
93 "Usage: gpgsplit [options] [files] (-h for help)";
96 "Syntax: gpgsplit [options] [files]\n"
97 "Split an OpenPGP message into packets\n";
108 main (int argc
, char **argv
)
112 #ifdef HAVE_DOSISH_SYSTEM
113 setmode( fileno(stdin
), O_BINARY
);
114 setmode( fileno(stdout
), O_BINARY
);
116 log_set_prefix ("gpgsplit", JNLIB_LOG_WITH_PREFIX
);
117 set_strusage (my_strusage
);
121 pargs
.flags
= 1; /* do not remove the args */
122 while (optfile_parse( NULL
, NULL
, NULL
, &pargs
, opts
))
126 case oVerbose
: opt_verbose
= 1; break;
127 case oPrefix
: opt_prefix
= pargs
.r
.ret_str
; break;
128 case oUncompress
: opt_uncompress
= 1; break;
129 case oSecretToPublic
: opt_secret_to_public
= 1; break;
130 case oNoSplit
: opt_no_split
= 1; break;
131 default : pargs
.err
= 2; break;
135 if (log_get_errorcount(0))
139 split_packets (NULL
);
142 for ( ;argc
; argc
--, argv
++)
143 split_packets (*argv
);
154 rc
= rc
? rc
: log_get_errorcount(0)? 2 : 0;
159 pkttype_to_string (int pkttype
)
165 case PKT_PUBKEY_ENC
: s
= "pk_enc"; break;
166 case PKT_SIGNATURE
: s
= "sig"; break;
167 case PKT_SYMKEY_ENC
: s
= "sym_enc"; break;
168 case PKT_ONEPASS_SIG
: s
= "onepass_sig"; break;
169 case PKT_SECRET_KEY
: s
= "secret_key"; break;
170 case PKT_PUBLIC_KEY
: s
= "public_key"; break;
171 case PKT_SECRET_SUBKEY
: s
= "secret_subkey"; break;
172 case PKT_COMPRESSED
:
173 s
= opt_uncompress
? "uncompressed":"compressed";
175 case PKT_ENCRYPTED
: s
= "encrypted"; break;
176 case PKT_MARKER
: s
= "marker"; break;
177 case PKT_PLAINTEXT
: s
= "plaintext"; break;
178 case PKT_RING_TRUST
: s
= "ring_trust"; break;
179 case PKT_USER_ID
: s
= "user_id"; break;
180 case PKT_PUBLIC_SUBKEY
: s
= "public_subkey"; break;
181 case PKT_OLD_COMMENT
: s
= "old_comment"; break;
182 case PKT_ATTRIBUTE
: s
= "attribute"; break;
183 case PKT_ENCRYPTED_MDC
: s
= "encrypted_mdc"; break;
184 case PKT_MDC
: s
= "mdc"; break;
185 case PKT_COMMENT
: s
= "comment"; break;
186 case PKT_GPG_CONTROL
: s
= "gpg_control"; break;
187 default: s
= "unknown"; break;
194 * Create a new filename and a return a pointer to a statically
198 create_filename (int pkttype
)
200 static unsigned int partno
= 0;
204 name
= xmalloc (strlen (opt_prefix
) + 100 );
206 assert (pkttype
< 1000 && pkttype
>= 0 );
208 sprintf (name
, "%s%06u-%03d" EXTSEP_S
"%.40s",
209 opt_prefix
, partno
, pkttype
, pkttype_to_string (pkttype
));
214 read_u16 (FILE *fp
, size_t *rn
)
218 if ( (c
= getc (fp
)) == EOF
)
221 if ( (c
= getc (fp
)) == EOF
)
228 read_u32 (FILE *fp
, unsigned long *rn
)
232 if (read_u16 (fp
, &tmp
))
235 if (read_u16 (fp
, &tmp
))
242 write_old_header (FILE *fp
, int pkttype
, unsigned int len
)
244 int ctb
= (0x80 | ((pkttype
& 15)<<2));
248 else if (len
< 65536)
253 if ( putc ( ctb
, fp
) == EOF
)
258 if (putc ((len
>>24), fp
) == EOF
)
260 if (putc ((len
>>16), fp
) == EOF
)
265 if (putc ((len
>>8), fp
) == EOF
)
268 if (putc ((len
&0xff), fp
) == EOF
)
274 write_new_header (FILE *fp
, int pkttype
, unsigned int len
)
276 if ( putc ((0xc0 | (pkttype
& 0x3f)), fp
) == EOF
)
281 if (putc (len
, fp
) == EOF
)
287 if (putc ((len
/256)+192, fp
) == EOF
)
289 if (putc ((len
%256), fp
) == EOF
)
294 if (putc ( 0xff, fp
) == EOF
)
296 if (putc ( (len
>> 24), fp
) == EOF
)
298 if (putc ( (len
>> 16), fp
) == EOF
)
300 if (putc ( (len
>> 8), fp
) == EOF
)
302 if (putc ( (len
& 0xff), fp
) == EOF
)
308 /* Return the length of the public key given BUF of BUFLEN with a
311 public_key_length (const unsigned char *buf
, size_t buflen
)
313 const unsigned char *s
;
316 /* byte version number (3 or 4)
318 [u16 valid days (version 3 only)]
323 if (buf
[0] < 2 || buf
[0] > 4)
324 return 0; /* wrong version number */
325 if (buflen
< (buf
[0] == 4? 6:8))
327 s
= buf
+ (buf
[0] == 4? 6:8);
328 buflen
-= (buf
[0] == 4? 6:8);
347 for (; nmpis
; nmpis
--)
349 unsigned int nbits
, nbytes
;
353 nbits
= (s
[0] << 8) | s
[1];
355 nbytes
= (nbits
+7) / 8;
358 s
+= nbytes
; buflen
-= nbytes
;
365 handle_zlib(int algo
,FILE *fpin
,FILE *fpout
)
368 byte
*inbuf
, *outbuf
;
369 unsigned int inbufsize
, outbufsize
;
370 int c
,zinit_done
, zrc
, nread
, count
;
373 memset (&zs
, 0, sizeof zs
);
375 inbuf
= xmalloc (inbufsize
);
377 outbuf
= xmalloc (outbufsize
);
383 if (zs
.avail_in
< inbufsize
)
387 zs
.next_in
= (Bytef
*) inbuf
;
388 count
= inbufsize
- n
;
390 nread
< count
&& (c
=getc (fpin
)) != EOF
;
395 if (nread
< count
&& algo
== 1)
397 inbuf
[n
] = 0xFF; /* chew dummy byte */
402 zs
.next_out
= (Bytef
*) outbuf
;
403 zs
.avail_out
= outbufsize
;
407 zrc
= (algo
== 1? inflateInit2 ( &zs
, -13)
408 : inflateInit ( &zs
));
411 log_fatal ("zlib problem: %s\n", zs
.msg
? zs
.msg
:
412 zrc
== Z_MEM_ERROR
? "out of core" :
413 zrc
== Z_VERSION_ERROR
?
414 "invalid lib version" :
422 zrc
= inflate (&zs
, Z_SYNC_FLUSH
);
424 zrc
= inflate (&zs
, Z_PARTIAL_FLUSH
);
426 if (zrc
== Z_STREAM_END
)
428 else if (zrc
!= Z_OK
&& zrc
!= Z_BUF_ERROR
)
431 log_fatal ("zlib inflate problem: %s\n", zs
.msg
);
433 log_fatal ("zlib inflate problem: rc=%d\n", zrc
);
435 for (n
=0; n
< outbufsize
- zs
.avail_out
; n
++)
437 if (putc (outbuf
[n
], fpout
) == EOF
)
442 while (zrc
!= Z_STREAM_END
&& zrc
!= Z_BUF_ERROR
);
446 fputs ("Left over bytes:", stderr
);
447 for (i
=0; i
< zs
.avail_in
; i
++)
448 fprintf (stderr
, " %02X", zs
.next_in
[i
]);
459 handle_bzip2(int algo
,FILE *fpin
,FILE *fpout
)
462 byte
*inbuf
, *outbuf
;
463 unsigned int inbufsize
, outbufsize
;
464 int c
,zinit_done
, zrc
, nread
, count
;
467 memset (&bzs
, 0, sizeof bzs
);
469 inbuf
= xmalloc (inbufsize
);
471 outbuf
= xmalloc (outbufsize
);
477 if (bzs
.avail_in
< inbufsize
)
482 count
= inbufsize
- n
;
484 nread
< count
&& (c
=getc (fpin
)) != EOF
;
489 if (nread
< count
&& algo
== 1)
491 inbuf
[n
] = 0xFF; /* chew dummy byte */
496 bzs
.next_out
= outbuf
;
497 bzs
.avail_out
= outbufsize
;
501 zrc
= BZ2_bzDecompressInit(&bzs
,0,0);
503 log_fatal ("bz2lib problem: %d\n",zrc
);
508 zrc
= BZ2_bzDecompress(&bzs
);
509 if (zrc
== BZ_STREAM_END
)
511 else if (zrc
!= BZ_OK
&& zrc
!= BZ_PARAM_ERROR
)
512 log_fatal ("bz2lib inflate problem: %d\n", zrc
);
513 for (n
=0; n
< outbufsize
- bzs
.avail_out
; n
++)
515 if (putc (outbuf
[n
], fpout
) == EOF
)
520 while (zrc
!= BZ_STREAM_END
&& zrc
!= BZ_PARAM_ERROR
);
521 BZ2_bzDecompressEnd(&bzs
);
525 #endif /* HAVE_BZIP2 */
527 /* hdr must point to a buffer large enough to hold all header bytes */
529 write_part (FILE *fpin
, unsigned long pktlen
,
530 int pkttype
, int partial
, unsigned char *hdr
, size_t hdrlen
)
535 const char *outname
= create_filename (pkttype
);
537 #if defined(__riscos__) && defined(USE_ZLIBRISCOS)
538 static int initialized
= 0;
541 initialized
= riscos_load_module("ZLib", zlib_path
, 1);
548 log_info ("writing `%s'\n", outname
);
549 fpout
= fopen (outname
, "wb");
552 log_error ("error creating `%s': %s\n", outname
, strerror(errno
));
553 /* stop right now, otherwise we would mess up the sequence
554 of the part numbers */
559 if (opt_secret_to_public
560 && (pkttype
== PKT_SECRET_KEY
|| pkttype
== PKT_SECRET_SUBKEY
))
562 unsigned char *blob
= xmalloc (pktlen
);
565 pkttype
= pkttype
== PKT_SECRET_KEY
? PKT_PUBLIC_KEY
:PKT_PUBLIC_SUBKEY
;
567 for (i
=0; i
< pktlen
; i
++)
574 len
= public_key_length (blob
, pktlen
);
577 log_error ("error calcualting public key length\n");
580 if ( (hdr
[0] & 0x40) )
582 if (write_new_header (fpout
, pkttype
, len
))
587 if (write_old_header (fpout
, pkttype
, len
))
591 for (i
=0; i
< len
; i
++)
593 if ( putc (blob
[i
], fpout
) == EOF
)
603 for (p
=hdr
; hdrlen
; p
++, hdrlen
--)
605 if ( putc (*p
, fpout
) == EOF
)
620 assert( c
>= 224 && c
< 255 );
623 else if ((c
= getc (fpin
)) == EOF
)
631 partial
= 0; /* (last segment may follow) */
635 pktlen
= (c
- 192) * 256;
636 if ((c
= getc (fpin
)) == EOF
)
644 if (read_u32 (fpin
, &pktlen
))
646 hdr
[hdrlen
++] = pktlen
>> 24;
647 hdr
[hdrlen
++] = pktlen
>> 16;
648 hdr
[hdrlen
++] = pktlen
>> 8;
649 hdr
[hdrlen
++] = pktlen
;
653 { /* next partial body length */
654 for (p
=hdr
; hdrlen
; p
++, hdrlen
--)
656 if ( putc (*p
, fpout
) == EOF
)
659 partlen
= 1 << (c
& 0x1f);
660 for (; partlen
; partlen
--)
662 if ((c
= getc (fpin
)) == EOF
)
664 if ( putc (c
, fpout
) == EOF
)
669 else if (partial
== 2)
672 if ( read_u16 (fpin
, &partlen
) )
674 hdr
[hdrlen
++] = partlen
>> 8;
675 hdr
[hdrlen
++] = partlen
;
676 for (p
=hdr
; hdrlen
; p
++, hdrlen
--)
678 if ( putc (*p
, fpout
) == EOF
)
682 partial
= 0; /* end of packet */
683 for (; partlen
; partlen
--)
688 if ( putc (c
, fpout
) == EOF
)
693 { /* compressed: read to end */
699 if ((c
= getc (fpin
)) == EOF
)
704 if(handle_zlib(c
,fpin
,fpout
))
710 if(handle_bzip2(c
,fpin
,fpout
))
713 #endif /* HAVE_BZIP2 */
716 log_error("invalid compression algorithm (%d)\n",c
);
722 while ( (c
=getc (fpin
)) != EOF
)
724 if ( putc (c
, fpout
) == EOF
)
733 for (p
=hdr
; hdrlen
; p
++, hdrlen
--)
735 if ( putc (*p
, fpout
) == EOF
)
739 /* standard packet or last segment of partial length encoded packet */
740 for (; pktlen
; pktlen
--)
745 if ( putc (c
, fpout
) == EOF
)
750 if ( !opt_no_split
&& fclose (fpout
) )
751 log_error ("error closing `%s': %s\n", outname
, strerror (errno
));
755 log_error ("error writing `%s': %s\n", outname
, strerror (errno
));
776 unsigned long pktlen
= 0;
778 unsigned char header
[20];
783 return 3; /* ready */
784 header
[header_idx
++] = ctb
;
788 log_error("invalid CTB %02x\n", ctb
);
793 pkttype
= (ctb
& 0x3f);
794 if( (c
= getc (fp
)) == EOF
)
796 header
[header_idx
++] = c
;
802 pktlen
= (c
- 192) * 256;
803 if( (c
= getc (fp
)) == EOF
)
805 header
[header_idx
++] = c
;
810 if (read_u32 (fp
, &pktlen
))
812 header
[header_idx
++] = pktlen
>> 24;
813 header
[header_idx
++] = pktlen
>> 16;
814 header
[header_idx
++] = pktlen
>> 8;
815 header
[header_idx
++] = pktlen
;
818 { /* partial body length */
827 pkttype
= (ctb
>>2)&0xf;
828 lenbytes
= ((ctb
&3)==3)? 0 : (1<<(ctb
& 3));
831 pktlen
= 0; /* don't know the value */
832 if( pkttype
== PKT_COMPRESSED
)
835 partial
= 2; /* the old GnuPG partial length encoding */
839 for ( ; lenbytes
; lenbytes
-- )
842 if( (c
= getc (fp
)) == EOF
)
844 header
[header_idx
++] = c
;
851 return write_part (fp
, pktlen
, pkttype
, partial
, header
, header_idx
);
856 split_packets (const char *fname
)
861 if (!fname
|| !strcmp (fname
, "-"))
866 else if ( !(fp
= fopen (fname
,"rb")) )
868 log_error ("can't open `%s': %s\n", fname
, strerror (errno
));
872 while ( !(rc
= do_split (fp
)) )
875 ; /* error already handled */
876 else if ( ferror (fp
) )
877 log_error ("error reading `%s': %s\n", fname
, strerror (errno
));
879 log_error ("premature EOF while reading `%s'\n", fname
);