compress stuff implemented
[gnupg.git] / g10 / parse-packet.c
1 /* parse-packet.c  - read packets
2  *      Copyright (c) 1997 by Werner Koch (dd9jn)
3  *
4  * This file is part of G10.
5  *
6  * G10 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  * G10 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 void skip_packet( IOBUF inp, int pkttype, unsigned long pktlen );
40 static void skip_rest( IOBUF inp, unsigned long pktlen );
41 static int  parse_publickey( IOBUF inp, int pkttype, unsigned long pktlen,
42                                                              PACKET *packet );
43 static int  parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
44                                                          PKT_signature *sig );
45 static int  parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
46                                       byte *hdr, int hdrlen, PACKET *packet );
47 static int  parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen,
48                                                            PACKET *packet );
49 static void parse_comment( IOBUF inp, int pkttype, unsigned long pktlen );
50 static void parse_trust( IOBUF inp, int pkttype, unsigned long pktlen );
51 static int  parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen,
52                                                                 PACKET *pkt );
53 static int  parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen,
54                                                            PACKET *packet );
55 static int  parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
56                                                            PACKET *packet );
57
58 static u16
59 checksum( byte *p )
60 {
61     u16 n, a;
62
63     n = *p++ << 8;
64     n |= *p++;
65     for(a=0; n; n-- )
66         a += *p++;
67     return a;
68 }
69
70 static unsigned short
71 read_16(IOBUF inp)
72 {
73     unsigned short a;
74     a = iobuf_get_noeof(inp) << 8;
75     a |= iobuf_get_noeof(inp);
76     return a;
77 }
78
79 static unsigned long
80 read_32(IOBUF inp)
81 {
82     unsigned long a;
83     a =  iobuf_get_noeof(inp) << 24;
84     a |= iobuf_get_noeof(inp) << 16;
85     a |= iobuf_get_noeof(inp) << 8;
86     a |= iobuf_get_noeof(inp);
87     return a;
88 }
89
90 int
91 set_packet_list_mode( int mode )
92 {
93     int old = list_mode;
94     list_mode = mode;
95     mpi_print_mode = DBG_MPI;
96     return old;
97 }
98
99 /****************
100  * Parse a Packet and return it in packet
101  * Returns: 0 := valid packet in pkt
102  *         -1 := no more packets
103  *         >0 := error
104  * Note: The function may return an error and a partly valid packet;
105  * caller must free this packet.
106  */
107 int
108 parse_packet( IOBUF inp, PACKET *pkt )
109 {
110     int rc, ctb, pkttype, lenbytes;
111     unsigned long pktlen;
112     byte hdr[5];
113     int hdrlen;
114
115     assert( !pkt->pkt.generic );
116     if( (ctb = iobuf_get(inp)) == -1 )
117         return -1;
118     hdrlen=0;
119     hdr[hdrlen++] = ctb;
120     if( !(ctb & 0x80) ) {
121         log_error("invalid packet at '%s'\n", iobuf_where(inp) );
122         return G10ERR_INVALID_PACKET;
123     }
124     /* we handle the pgp 3 extensions here, so that we can skip such packets*/
125     pkttype =  ctb & 0x40 ? (ctb & 0x3f) : ((ctb>>2)&0xf);
126     lenbytes = (ctb & 0x40) || ((ctb&3)==3)? 0 : (1<<(ctb & 3));
127     pktlen = 0;
128     if( !lenbytes ) {
129         pktlen = 0; /* don't know the value */
130         if( pkttype != PKT_COMPR_DATA )
131             iobuf_set_block_mode(inp, 1);
132     }
133     else {
134         for( ; lenbytes; lenbytes-- ) {
135             pktlen <<= 8;
136             pktlen |= hdr[hdrlen++] = iobuf_get_noeof(inp);
137         }
138     }
139
140     if( DBG_PACKET )
141         log_debug("parse_packet(iob=%d): type=%d length=%lu\n",
142                                             iobuf_id(inp), pkttype, pktlen );
143     pkt->pkttype = pkttype;
144     rc = G10ERR_UNKNOWN_PACKET; /* default to no error */
145     switch( pkttype ) {
146       case PKT_PUBKEY_CERT:
147         pkt->pkt.pubkey_cert = m_alloc_clear(sizeof *pkt->pkt.pubkey_cert );
148         rc = parse_certificate(inp, pkttype, pktlen, hdr, hdrlen, pkt );
149         break;
150       case PKT_SECKEY_CERT:
151         pkt->pkt.seckey_cert = m_alloc_clear(sizeof *pkt->pkt.seckey_cert );
152         rc = parse_certificate(inp, pkttype, pktlen, hdr, hdrlen, pkt );
153         break;
154       case PKT_PUBKEY_ENC:
155         rc = parse_publickey(inp, pkttype, pktlen, pkt );
156         break;
157       case PKT_SIGNATURE:
158         pkt->pkt.signature = m_alloc_clear(sizeof *pkt->pkt.signature );
159         rc = parse_signature(inp, pkttype, pktlen, pkt->pkt.signature );
160         m_check(pkt->pkt.signature);
161         break;
162       case PKT_USER_ID:
163         rc = parse_user_id(inp, pkttype, pktlen, pkt );
164         break;
165       case PKT_COMMENT:
166         parse_comment(inp, pkttype, pktlen);
167         break;
168       case PKT_RING_TRUST:
169         parse_trust(inp, pkttype, pktlen);
170         break;
171       case PKT_PLAINTEXT:
172         rc = parse_plaintext(inp, pkttype, pktlen, pkt );
173         break;
174       case PKT_COMPR_DATA:
175         rc = parse_compressed(inp, pkttype, pktlen, pkt );
176         break;
177       case PKT_ENCR_DATA:
178         rc = parse_encrypted(inp, pkttype, pktlen, pkt );
179         break;
180       default:
181         skip_packet(inp, pkttype, pktlen);
182         break;
183     }
184
185     return rc;
186 }
187
188
189 static void
190 skip_packet( IOBUF inp, int pkttype, unsigned long pktlen )
191 {
192     if( list_mode )
193         printf(":unknown packet: type %2d, length %lu\n", pkttype, pktlen );
194     skip_rest(inp,pktlen);
195 }
196
197 static void
198 skip_rest( IOBUF inp, unsigned long pktlen )
199 {
200     if( iobuf_in_block_mode(inp) ) {
201         while( iobuf_get(inp) != -1 )
202                 ;
203     }
204     else {
205         for( ; pktlen; pktlen-- )
206             iobuf_get(inp);
207     }
208 }
209
210
211 static int
212 parse_publickey( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
213 {
214     int version;
215     unsigned n;
216     PKT_pubkey_enc *k;
217
218     k = packet->pkt.pubkey_enc = m_alloc(sizeof *packet->pkt.pubkey_enc );
219     if( pktlen < 12 ) {
220         log_error("packet(%d) too short\n", pkttype);
221         goto leave;
222     }
223     version = iobuf_get_noeof(inp); pktlen--;
224     if( version != 2 && version != 3 ) {
225         log_error("packet(%d) with unknown version %d\n", pkttype, version);
226         goto leave;
227     }
228     k->keyid[0] = read_32(inp); pktlen -= 4;
229     k->keyid[1] = read_32(inp); pktlen -= 4;
230     k->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
231     if( list_mode )
232         printf(":public key packet: keyid %08lX%08lX\n",
233                                         k->keyid[0], k->keyid[1]);
234     if( k->pubkey_algo == PUBKEY_ALGO_RSA ) {
235         n = pktlen;
236         k->d.rsa.rsa_integer = mpi_decode(inp, &n ); pktlen -=n;
237         if( list_mode ) {
238             printf("\trsa integer: ");
239             mpi_print(stdout, k->d.rsa.rsa_integer, mpi_print_mode );
240             putchar('\n');
241         }
242     }
243     else if( list_mode )
244         printf("\tunknown algorithm %d\n", k->pubkey_algo );
245
246
247   leave:
248     skip_rest(inp, pktlen);
249     return 0;
250 }
251
252
253 static int
254 parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
255                                           PKT_signature *sig )
256 {
257     int version, md5_len;
258     unsigned n;
259
260     if( pktlen < 16 ) {
261         log_error("packet(%d) too short\n", pkttype);
262         goto leave;
263     }
264     version = iobuf_get_noeof(inp); pktlen--;
265     if( version != 2 && version != 3 ) {
266         log_error("packet(%d) with unknown version %d\n", pkttype, version);
267         goto leave;
268     }
269     m_check(sig);
270     md5_len = iobuf_get_noeof(inp); pktlen--;
271     sig->sig_class = iobuf_get_noeof(inp); pktlen--;
272     sig->timestamp = read_32(inp); pktlen -= 4;
273     sig->keyid[0] = read_32(inp); pktlen -= 4;
274     sig->keyid[1] = read_32(inp); pktlen -= 4;
275     sig->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
276     m_check(sig);
277     if( list_mode )
278         printf(":signature packet: keyid %08lX%08lX\n"
279                "\tversion %d, created %lu, md5len %d, sigclass %02x\n",
280                 sig->keyid[0], sig->keyid[1],
281                 version, sig->timestamp, md5_len, sig->sig_class );
282     if( sig->pubkey_algo == PUBKEY_ALGO_RSA ) {
283         if( pktlen < 5 ) {
284             log_error("packet(%d) too short\n", pkttype);
285             goto leave;
286         }
287     m_check(sig);
288         sig->d.rsa.digest_algo = iobuf_get_noeof(inp); pktlen--;
289         sig->d.rsa.digest_start[0] = iobuf_get_noeof(inp); pktlen--;
290         sig->d.rsa.digest_start[1] = iobuf_get_noeof(inp); pktlen--;
291     m_check(sig);
292         n = pktlen;
293         sig->d.rsa.rsa_integer = mpi_decode(inp, &n ); pktlen -=n;
294         if( list_mode ) {
295             printf("\tdigest algo %d, begin of digest %02x %02x\n",
296                     sig->d.rsa.digest_algo,
297                     sig->d.rsa.digest_start[0], sig->d.rsa.digest_start[1] );
298             printf("\trsa integer: ");
299             mpi_print(stdout, sig->d.rsa.rsa_integer, mpi_print_mode );
300             putchar('\n');
301         }
302     }
303     else if( list_mode )
304         printf("\tunknown algorithm %d\n", sig->pubkey_algo );
305     m_check(sig);
306
307
308   leave:
309     skip_rest(inp, pktlen);
310     return 0;
311 }
312
313
314
315
316 static int
317 parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
318                               byte *hdr, int hdrlen, PACKET *pkt )
319 {
320     int i, version, algorithm;
321     unsigned n;
322     unsigned long timestamp;
323     unsigned short valid_period;
324     MPI rsa_pub_mod, rsa_pub_exp;
325
326     if( pkttype == PKT_PUBKEY_CERT ) {
327         pkt->pkt.pubkey_cert->mfx.md5 = md5_open(0);
328         pkt->pkt.pubkey_cert->mfx.rmd160 = rmd160_open(0);
329         pkt->pkt.pubkey_cert->mfx.maxbuf_size = 1;
330         md5_write(pkt->pkt.pubkey_cert->mfx.md5, hdr, hdrlen);
331         rmd160_write(pkt->pkt.pubkey_cert->mfx.rmd160, hdr, hdrlen);
332         iobuf_push_filter( inp, md_filter, &pkt->pkt.pubkey_cert->mfx );
333     }
334
335     if( pktlen < 12 ) {
336         log_error("packet(%d) too short\n", pkttype);
337         goto leave;
338     }
339     version = iobuf_get_noeof(inp); pktlen--;
340     if( version != 2 && version != 3 ) {
341         log_error("packet(%d) with unknown version %d\n", pkttype, version);
342         goto leave;
343     }
344
345     timestamp = read_32(inp); pktlen -= 4;
346     valid_period = read_16(inp); pktlen -= 2;
347     algorithm = iobuf_get_noeof(inp); pktlen--;
348     if( list_mode )
349         printf(":%s key certification packet:\n"
350                "\tversion %d, created %lu, valid for %hu days\n",
351                 pkttype == PKT_PUBKEY_CERT? "public": "secret",
352                 version, timestamp, valid_period );
353     if( pkttype == PKT_SECKEY_CERT )  {
354         pkt->pkt.seckey_cert->timestamp = timestamp;
355         pkt->pkt.seckey_cert->valid_days = valid_period;
356         pkt->pkt.seckey_cert->pubkey_algo = algorithm;
357     }
358     else {
359         pkt->pkt.pubkey_cert->timestamp = timestamp;
360         pkt->pkt.pubkey_cert->valid_days = valid_period;
361         pkt->pkt.pubkey_cert->pubkey_algo = algorithm;
362     }
363
364     if( algorithm == PUBKEY_ALGO_RSA ) {
365         n = pktlen; rsa_pub_mod = mpi_decode(inp, &n ); pktlen -=n;
366         n = pktlen; rsa_pub_exp = mpi_decode(inp, &n ); pktlen -=n;
367         if( list_mode ) {
368             printf(  "\tpublic modulus  n:  ");
369             mpi_print(stdout, rsa_pub_mod, mpi_print_mode  );
370             printf("\n\tpublic exponent e: ");
371             mpi_print(stdout, rsa_pub_exp, mpi_print_mode  );
372             putchar('\n');
373         }
374         if( pkttype == PKT_PUBKEY_CERT ) {
375             pkt->pkt.pubkey_cert->d.rsa.rsa_n = rsa_pub_mod;
376             pkt->pkt.pubkey_cert->d.rsa.rsa_e = rsa_pub_exp;
377         }
378         else {
379             PKT_seckey_cert *cert = pkt->pkt.seckey_cert;
380             byte temp[8];
381             byte *mpibuf;
382
383             pkt->pkt.seckey_cert->d.rsa.rsa_n = rsa_pub_mod;
384             pkt->pkt.seckey_cert->d.rsa.rsa_e = rsa_pub_exp;
385             cert->d.rsa.protect_algo = iobuf_get_noeof(inp); pktlen--;
386             if( list_mode )
387                 printf(  "\tprotect algo: %d\n", cert->d.rsa.protect_algo);
388             if( cert->d.rsa.protect_algo ) {
389                 cert->d.rsa.is_protected = 1;
390                 for(i=0; i < 8 && pktlen; i++, pktlen-- )
391                     temp[i] = iobuf_get_noeof(inp);
392                 if( list_mode ) {
393                     printf(  "\tprotect IV: ");
394                     for(i=0; i < 8; i++ )
395                         printf(" %02x", temp[i] );
396                     putchar('\n');
397                 }
398                 if( cert->d.rsa.protect_algo == CIPHER_ALGO_IDEA )
399                     memcpy(cert->d.rsa.protect.idea.iv, temp, 8 );
400                 else if( cert->d.rsa.protect_algo == CIPHER_ALGO_BLOWFISH )
401                     memcpy(cert->d.rsa.protect.blowfish.iv, temp, 8 );
402             }
403             else
404                 cert->d.rsa.is_protected = 0;
405
406             n = pktlen; mpibuf = mpi_read(inp, &n ); pktlen -=n; assert(n>=2);
407             cert->d.rsa.rsa_d = (MPI)mpibuf;
408
409             n = pktlen; mpibuf = mpi_read(inp, &n ); pktlen -=n; assert(n>=2);
410             cert->d.rsa.rsa_p = (MPI)mpibuf;
411
412             n = pktlen; mpibuf = mpi_read(inp, &n ); pktlen -=n; assert(n>=2);
413             cert->d.rsa.rsa_q = (MPI)mpibuf;
414
415             n = pktlen; mpibuf = mpi_read(inp, &n ); pktlen -=n; assert(n>=2);
416             cert->d.rsa.rsa_u = (MPI)mpibuf;
417
418             cert->d.rsa.csum = read_16(inp); pktlen -= 2;
419             cert->d.rsa.calc_csum = 0;
420             if( list_mode ) {
421                 printf("\t[secret values d,p,q,u are not shown]\n"
422                        "\tchecksum: %04hx\n", cert->d.rsa.csum);
423             }
424             if( !cert->d.rsa.is_protected ) { /* convert buffer to MPIs */
425               #define X(a) do {                                         \
426                     mpibuf = (byte*)cert->d.rsa.rsa_##a;                \
427                     cert->d.rsa.calc_csum += checksum( mpibuf );        \
428                     cert->d.rsa.rsa_##a = mpi_decode_buffer( mpibuf );  \
429                     m_free( mpibuf );                                   \
430                 } while(0)
431                 X(d);
432                 X(p);
433                 X(q);
434                 X(u);
435               #undef X
436              /* log_mpidump("rsa n=", cert->d.rsa.rsa_n );
437                 log_mpidump("rsa e=", cert->d.rsa.rsa_e );
438                 log_mpidump("rsa d=", cert->d.rsa.rsa_d );
439                 log_mpidump("rsa p=", cert->d.rsa.rsa_p );
440                 log_mpidump("rsa q=", cert->d.rsa.rsa_q );
441                 log_mpidump("rsa u=", cert->d.rsa.rsa_u ); */
442             }
443         }
444     }
445     else if( list_mode )
446         printf("\tunknown algorithm %d\n", algorithm );
447
448
449   leave:
450     if( pkttype == PKT_PUBKEY_CERT )
451         iobuf_pop_filter( inp, md_filter, &pkt->pkt.pubkey_cert->mfx );
452     skip_rest(inp, pktlen);
453     return 0;
454 }
455
456
457 static int
458 parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
459 {
460     byte *p;
461
462     packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id  + pktlen - 1);
463     packet->pkt.user_id->len = pktlen;
464     p = packet->pkt.user_id->name;
465     for( ; pktlen; pktlen--, p++ )
466         *p = iobuf_get_noeof(inp);
467
468     if( list_mode ) {
469         int n = packet->pkt.user_id->len;
470         printf(":user id packet: \"");
471         for(p=packet->pkt.user_id->name; n; p++, n-- ) {
472             if( *p >= ' ' && *p <= 'z' )
473                 putchar(*p);
474             else
475                 printf("\\x%02x", *p );
476         }
477         printf("\"\n");
478     }
479     return 0;
480 }
481
482 static void
483 parse_comment( IOBUF inp, int pkttype, unsigned long pktlen )
484 {
485     if( list_mode ) {
486         printf(":comment packet: \"" );
487         for( ; pktlen; pktlen-- ) {
488             int c;
489             c = iobuf_get_noeof(inp);
490             if( c >= ' ' && c <= 'z' )
491                 putchar(c);
492             else
493                 printf("\\x%02x", c );
494         }
495         printf("\"\n");
496     }
497     skip_rest(inp, pktlen);
498 }
499
500
501 static void
502 parse_trust( IOBUF inp, int pkttype, unsigned long pktlen )
503 {
504     int c;
505
506     c = iobuf_get_noeof(inp);
507     if( list_mode )
508         printf(":trust packet: flag=%02x\n", c );
509   #if 0 /* fixme: depending on the context we have different interpretations*/
510     if( prev_packet_is_a_key_packet ) {
511         int ot = c & 7;   /* ownertrust bits (for the key owner) */
512
513             !ot ? "undefined" :
514         ot == 1 ? "unknown"   : /* we don't know the owner of this key */
515         ot == 2 ? "no"        : /* usually we do not trust this key owner */
516                                 /* to sign other keys */
517         ot == 5 ? "usually"   : /* usually we trust this key owner to sign */
518         ot == 6 ? "always"    : /* always trust this key owner to sign */
519         ot == 7 ? "ultimate"  : /* also present in the secret keyring */
520               ""                /* reserved value */
521         if( c & (1<<5) )
522             "key is disabled"
523         if( c & (1<<7) )
524             "buckstop"
525     else if( prev_packet_is_user_is_packet ) {
526             int kl = c & 3; /* keylegit bits */
527         0 = "unknown, undefined, or uninitialized trust"
528         1 = "we do not trust this key's ownership"
529         2 = "we have marginal confidence of this key's ownership"
530         3 = "we completely trust this key's ownership."
531          /* This one (3) requires either:
532           * - 1 ultimately trusted signature (SIGTRUST=7)
533           * - COMPLETES_NEEDED completely trusted signatures (SIGTRUST=6)
534           * - MARGINALS_NEEDED marginally trusted signatures (SIGTRUST=5)
535           */
536         if( c & 0x80 )
537             "warnonly"
538     else if( prev_packet_is_a_signature ) {
539          Bits 0-2 - SIGTRUST bits - Trust bits for this signature.  Value is
540                     copied directly from OWNERTRUST bits of signer:
541               000 - undefined, or uninitialized trust.
542               001 - unknown
543               010 - We do not trust this signature.
544               011 - reserved
545               100 - reserved
546               101 - We reasonably trust this signature.
547               110 - We completely trust this signature.
548               111 - ultimately trusted signature (from the owner of the ring)
549           Bit 6 - CHECKED bit - This means that the key checking pass (pgp -kc,
550                   also invoked automatically whenever keys are added to the
551                   keyring) has tested this signature and found it good.  If
552                   this bit is not set, the maintenance pass considers this
553                   signature untrustworthy.
554           Bit 7 - CONTIG bit - Means this signature leads up a contiguous trusted
555                   certification path all the way back to the ultimately-
556                   trusted keyring owner, where the buck stops.  This bit is derived
557                   from other trust packets.  It is currently not used for anything
558                   in PGP.
559     }
560   #endif
561 }
562
563
564 static int
565 parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
566 {
567     int mode, namelen;
568     PKT_plaintext *pt;
569     byte *p;
570     int c, i;
571
572     if( pktlen && pktlen < 6 ) {
573         log_error("packet(%d) too short (%lu)\n", pkttype, (ulong)pktlen);
574         goto leave;
575     }
576     mode = iobuf_get_noeof(inp); if( pktlen ) pktlen--;
577     namelen = iobuf_get_noeof(inp); if( pktlen ) pktlen--;
578     pt = pkt->pkt.plaintext = m_alloc(sizeof *pkt->pkt.plaintext + namelen -1);
579     pt->mode = mode;
580     pt->namelen = namelen;
581     if( pktlen ) {
582         for( i=0; pktlen > 4 && i < namelen; pktlen--, i++ )
583             pt->name[i] = iobuf_get_noeof(inp);
584     }
585     else {
586         for( i=0; i < namelen; i++ )
587             if( (c=iobuf_get(inp)) == -1 )
588                 break;
589             else
590                 pt->name[i] = c;
591     }
592     pt->timestamp = read_32(inp); if( pktlen) pktlen -= 4;
593     pt->len = pktlen;
594     pt->buf = inp;
595     pktlen = 0;
596
597     if( list_mode ) {
598         printf(":literal data packet:\n"
599                "\tmode %c, created %lu, name=\"",
600                     mode >= ' ' && mode <'z'? mode : '?',
601                     pt->timestamp );
602         for(p=pt->name,i=0; i < namelen; p++, i++ ) {
603             if( *p >= ' ' && *p <= 'z' )
604                 putchar(*p);
605             else
606                 printf("\\x%02x", *p );
607         }
608         printf("\",\n\traw data: %lu bytes\n", pt->len );
609     }
610
611   leave:
612     return 0;
613 }
614
615
616 static int
617 parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
618 {
619     PKT_compressed *zd;
620     int algorithm;
621
622     /* pktlen is here 0, but data follows
623      * (this should be the last object in a file or
624      *  the compress algorithm should know the length)
625      */
626     zd = pkt->pkt.compressed =  m_alloc(sizeof *pkt->pkt.compressed );
627     zd->len = 0; /* not yet used */
628     zd->algorithm = iobuf_get_noeof(inp);
629     zd->buf = inp;
630     if( list_mode )
631         printf(":compressed packet: algo=%d\n", zd->algorithm);
632     return 0;
633 }
634
635
636 static int
637 parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
638 {
639     PKT_encr_data *ed;
640
641     ed = pkt->pkt.encr_data =  m_alloc(sizeof *pkt->pkt.encr_data );
642     ed->len = pktlen;
643     ed->buf = NULL;
644     if( pktlen && pktlen < 10 ) {
645         log_error("packet(%d) too short\n", pkttype);
646         skip_rest(inp, pktlen);
647         goto leave;
648     }
649     if( list_mode )
650         if( pktlen )
651             printf(":encrypted data packet:\n\tlength: %lu\n", pktlen-10);
652         else
653             printf(":encrypted data packet:\n\tlength: unknown\n");
654
655     ed->buf = inp;
656     pktlen = 0;
657
658   leave:
659     return 0;
660 }
661
662