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