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