release 0.2.14
[gnupg.git] / g10 / parse-packet.c
1 /* parse-packet.c  - read packets
2  *      Copyright (C) 1998 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 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <assert.h>
26
27 #include "packet.h"
28 #include "iobuf.h"
29 #include "mpi.h"
30 #include "util.h"
31 #include "cipher.h"
32 #include "memory.h"
33 #include "filter.h"
34 #include "options.h"
35
36 static mpi_print_mode = 0;
37 static list_mode = 0;
38
39 static int  parse( IOBUF inp, PACKET *pkt, int reqtype,
40                    ulong *retpos, int *skip, IOBUF out, int do_skip );
41 static int  copy_packet( IOBUF inp, IOBUF out, int pkttype,
42                                                unsigned long pktlen );
43 static void skip_packet( IOBUF inp, int pkttype, unsigned long pktlen );
44 static void skip_rest( IOBUF inp, unsigned long pktlen );
45 static int  parse_publickey( IOBUF inp, int pkttype, unsigned long pktlen,
46                                                              PACKET *packet );
47 static int  parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
48                                                          PKT_signature *sig );
49 static int  parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen,
50                                                         PKT_onepass_sig *ops );
51 static int  parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
52                                       byte *hdr, int hdrlen, PACKET *packet );
53 static int  parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen,
54                                                            PACKET *packet );
55 static int  parse_comment( IOBUF inp, int pkttype, unsigned long pktlen,
56                                                            PACKET *packet );
57 static void parse_trust( IOBUF inp, int pkttype, unsigned long pktlen );
58 static int  parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen,
59                                                                 PACKET *pkt );
60 static int  parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen,
61                                                            PACKET *packet );
62 static int  parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
63                                                            PACKET *packet );
64 #if 0
65 static u16
66 checksum( byte *p )
67 {
68     u16 n, a;
69
70     n = *p++ << 8;
71     n |= *p++;
72     for(a=0; n; n-- )
73         a += *p++;
74     return a;
75 }
76 #endif
77
78 static unsigned short
79 read_16(IOBUF inp)
80 {
81     unsigned short a;
82     a = iobuf_get_noeof(inp) << 8;
83     a |= iobuf_get_noeof(inp);
84     return a;
85 }
86
87 static unsigned long
88 read_32(IOBUF inp)
89 {
90     unsigned long a;
91     a =  iobuf_get_noeof(inp) << 24;
92     a |= iobuf_get_noeof(inp) << 16;
93     a |= iobuf_get_noeof(inp) << 8;
94     a |= iobuf_get_noeof(inp);
95     return a;
96 }
97
98 static unsigned long
99 buffer_to_u32( const byte *buffer )
100 {
101     unsigned long a;
102     a =  *buffer << 24;
103     a |= buffer[1] << 16;
104     a |= buffer[2] << 8;
105     a |= buffer[3];
106     return a;
107 }
108
109 int
110 set_packet_list_mode( int mode )
111 {
112     int old = list_mode;
113     list_mode = mode;
114     mpi_print_mode = DBG_MPI;
115     return old;
116 }
117
118 /****************
119  * Parse a Packet and return it in packet
120  * Returns: 0 := valid packet in pkt
121  *         -1 := no more packets
122  *         >0 := error
123  * Note: The function may return an error and a partly valid packet;
124  * caller must free this packet.
125  */
126 int
127 parse_packet( IOBUF inp, PACKET *pkt )
128 {
129     int skip, rc;
130
131     do {
132         rc = parse( inp, pkt, 0, NULL, &skip, NULL, 0 );
133     } while( skip );
134     return rc;
135 }
136
137 /****************
138  * Like parse packet, but do only return packets of the given type.
139  */
140 int
141 search_packet( IOBUF inp, PACKET *pkt, int pkttype, ulong *retpos )
142 {
143     int skip, rc;
144
145     do {
146         rc = parse( inp, pkt, pkttype, retpos, &skip, NULL, 0 );
147     } while( skip );
148     return rc;
149 }
150
151 /****************
152  * Copy all packets from INP to OUT, thereby removing unused spaces.
153  */
154 int
155 copy_all_packets( IOBUF inp, IOBUF out )
156 {
157     PACKET pkt;
158     int skip, rc=0;
159     do {
160         init_packet(&pkt);
161     } while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0 )));
162     return rc;
163 }
164
165 /****************
166  * Copy some packets from INP to OUT, thereby removing unused spaces.
167  * Stop after at offset STOPoff (i.e. don't copy the packet at this offset)
168  */
169 int
170 copy_some_packets( IOBUF inp, IOBUF out, ulong stopoff )
171 {
172     PACKET pkt;
173     int skip, rc=0;
174     do {
175         if( iobuf_tell(inp) >= stopoff )
176             return 0;
177         init_packet(&pkt);
178     } while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0 )) );
179     return rc;
180 }
181
182 /****************
183  * Skip over N packets
184  */
185 int
186 skip_some_packets( IOBUF inp, unsigned n )
187 {
188     int skip, rc=0;
189     PACKET pkt;
190
191     for( ;n && !rc; n--) {
192         init_packet(&pkt);
193         rc = parse( inp, &pkt, 0, NULL, &skip, NULL, 1 );
194     }
195     return rc;
196 }
197
198 /****************
199  * Parse packet. Set the variable skip points to to 1 if the packet
200  * should be skipped; this is the case if either there is a
201  * requested packet type and the parsed packet doesn't match or the
202  * packet-type is 0, indicating deleted stuff.
203  * if OUT is not NULL, a special copymode is used.
204  */
205 static int
206 parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos,
207        int *skip, IOBUF out, int do_skip )
208 {
209     int rc, c, ctb, pkttype, lenbytes;
210     unsigned long pktlen;
211     byte hdr[5];
212     int hdrlen;
213     int pgp3 = 0;
214
215     *skip = 0;
216     assert( !pkt->pkt.generic );
217     if( retpos )
218         *retpos = iobuf_tell(inp);
219     if( (ctb = iobuf_get(inp)) == -1 )
220         return -1;
221     hdrlen=0;
222     hdr[hdrlen++] = ctb;
223     if( !(ctb & 0x80) ) {
224         log_error("%s: invalid packet (ctb=%02x)\n", iobuf_where(inp), ctb );
225         return G10ERR_INVALID_PACKET;
226     }
227     pktlen = 0;
228     pgp3 = !!(ctb & 0x40);
229     if( pgp3 ) {
230         pkttype =  ctb & 0x3f;
231         if( (c = iobuf_get(inp)) == -1 ) {
232             log_error("%s: 1st length byte missing\n", iobuf_where(inp) );
233             return G10ERR_INVALID_PACKET;
234         }
235         hdr[hdrlen++] = c;
236         if( c < 192 )
237             pktlen = c;
238         else if( c < 224 ) {
239             pktlen = (c - 192) * 256;
240             if( (c = iobuf_get(inp)) == -1 ) {
241                 log_error("%s: 2nd length byte missing\n", iobuf_where(inp) );
242                 return G10ERR_INVALID_PACKET;
243             }
244             hdr[hdrlen++] = c;
245             pktlen += c + 192;
246         }
247         else { /* partial body length */
248             pktlen = 1 << (c & 0x1f);
249             log_debug("partial body length of %lu bytes\n", pktlen );
250             iobuf_set_partial_block_mode(inp, pktlen);
251             pktlen = 0;/* to indicate partial length */
252         }
253     }
254     else {
255         pkttype = (ctb>>2)&0xf;
256         lenbytes = ((ctb&3)==3)? 0 : (1<<(ctb & 3));
257         if( !lenbytes ) {
258             pktlen = 0; /* don't know the value */
259             if( pkttype != PKT_COMPRESSED )
260                 iobuf_set_block_mode(inp, 1);
261         }
262         else {
263             for( ; lenbytes; lenbytes-- ) {
264                 pktlen <<= 8;
265                 pktlen |= hdr[hdrlen++] = iobuf_get_noeof(inp);
266             }
267         }
268     }
269
270     if( out && pkttype  ) {
271         if( iobuf_write( out, hdr, hdrlen ) == -1 )
272             rc = G10ERR_WRITE_FILE;
273         else
274             rc = copy_packet(inp, out, pkttype, pktlen );
275         return rc;
276     }
277
278     if( do_skip || !pkttype || (reqtype && pkttype != reqtype) ) {
279         skip_packet(inp, pkttype, pktlen);
280         *skip = 1;
281         return 0;
282     }
283
284     if( DBG_PACKET )
285         log_debug("parse_packet(iob=%d): type=%d length=%lu%s\n",
286                    iobuf_id(inp), pkttype, pktlen, pgp3?" (pgp3)":"" );
287     pkt->pkttype = pkttype;
288     rc = G10ERR_UNKNOWN_PACKET; /* default error */
289     switch( pkttype ) {
290       case PKT_PUBLIC_CERT:
291       case PKT_PUBKEY_SUBCERT:
292         pkt->pkt.public_cert = m_alloc_clear(sizeof *pkt->pkt.public_cert );
293         rc = parse_certificate(inp, pkttype, pktlen, hdr, hdrlen, pkt );
294         break;
295       case PKT_SECRET_CERT:
296       case PKT_SECKEY_SUBCERT:
297         pkt->pkt.secret_cert = m_alloc_clear(sizeof *pkt->pkt.secret_cert );
298         rc = parse_certificate(inp, pkttype, pktlen, hdr, hdrlen, pkt );
299         break;
300       case PKT_PUBKEY_ENC:
301         rc = parse_publickey(inp, pkttype, pktlen, pkt );
302         break;
303       case PKT_SIGNATURE:
304         pkt->pkt.signature = m_alloc_clear(sizeof *pkt->pkt.signature );
305         rc = parse_signature(inp, pkttype, pktlen, pkt->pkt.signature );
306         break;
307       case PKT_ONEPASS_SIG:
308         pkt->pkt.onepass_sig = m_alloc_clear(sizeof *pkt->pkt.onepass_sig );
309         rc = parse_onepass_sig(inp, pkttype, pktlen, pkt->pkt.onepass_sig );
310         break;
311       case PKT_USER_ID:
312         rc = parse_user_id(inp, pkttype, pktlen, pkt );
313         break;
314       case PKT_COMMENT:
315         rc = parse_comment(inp, pkttype, pktlen, pkt);
316         break;
317       case PKT_RING_TRUST:
318         parse_trust(inp, pkttype, pktlen);
319         break;
320       case PKT_PLAINTEXT:
321         rc = parse_plaintext(inp, pkttype, pktlen, pkt );
322         break;
323       case PKT_COMPRESSED:
324         rc = parse_compressed(inp, pkttype, pktlen, pkt );
325         break;
326       case PKT_ENCRYPTED:
327         rc = parse_encrypted(inp, pkttype, pktlen, pkt );
328         break;
329       default:
330         skip_packet(inp, pkttype, pktlen);
331         break;
332     }
333
334     return rc;
335 }
336
337 static void
338 dump_hex_line( int c, int *i )
339 {
340     if( *i && !(*i%8) ) {
341         if( *i && !(*i%24) )
342             printf("\n%4d:", *i );
343         else
344             putchar(' ');
345     }
346     if( c == -1 )
347         printf(" EOF" );
348     else
349         printf(" %02x", c );
350     ++*i;
351 }
352
353
354 static int
355 copy_packet( IOBUF inp, IOBUF out, int pkttype, unsigned long pktlen )
356 {
357     int n;
358     char buf[100];
359
360     if( iobuf_in_block_mode(inp) ) {
361         while( (n = iobuf_read( inp, buf, 100 )) != -1 )
362             if( iobuf_write(out, buf, n ) )
363                 return G10ERR_WRITE_FILE; /* write error */
364     }
365     else if( !pktlen && pkttype == PKT_COMPRESSED ) {
366         /* compressed packet, copy till EOF */
367         while( (n = iobuf_read( inp, buf, 100 )) != -1 )
368             if( iobuf_write(out, buf, n ) )
369                 return G10ERR_WRITE_FILE; /* write error */
370     }
371     else {
372         for( ; pktlen; pktlen -= n ) {
373             n = pktlen > 100 ? 100 : pktlen;
374             n = iobuf_read( inp, buf, n );
375             if( n == -1 )
376                 return G10ERR_READ_FILE;
377             if( iobuf_write(out, buf, n ) )
378                 return G10ERR_WRITE_FILE; /* write error */
379         }
380     }
381     return 0;
382 }
383
384
385 static void
386 skip_packet( IOBUF inp, int pkttype, unsigned long pktlen )
387 {
388     if( list_mode ) {
389         printf(":unknown packet: type %2d, length %lu\n", pkttype, pktlen );
390         if( pkttype ) {
391             int c, i=0 ;
392             printf("dump:");
393             if( iobuf_in_block_mode(inp) ) {
394                 while( (c=iobuf_get(inp)) != -1 )
395                     dump_hex_line(c, &i);
396             }
397             else {
398                 for( ; pktlen; pktlen-- )
399                     dump_hex_line(iobuf_get(inp), &i);
400             }
401             putchar('\n');
402             return;
403         }
404     }
405     skip_rest(inp,pktlen);
406 }
407
408 static void
409 skip_rest( IOBUF inp, unsigned long pktlen )
410 {
411     if( iobuf_in_block_mode(inp) ) {
412         while( iobuf_get(inp) != -1 )
413                 ;
414     }
415     else {
416         for( ; pktlen; pktlen-- )
417             iobuf_get(inp);
418     }
419 }
420
421
422 static int
423 parse_publickey( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
424 {
425     unsigned n;
426     PKT_pubkey_enc *k;
427
428     k = packet->pkt.pubkey_enc = m_alloc(sizeof *packet->pkt.pubkey_enc );
429     if( pktlen < 12 ) {
430         log_error("packet(%d) too short\n", pkttype);
431         goto leave;
432     }
433     k->version = iobuf_get_noeof(inp); pktlen--;
434     if( k->version != 2 && k->version != 3 ) {
435         log_error("packet(%d) with unknown version %d\n", pkttype, k->version);
436         goto leave;
437     }
438     k->keyid[0] = read_32(inp); pktlen -= 4;
439     k->keyid[1] = read_32(inp); pktlen -= 4;
440     k->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
441     if( list_mode )
442         printf(":public key encoded packet: version %d, keyid %08lX%08lX\n",
443                             k->version, (ulong)k->keyid[0], (ulong)k->keyid[1]);
444     if( k->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
445         n = pktlen;
446         k->d.elg.a = mpi_read(inp, &n, 0); pktlen -=n;
447         n = pktlen;
448         k->d.elg.b = mpi_read(inp, &n, 0 ); pktlen -=n;
449         if( list_mode ) {
450             printf("\telg a: ");
451             mpi_print(stdout, k->d.elg.a, mpi_print_mode );
452             printf("\n\telg b: ");
453             mpi_print(stdout, k->d.elg.b, mpi_print_mode );
454             putchar('\n');
455         }
456     }
457     else if( k->pubkey_algo == PUBKEY_ALGO_RSA ) {
458         n = pktlen;
459         k->d.rsa.rsa_integer = mpi_read(inp, &n, 0 ); pktlen -=n;
460         if( list_mode ) {
461             printf("\trsa integer: ");
462             mpi_print(stdout, k->d.rsa.rsa_integer, mpi_print_mode );
463             putchar('\n');
464         }
465     }
466     else if( list_mode )
467         printf("\tunknown algorithm %d\n", k->pubkey_algo );
468
469
470   leave:
471     skip_rest(inp, pktlen);
472     return 0;
473 }
474
475
476 static const byte *
477 parse_subpkt( const byte *buffer, int reqtype )
478 {
479     int buflen = (*buffer << 8) | buffer[1];
480     int type;
481     int critical;
482     size_t n;
483
484     buffer += 2;
485     for(;;) {
486         if( !buflen )
487             return NULL; /* end of packets; not found */
488         n = *buffer++; buflen--;
489         if( n >= 192 ) {
490             if( buflen < 2 )
491                 goto too_short;
492             n = (( n - 192 ) << 8) + *buffer + 192;
493             buflen--;
494         }
495         if( buflen < n )
496             goto too_short;
497         type = *buffer;
498         if( type & 0x80 ) {
499             type &= 0x7f;
500             critical = 1;
501         }
502         else
503             critical = 0;
504         if( reqtype < 0 ) { /* list packets */
505             printf("\t%ssubpacket %d of length %u (%s)\n",
506                     reqtype == -1 ? "hashed ":"", type, n,
507                     type == 2 ? "signature creation time"
508                   : type == 3 ? "signature expiration time"
509                   : type == 4 ? "exportable"
510                   : type == 5 ? "trust signature"
511                   : type == 6 ? "regular expression"
512                   : type == 7 ? "revocable"
513                   : type == 9 ? "key expiration time"
514                   : type ==10 ? "additional recipient request"
515                   : type ==11 ? "preferred symmetric algorithms"
516                   : type ==12 ? "revocation key"
517                   : type ==16 ? "issuer key ID"
518                   : type ==20 ? "notation data"
519                   : type ==21 ? "preferred hash algorithms"
520                   : type ==22 ? "preferred compression algorithms"
521                   : type ==23 ? "key server preferences"
522                   : type ==24 ? "preferred key server"
523                               : "?");
524         }
525         else if( type == reqtype )
526             break; /* found */
527         buffer += n; buflen -=n;
528     }
529     buffer++;
530     n--;
531     if( n > buflen )
532         goto too_short;
533     switch( type ) {
534       case 2: /* signature creation time */
535         if( n < 4 )
536             break;
537         return buffer;
538       case 16:/* issuer key ID */
539         if( n < 8 )
540             break;
541         return buffer;
542       case 3: /* signature expiration time */
543       case 4: /* exportable */
544       case 5: /* trust signature */
545       case 6: /* regular expression */
546       case 7: /* revocable */
547       case 9: /* key expiration time */
548       case 10:/* additional recipient request */
549       case 11:/* preferred symmetric algorithms */
550       case 12:/* revocation key */
551       case 20:/* notation data */
552       case 21:/* preferred hash algorithms */
553       case 22:/* preferred compression algorithms */
554       case 23:/* key server preferences */
555       case 24:/* preferred key server */
556       default: BUG(); /* not yet needed */
557     }
558     log_error("subpacket of type %d too short\n", type);
559     return NULL;
560
561   too_short:
562     log_error("buffer shorter than subpacket\n");
563     return NULL;
564 }
565
566
567 static int
568 parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
569                                           PKT_signature *sig )
570 {
571     int md5_len=0;
572     unsigned n;
573     int is_v4=0;
574     int rc=0;
575
576     if( pktlen < 16 ) {
577         log_error("packet(%d) too short\n", pkttype);
578         goto leave;
579     }
580     sig->version = iobuf_get_noeof(inp); pktlen--;
581     if( sig->version == 4 )
582         is_v4=1;
583     else if( sig->version != 2 && sig->version != 3 ) {
584         log_error("packet(%d) with unknown version %d\n", pkttype, sig->version);
585         goto leave;
586     }
587
588     if( !is_v4 ) {
589         md5_len = iobuf_get_noeof(inp); pktlen--;
590     }
591     sig->sig_class = iobuf_get_noeof(inp); pktlen--;
592     if( !is_v4 ) {
593         sig->timestamp = read_32(inp); pktlen -= 4;
594         sig->keyid[0] = read_32(inp); pktlen -= 4;
595         sig->keyid[1] = read_32(inp); pktlen -= 4;
596     }
597     sig->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
598     sig->digest_algo = iobuf_get_noeof(inp); pktlen--;
599     if( is_v4 ) { /* read subpackets */
600         n = read_16(inp); pktlen -= 2; /* length of hashed data */
601         if( n > 10000 ) {
602             log_error("signature packet: hashed data too long\n");
603             rc = G10ERR_INVALID_PACKET;
604             goto leave;
605         }
606         if( n ) {
607             sig->hashed_data = m_alloc( n + 2 );
608             sig->hashed_data[0] = n << 8;
609             sig->hashed_data[1] = n;
610             if( iobuf_read(inp, sig->hashed_data+2, n ) != n ) {
611                 log_error("premature eof while reading hashed signature data\n");
612                 rc = -1;
613                 goto leave;
614             }
615             pktlen -= n;
616         }
617         n = read_16(inp); pktlen -= 2; /* length of unhashed data */
618         if( n > 10000 ) {
619             log_error("signature packet: unhashed data too long\n");
620             rc = G10ERR_INVALID_PACKET;
621             goto leave;
622         }
623         if( n ) {
624             sig->unhashed_data = m_alloc( n + 2 );
625             sig->unhashed_data[0] = n << 8;
626             sig->unhashed_data[1] = n;
627             if( iobuf_read(inp, sig->unhashed_data+2, n ) != n ) {
628                 log_error("premature eof while reading unhashed signature data\n");
629                 rc = -1;
630                 goto leave;
631             }
632             pktlen -= n;
633         }
634     }
635
636     if( pktlen < 5 ) { /* sanity check */
637         log_error("packet(%d) too short\n", pkttype);
638         rc = G10ERR_INVALID_PACKET;
639         goto leave;
640     }
641
642     sig->digest_start[0] = iobuf_get_noeof(inp); pktlen--;
643     sig->digest_start[1] = iobuf_get_noeof(inp); pktlen--;
644
645     if( is_v4 ) { /*extract required informations */
646         const byte *p;
647         p = parse_subpkt( sig->hashed_data, 2 );
648         if( !p )
649             log_error("signature packet without timestamp\n");
650         else
651             sig->timestamp = buffer_to_u32(p);
652         p = parse_subpkt( sig->unhashed_data, 16 );
653         if( !p )
654             log_error("signature packet without keyid\n");
655         else {
656             sig->keyid[0] = buffer_to_u32(p);
657             sig->keyid[1] = buffer_to_u32(p+4);
658         }
659     }
660
661     if( list_mode ) {
662         printf(":signature packet: keyid %08lX%08lX\n"
663                "\tversion %d, created %lu, md5len %d, sigclass %02x\n"
664                "\tdigest algo %d, begin of digest %02x %02x\n",
665                 (ulong)sig->keyid[0], (ulong)sig->keyid[1],
666                 sig->version, (ulong)sig->timestamp, md5_len, sig->sig_class,
667                 sig->digest_algo,
668                 sig->digest_start[0], sig->digest_start[1] );
669         if( is_v4 ) {
670             parse_subpkt( sig->hashed_data, -1 );
671             parse_subpkt( sig->unhashed_data, -2 );
672         }
673     }
674     if( sig->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
675         n = pktlen;
676         sig->d.elg.a = mpi_read(inp, &n, 0 ); pktlen -=n;
677         n = pktlen;
678         sig->d.elg.b = mpi_read(inp, &n, 0 ); pktlen -=n;
679         if( list_mode ) {
680             printf("\telg a: ");
681             mpi_print(stdout, sig->d.elg.a, mpi_print_mode );
682             printf("\n\telg b: ");
683             mpi_print(stdout, sig->d.elg.b, mpi_print_mode );
684             putchar('\n');
685         }
686     }
687     else if( sig->pubkey_algo == PUBKEY_ALGO_DSA ) {
688         n = pktlen;
689         sig->d.dsa.r = mpi_read(inp, &n, 0 ); pktlen -=n;
690         n = pktlen;
691         sig->d.dsa.s = mpi_read(inp, &n, 0 ); pktlen -=n;
692         if( list_mode ) {
693             printf("\tdsa r: ");
694             mpi_print(stdout, sig->d.elg.a, mpi_print_mode );
695             printf("\n\tdsa s: ");
696             mpi_print(stdout, sig->d.elg.b, mpi_print_mode );
697             putchar('\n');
698         }
699     }
700     else if( sig->pubkey_algo == PUBKEY_ALGO_RSA ) {
701         n = pktlen;
702         sig->d.rsa.rsa_integer = mpi_read(inp, &n, 0 ); pktlen -=n;
703         if( list_mode ) {
704             printf("\trsa integer: ");
705             mpi_print(stdout, sig->d.rsa.rsa_integer, mpi_print_mode );
706             putchar('\n');
707         }
708     }
709     else if( list_mode )
710         printf("\tunknown algorithm %d\n", sig->pubkey_algo );
711
712
713   leave:
714     skip_rest(inp, pktlen);
715     return rc;
716 }
717
718
719 static int
720 parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen,
721                                              PKT_onepass_sig *ops )
722 {
723     int version;
724
725     if( pktlen < 13 ) {
726         log_error("packet(%d) too short\n", pkttype);
727         goto leave;
728     }
729     version = iobuf_get_noeof(inp); pktlen--;
730     if( version != 3 ) {
731         log_error("onepass_sig with unknown version %d\n", version);
732         goto leave;
733     }
734     ops->sig_class = iobuf_get_noeof(inp); pktlen--;
735     ops->digest_algo = iobuf_get_noeof(inp); pktlen--;
736     ops->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
737     ops->keyid[0] = read_32(inp); pktlen -= 4;
738     ops->keyid[1] = read_32(inp); pktlen -= 4;
739     ops->last = iobuf_get_noeof(inp); pktlen--;
740     if( list_mode )
741         printf(":onepass_sig packet: keyid %08lX%08lX\n"
742                "\tversion %d, sigclass %02x, digest %d, pubkey %d, last=%d\n",
743                 (ulong)ops->keyid[0], (ulong)ops->keyid[1],
744                 version, ops->sig_class,
745                 ops->digest_algo, ops->pubkey_algo, ops->last );
746
747
748   leave:
749     skip_rest(inp, pktlen);
750     return 0;
751 }
752
753
754
755
756 static int
757 parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
758                               byte *hdr, int hdrlen, PACKET *pkt )
759 {
760     int i, version, algorithm;
761     unsigned n;
762     unsigned long timestamp;
763     unsigned short valid_period;
764     int is_v4=0;
765     int rc=0;
766
767     version = iobuf_get_noeof(inp); pktlen--;
768     if( pkttype == PKT_PUBKEY_SUBCERT && version == '#' ) {
769         /* early versions of G10 use old comments packets; luckily all those
770          * comments are started by a hash */
771         if( list_mode ) {
772             printf(":old comment packet: \"" );
773             for( ; pktlen; pktlen-- ) {
774                 int c;
775                 c = iobuf_get_noeof(inp);
776                 if( c >= ' ' && c <= 'z' )
777                     putchar(c);
778                 else
779                     printf("\\x%02x", c );
780             }
781             printf("\"\n");
782         }
783         skip_rest(inp, pktlen);
784         return 0;
785     }
786     else if( version == 4 )
787         is_v4=1;
788     else if( version != 2 && version != 3 ) {
789         log_error("packet(%d) with unknown version %d\n", pkttype, version);
790         goto leave;
791     }
792
793     if( pktlen < 11 ) {
794         log_error("packet(%d) too short\n", pkttype);
795         goto leave;
796     }
797
798     timestamp = read_32(inp); pktlen -= 4;
799     if( is_v4 )
800         valid_period = 0;
801     else {
802         valid_period = read_16(inp); pktlen -= 2;
803     }
804     algorithm = iobuf_get_noeof(inp); pktlen--;
805     if( list_mode )
806         printf(":%s key packet:\n"
807                "\tversion %d, created %lu, valid for %hu days\n",
808                 pkttype == PKT_PUBLIC_CERT? "public" :
809                 pkttype == PKT_SECRET_CERT? "secret" :
810                 pkttype == PKT_PUBKEY_SUBCERT? "public sub" :
811                 pkttype == PKT_SECKEY_SUBCERT? "secret sub" : "??",
812                 version, timestamp, valid_period );
813     if( pkttype == PKT_SECRET_CERT || pkttype == PKT_SECKEY_SUBCERT )  {
814         pkt->pkt.secret_cert->timestamp = timestamp;
815         pkt->pkt.secret_cert->valid_days = valid_period;
816         pkt->pkt.secret_cert->hdrbytes = hdrlen;
817         pkt->pkt.secret_cert->version = version;
818         pkt->pkt.secret_cert->pubkey_algo = algorithm;
819     }
820     else {
821         pkt->pkt.public_cert->timestamp = timestamp;
822         pkt->pkt.public_cert->valid_days = valid_period;
823         pkt->pkt.public_cert->hdrbytes    = hdrlen;
824         pkt->pkt.public_cert->version     = version;
825         pkt->pkt.public_cert->pubkey_algo = algorithm;
826     }
827
828     if( algorithm == PUBKEY_ALGO_ELGAMAL ) {
829         MPI elg_p, elg_g, elg_y;
830         n = pktlen; elg_p = mpi_read(inp, &n, 0 ); pktlen -=n;
831         n = pktlen; elg_g = mpi_read(inp, &n, 0 ); pktlen -=n;
832         n = pktlen; elg_y = mpi_read(inp, &n, 0 ); pktlen -=n;
833         if( list_mode ) {
834             printf(  "\telg p: ");
835             mpi_print(stdout, elg_p, mpi_print_mode  );
836             printf("\n\telg g: ");
837             mpi_print(stdout, elg_g, mpi_print_mode  );
838             printf("\n\telg y: ");
839             mpi_print(stdout, elg_y, mpi_print_mode  );
840             putchar('\n');
841         }
842         if( pkttype == PKT_PUBLIC_CERT || pkttype == PKT_PUBKEY_SUBCERT ) {
843             pkt->pkt.public_cert->d.elg.p = elg_p;
844             pkt->pkt.public_cert->d.elg.g = elg_g;
845             pkt->pkt.public_cert->d.elg.y = elg_y;
846         }
847         else {
848             PKT_secret_cert *cert = pkt->pkt.secret_cert;
849             byte temp[8];
850
851             pkt->pkt.secret_cert->d.elg.p = elg_p;
852             pkt->pkt.secret_cert->d.elg.g = elg_g;
853             pkt->pkt.secret_cert->d.elg.y = elg_y;
854             cert->protect.algo = iobuf_get_noeof(inp); pktlen--;
855             if( cert->protect.algo ) {
856                 cert->is_protected = 1;
857                 cert->protect.count = 0;
858                 if( cert->protect.algo == 255 ) {
859                     if( pktlen < 3 ) {
860                         rc = G10ERR_INVALID_PACKET;
861                         goto leave;
862                     }
863                     cert->protect.algo = iobuf_get_noeof(inp); pktlen--;
864                     cert->protect.s2k  = iobuf_get_noeof(inp); pktlen--;
865                     cert->protect.hash = iobuf_get_noeof(inp); pktlen--;
866                     switch( cert->protect.s2k ) {
867                       case 1:
868                       case 3:
869                         for(i=0; i < 8 && pktlen; i++, pktlen-- )
870                             temp[i] = iobuf_get_noeof(inp);
871                         memcpy(cert->protect.salt, temp, 8 );
872                         break;
873                     }
874                     switch( cert->protect.s2k ) {
875                       case 0: if( list_mode ) printf(  "\tsimple S2K" );
876                         break;
877                       case 1: if( list_mode ) printf(  "\tsalted S2K" );
878                         break;
879                       case 3: if( list_mode ) printf(  "\titer+salt S2K" );
880                         break;
881                       default:
882                         if( list_mode )
883                             printf(  "\tunknown S2K %d\n",
884                                                 cert->protect.s2k );
885                         rc = G10ERR_INVALID_PACKET;
886                         goto leave;
887                     }
888
889                     if( list_mode ) {
890                         printf(", algo: %d, hash: %d",
891                                          cert->protect.algo,
892                                          cert->protect.hash );
893                         if( cert->protect.s2k == 1
894                             || cert->protect.s2k == 3 ) {
895                             printf(", salt: ");
896                             for(i=0; i < 8; i++ )
897                                 printf("%02x", cert->protect.salt[i]);
898                         }
899                         putchar('\n');
900                     }
901
902                     if( cert->protect.s2k == 3 ) {
903                         if( !pktlen ) {
904                             rc = G10ERR_INVALID_PACKET;
905                             goto leave;
906                         }
907                         cert->protect.count = iobuf_get_noeof(inp);
908                         pktlen--;
909                     }
910
911                 }
912                 else {
913                     if( list_mode )
914                         printf(  "\tprotect algo: %d\n",
915                                                 cert->protect.algo);
916                     /* old version, we don't have a S2K, so we fake one */
917                     cert->protect.s2k = 0;
918                     /* We need this kludge to cope with old GNUPG versions */
919                     cert->protect.hash =
920                          cert->protect.algo == CIPHER_ALGO_BLOWFISH?
921                                       DIGEST_ALGO_RMD160 : DIGEST_ALGO_MD5;
922                 }
923                 if( pktlen < 8 ) {
924                     rc = G10ERR_INVALID_PACKET;
925                     goto leave;
926                 }
927                 for(i=0; i < 8 && pktlen; i++, pktlen-- )
928                     temp[i] = iobuf_get_noeof(inp);
929                 if( list_mode ) {
930                     printf(  "\tprotect IV: ");
931                     for(i=0; i < 8; i++ )
932                         printf(" %02x", temp[i] );
933                     putchar('\n');
934                 }
935                 memcpy(cert->protect.iv, temp, 8 );
936             }
937             else
938                 cert->is_protected = 0;
939             /* It does not make sense to read it into secure memory.
940              * If the user is so careless, not to protect his secret key,
941              * we can assume, that he operates an open system :=(.
942              * So we put the key into secure memory when we unprotect him. */
943             n = pktlen; cert->d.elg.x = mpi_read(inp, &n, 0 ); pktlen -=n;
944
945             cert->csum = read_16(inp); pktlen -= 2;
946             if( list_mode ) {
947                 printf("\t[secret value x is not shown]\n"
948                        "\tchecksum: %04hx\n", cert->csum);
949             }
950           /*log_mpidump("elg p=", cert->d.elg.p );
951             log_mpidump("elg g=", cert->d.elg.g );
952             log_mpidump("elg y=", cert->d.elg.y );
953             log_mpidump("elg x=", cert->d.elg.x ); */
954         }
955     }
956     else if( algorithm == PUBKEY_ALGO_DSA ) {
957         MPI dsa_p, dsa_q, dsa_g, dsa_y;
958         n = pktlen; dsa_p = mpi_read(inp, &n, 0 ); pktlen -=n;
959         n = pktlen; dsa_q = mpi_read(inp, &n, 0 ); pktlen -=n;
960         n = pktlen; dsa_g = mpi_read(inp, &n, 0 ); pktlen -=n;
961         n = pktlen; dsa_y = mpi_read(inp, &n, 0 ); pktlen -=n;
962         if( list_mode ) {
963             printf(  "\tdsa p: ");
964             mpi_print(stdout, dsa_p, mpi_print_mode  );
965             printf("\n\tdsa q: ");
966             mpi_print(stdout, dsa_q, mpi_print_mode  );
967             printf("\n\tdsa g: ");
968             mpi_print(stdout, dsa_g, mpi_print_mode  );
969             printf("\n\tdsa y: ");
970             mpi_print(stdout, dsa_y, mpi_print_mode  );
971             putchar('\n');
972         }
973         if( pkttype == PKT_PUBLIC_CERT || pkttype == PKT_PUBKEY_SUBCERT ) {
974             pkt->pkt.public_cert->d.dsa.p = dsa_p;
975             pkt->pkt.public_cert->d.dsa.q = dsa_q;
976             pkt->pkt.public_cert->d.dsa.g = dsa_g;
977             pkt->pkt.public_cert->d.dsa.y = dsa_y;
978         }
979         else {
980             PKT_secret_cert *cert = pkt->pkt.secret_cert;
981             byte temp[8];
982
983             pkt->pkt.secret_cert->d.dsa.p = dsa_p;
984             pkt->pkt.secret_cert->d.dsa.q = dsa_q;
985             pkt->pkt.secret_cert->d.dsa.g = dsa_g;
986             pkt->pkt.secret_cert->d.dsa.y = dsa_y;
987             cert->protect.algo = iobuf_get_noeof(inp); pktlen--;
988             if( cert->protect.algo ) {
989                 cert->is_protected = 1;
990                 cert->protect.count = 0;
991                 if( cert->protect.algo == 255 ) {
992                     if( pktlen < 3 ) {
993                         rc = G10ERR_INVALID_PACKET;
994                         goto leave;
995                     }
996                     cert->protect.algo = iobuf_get_noeof(inp); pktlen--;
997                     cert->protect.s2k  = iobuf_get_noeof(inp); pktlen--;
998                     cert->protect.hash = iobuf_get_noeof(inp); pktlen--;
999                     switch( cert->protect.s2k ) {
1000                       case 1:
1001                       case 3:
1002                         for(i=0; i < 8 && pktlen; i++, pktlen-- )
1003                             temp[i] = iobuf_get_noeof(inp);
1004                         memcpy(cert->protect.salt, temp, 8 );
1005                         break;
1006                     }
1007                     switch( cert->protect.s2k ) {
1008                       case 0: if( list_mode ) printf(  "\tsimple S2K" );
1009                         break;
1010                       case 1: if( list_mode ) printf(  "\tsalted S2K" );
1011                         break;
1012                       case 3: if( list_mode ) printf(  "\titer+salt S2K" );
1013                         break;
1014                       default:
1015                         if( list_mode )
1016                             printf(  "\tunknown S2K %d\n", cert->protect.s2k );
1017                         rc = G10ERR_INVALID_PACKET;
1018                         goto leave;
1019                     }
1020
1021                     if( list_mode ) {
1022                         printf(", algo: %d, hash: %d",
1023                                          cert->protect.algo,
1024                                          cert->protect.hash );
1025                         if( cert->protect.s2k == 1 || cert->protect.s2k == 3 ){
1026                             printf(", salt: ");
1027                             for(i=0; i < 8; i++ )
1028                                 printf("%02x", cert->protect.salt[i]);
1029                         }
1030                         putchar('\n');
1031                     }
1032
1033                     if( cert->protect.s2k == 3 ) {
1034                         if( !pktlen ) {
1035                             rc = G10ERR_INVALID_PACKET;
1036                             goto leave;
1037                         }
1038                         cert->protect.count = iobuf_get_noeof(inp);
1039                         pktlen--;
1040                     }
1041
1042                 }
1043                 else {
1044                     if( list_mode )
1045                         printf(  "\tprotect algo: %d\n", cert->protect.algo);
1046                     /* old version, we don't have a S2K, so we fake one */
1047                     cert->protect.s2k = 0;
1048                     cert->protect.hash = DIGEST_ALGO_MD5;
1049                 }
1050                 if( pktlen < 8 ) {
1051                     rc = G10ERR_INVALID_PACKET;
1052                     goto leave;
1053                 }
1054                 for(i=0; i < 8 && pktlen; i++, pktlen-- )
1055                     temp[i] = iobuf_get_noeof(inp);
1056                 if( list_mode ) {
1057                     printf(  "\tprotect IV: ");
1058                     for(i=0; i < 8; i++ )
1059                         printf(" %02x", temp[i] );
1060                     putchar('\n');
1061                 }
1062                 memcpy(cert->protect.iv, temp, 8 );
1063             }
1064             else
1065                 cert->is_protected = 0;
1066             /* It does not make sense to read it into secure memory.
1067              * If the user is so careless, not to protect his secret key,
1068              * we can assume, that he operates an open system :=(.
1069              * So we put the key into secure memory when we unprotect him. */
1070             n = pktlen; cert->d.dsa.x = mpi_read(inp, &n, 0 ); pktlen -=n;
1071
1072             cert->csum = read_16(inp); pktlen -= 2;
1073             if( list_mode ) {
1074                 printf("\t[secret value x is not shown]\n"
1075                        "\tchecksum: %04hx\n", cert->csum);
1076             }
1077           /*log_mpidump("dsa p=", cert->d.dsa.p );
1078             log_mpidump("dsa q=", cert->d.dsa.q );
1079             log_mpidump("dsa g=", cert->d.dsa.g );
1080             log_mpidump("dsa y=", cert->d.dsa.y );
1081             log_mpidump("dsa x=", cert->d.dsa.x ); */
1082         }
1083     }
1084     else if( algorithm == PUBKEY_ALGO_RSA ) {
1085         MPI rsa_pub_mod, rsa_pub_exp;
1086
1087         n = pktlen; rsa_pub_mod = mpi_read(inp, &n, 0); pktlen -=n;
1088         n = pktlen; rsa_pub_exp = mpi_read(inp, &n, 0 ); pktlen -=n;
1089         if( list_mode ) {
1090             printf(  "\tpublic modulus  n:  ");
1091             mpi_print(stdout, rsa_pub_mod, mpi_print_mode  );
1092             printf("\n\tpublic exponent e: ");
1093             mpi_print(stdout, rsa_pub_exp, mpi_print_mode  );
1094             putchar('\n');
1095         }
1096         if( pkttype == PKT_PUBLIC_CERT || pkttype == PKT_PUBKEY_SUBCERT ) {
1097             pkt->pkt.public_cert->d.rsa.rsa_n = rsa_pub_mod;
1098             pkt->pkt.public_cert->d.rsa.rsa_e = rsa_pub_exp;
1099         }
1100         else {
1101             PKT_secret_cert *cert = pkt->pkt.secret_cert;
1102             byte temp[8];
1103
1104             pkt->pkt.secret_cert->d.rsa.rsa_n = rsa_pub_mod;
1105             pkt->pkt.secret_cert->d.rsa.rsa_e = rsa_pub_exp;
1106             cert->protect.algo = iobuf_get_noeof(inp); pktlen--;
1107             if( list_mode )
1108                 printf(  "\tprotect algo: %d\n", cert->protect.algo);
1109             if( cert->protect.algo ) {
1110                 cert->is_protected = 1;
1111                 for(i=0; i < 8 && pktlen; i++, pktlen-- )
1112                     temp[i] = iobuf_get_noeof(inp);
1113                 if( list_mode ) {
1114                     printf(  "\tprotect IV: ");
1115                     for(i=0; i < 8; i++ )
1116                         printf(" %02x", temp[i] );
1117                     putchar('\n');
1118                 }
1119                 if( cert->protect.algo == CIPHER_ALGO_BLOWFISH )
1120                     memcpy(cert->protect.iv, temp, 8 );
1121             }
1122             else
1123                 cert->is_protected = 0;
1124             /* (See comments at the code for elg keys) */
1125             n = pktlen; cert->d.rsa.rsa_d = mpi_read(inp, &n, 0 ); pktlen -=n;
1126             n = pktlen; cert->d.rsa.rsa_p = mpi_read(inp, &n, 0 ); pktlen -=n;
1127             n = pktlen; cert->d.rsa.rsa_q = mpi_read(inp, &n, 0 ); pktlen -=n;
1128             n = pktlen; cert->d.rsa.rsa_u = mpi_read(inp, &n, 0 ); pktlen -=n;
1129
1130             cert->csum = read_16(inp); pktlen -= 2;
1131             if( list_mode ) {
1132                 printf("\t[secret values d,p,q,u are not shown]\n"
1133                        "\tchecksum: %04hx\n", cert->csum);
1134             }
1135          /* log_mpidump("rsa n=", cert->d.rsa.rsa_n );
1136             log_mpidump("rsa e=", cert->d.rsa.rsa_e );
1137             log_mpidump("rsa d=", cert->d.rsa.rsa_d );
1138             log_mpidump("rsa p=", cert->d.rsa.rsa_p );
1139             log_mpidump("rsa q=", cert->d.rsa.rsa_q );
1140             log_mpidump("rsa u=", cert->d.rsa.rsa_u ); */
1141         }
1142     }
1143     else if( list_mode )
1144         printf("\tunknown algorithm %d\n", algorithm );
1145
1146
1147   leave:
1148     skip_rest(inp, pktlen);
1149     return rc;
1150 }
1151
1152
1153 static int
1154 parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
1155 {
1156     byte *p;
1157
1158     packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id  + pktlen - 1);
1159     packet->pkt.user_id->len = pktlen;
1160     p = packet->pkt.user_id->name;
1161     for( ; pktlen; pktlen--, p++ )
1162         *p = iobuf_get_noeof(inp);
1163
1164     if( list_mode ) {
1165         int n = packet->pkt.user_id->len;
1166         printf(":user id packet: \"");
1167         for(p=packet->pkt.user_id->name; n; p++, n-- ) {
1168             if( *p >= ' ' && *p <= 'z' )
1169                 putchar(*p);
1170             else
1171                 printf("\\x%02x", *p );
1172         }
1173         printf("\"\n");
1174     }
1175     return 0;
1176 }
1177
1178
1179
1180 static int
1181 parse_comment( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
1182 {
1183     byte *p;
1184
1185     packet->pkt.comment = m_alloc(sizeof *packet->pkt.comment + pktlen - 1);
1186     packet->pkt.comment->len = pktlen;
1187     p = packet->pkt.comment->data;
1188     for( ; pktlen; pktlen--, p++ )
1189         *p = iobuf_get_noeof(inp);
1190
1191     if( list_mode ) {
1192         int n = packet->pkt.comment->len;
1193         printf(":comment packet: \"");
1194         for(p=packet->pkt.comment->data; n; p++, n-- ) {
1195             if( *p >= ' ' && *p <= 'z' )
1196                 putchar(*p);
1197             else
1198                 printf("\\x%02x", *p );
1199         }
1200         printf("\"\n");
1201     }
1202     return 0;
1203 }
1204
1205
1206 static void
1207 parse_trust( IOBUF inp, int pkttype, unsigned long pktlen )
1208 {
1209     int c;
1210
1211     c = iobuf_get_noeof(inp);
1212     if( list_mode )
1213         printf(":trust packet: flag=%02x\n", c );
1214 }
1215
1216
1217 static int
1218 parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
1219 {
1220     int mode, namelen;
1221     PKT_plaintext *pt;
1222     byte *p;
1223     int c, i;
1224
1225     if( pktlen && pktlen < 6 ) {
1226         log_error("packet(%d) too short (%lu)\n", pkttype, (ulong)pktlen);
1227         goto leave;
1228     }
1229     mode = iobuf_get_noeof(inp); if( pktlen ) pktlen--;
1230     namelen = iobuf_get_noeof(inp); if( pktlen ) pktlen--;
1231     pt = pkt->pkt.plaintext = m_alloc(sizeof *pkt->pkt.plaintext + namelen -1);
1232     pt->mode = mode;
1233     pt->namelen = namelen;
1234     if( pktlen ) {
1235         for( i=0; pktlen > 4 && i < namelen; pktlen--, i++ )
1236             pt->name[i] = iobuf_get_noeof(inp);
1237     }
1238     else {
1239         for( i=0; i < namelen; i++ )
1240             if( (c=iobuf_get(inp)) == -1 )
1241                 break;
1242             else
1243                 pt->name[i] = c;
1244     }
1245     pt->timestamp = read_32(inp); if( pktlen) pktlen -= 4;
1246     pt->len = pktlen;
1247     pt->buf = inp;
1248     pktlen = 0;
1249
1250     if( list_mode ) {
1251         printf(":literal data packet:\n"
1252                "\tmode %c, created %lu, name=\"",
1253                     mode >= ' ' && mode <'z'? mode : '?',
1254                     (ulong)pt->timestamp );
1255         for(p=pt->name,i=0; i < namelen; p++, i++ ) {
1256             if( *p >= ' ' && *p <= 'z' )
1257                 putchar(*p);
1258             else
1259                 printf("\\x%02x", *p );
1260         }
1261         printf("\",\n\traw data: %lu bytes\n", (ulong)pt->len );
1262     }
1263
1264   leave:
1265     return 0;
1266 }
1267
1268
1269 static int
1270 parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
1271 {
1272     PKT_compressed *zd;
1273
1274     /* pktlen is here 0, but data follows
1275      * (this should be the last object in a file or
1276      *  the compress algorithm should know the length)
1277      */
1278     zd = pkt->pkt.compressed =  m_alloc(sizeof *pkt->pkt.compressed );
1279     zd->len = 0; /* not yet used */
1280     zd->algorithm = iobuf_get_noeof(inp);
1281     zd->buf = inp;
1282     if( list_mode )
1283         printf(":compressed packet: algo=%d\n", zd->algorithm);
1284     return 0;
1285 }
1286
1287
1288 static int
1289 parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
1290 {
1291     PKT_encrypted *ed;
1292
1293     ed = pkt->pkt.encrypted =  m_alloc(sizeof *pkt->pkt.encrypted );
1294     ed->len = pktlen;
1295     ed->buf = NULL;
1296     if( pktlen && pktlen < 10 ) {
1297         log_error("packet(%d) too short\n", pkttype);
1298         skip_rest(inp, pktlen);
1299         goto leave;
1300     }
1301     if( list_mode )
1302         if( pktlen )
1303             printf(":encrypted data packet:\n\tlength: %lu\n", pktlen-10);
1304         else
1305             printf(":encrypted data packet:\n\tlength: unknown\n");
1306
1307     ed->buf = inp;
1308     pktlen = 0;
1309
1310   leave:
1311     return 0;
1312 }
1313
1314
1315