4281ef1737511d604d9394e346f7d2db8b1249f7
[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     unsigned n;
429     PKT_pubkey_enc *k;
430
431     k = packet->pkt.pubkey_enc = m_alloc(sizeof *packet->pkt.pubkey_enc );
432     if( pktlen < 12 ) {
433         log_error("packet(%d) too short\n", pkttype);
434         goto leave;
435     }
436     k->version = iobuf_get_noeof(inp); pktlen--;
437     if( k->version != 2 && k->version != 3 ) {
438         log_error("packet(%d) with unknown version %d\n", pkttype, k->version);
439         goto leave;
440     }
441     k->keyid[0] = read_32(inp); pktlen -= 4;
442     k->keyid[1] = read_32(inp); pktlen -= 4;
443     k->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
444     if( list_mode )
445         printf(":public key encoded packet: version %d, keyid %08lX%08lX\n",
446                             k->version, (ulong)k->keyid[0], (ulong)k->keyid[1]);
447     if( k->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
448         n = pktlen;
449         k->d.elg.a = mpi_read(inp, &n, 0); pktlen -=n;
450         n = pktlen;
451         k->d.elg.b = mpi_read(inp, &n, 0 ); pktlen -=n;
452         if( list_mode ) {
453             printf("\telg a: ");
454             mpi_print(stdout, k->d.elg.a, mpi_print_mode );
455             printf("\n\telg b: ");
456             mpi_print(stdout, k->d.elg.b, mpi_print_mode );
457             putchar('\n');
458         }
459     }
460     else if( k->pubkey_algo == PUBKEY_ALGO_RSA ) {
461         n = pktlen;
462         k->d.rsa.rsa_integer = mpi_read(inp, &n, 0 ); pktlen -=n;
463         if( list_mode ) {
464             printf("\trsa integer: ");
465             mpi_print(stdout, k->d.rsa.rsa_integer, mpi_print_mode );
466             putchar('\n');
467         }
468     }
469     else if( list_mode )
470         printf("\tunknown algorithm %d\n", k->pubkey_algo );
471
472
473   leave:
474     skip_rest(inp, pktlen);
475     return 0;
476 }
477
478
479 static const byte *
480 parse_subpkt( const byte *buffer, int reqtype )
481 {
482     int buflen = (*buffer << 8) | buffer[1];
483     int type;
484     int critical;
485     size_t n;
486
487     buffer += 2;
488     for(;;) {
489         if( !buflen )
490             return NULL; /* end of packets; not found */
491         n = *buffer++; buflen--;
492         if( n >= 192 ) {
493             if( buflen < 2 )
494                 goto too_short;
495             n = (( n - 192 ) << 8) + *buffer + 192;
496             buflen--;
497         }
498         if( buflen < n )
499             goto too_short;
500         type = *buffer;
501         if( type & 0x80 ) {
502             type &= 0x7f;
503             critical = 1;
504         }
505         else
506             critical = 0;
507         if( reqtype < 0 ) { /* list packets */
508             printf("\t%ssubpacket %d of length %u (%s)\n",
509                     reqtype == -1 ? "hashed ":"", type, n,
510                     type == 2 ? "signature creation time"
511                   : type == 3 ? "signature expiration time"
512                   : type == 4 ? "exportable"
513                   : type == 5 ? "trust signature"
514                   : type == 6 ? "regular expression"
515                   : type == 7 ? "revocable"
516                   : type == 9 ? "key expiration time"
517                   : type ==10 ? "additional recipient request"
518                   : type ==11 ? "preferred symmetric algorithms"
519                   : type ==12 ? "revocation key"
520                   : type ==16 ? "issuer key ID"
521                   : type ==20 ? "notation data"
522                   : type ==21 ? "preferred hash algorithms"
523                   : type ==22 ? "preferred compression algorithms"
524                   : type ==23 ? "key server preferences"
525                   : type ==24 ? "preferred key server"
526                               : "?");
527         }
528         else if( type == reqtype )
529             break; /* found */
530         buffer += n; buflen -=n;
531     }
532     buffer++;
533     n--;
534     if( n > buflen )
535         goto too_short;
536     switch( type ) {
537       case 2: /* signature creation time */
538         if( n < 4 )
539             break;
540         return buffer;
541       case 16:/* issuer key ID */
542         if( n < 8 )
543             break;
544         return buffer;
545       case 3: /* signature expiration time */
546       case 4: /* exportable */
547       case 5: /* trust signature */
548       case 6: /* regular expression */
549       case 7: /* revocable */
550       case 9: /* key expiration time */
551       case 10:/* additional recipient request */
552       case 11:/* preferred symmetric algorithms */
553       case 12:/* revocation key */
554       case 20:/* notation data */
555       case 21:/* preferred hash algorithms */
556       case 22:/* preferred compression algorithms */
557       case 23:/* key server preferences */
558       case 24:/* preferred key server */
559       default: BUG(); /* not yet needed */
560     }
561     log_error("subpacket of type %d too short\n", type);
562     return NULL;
563
564   too_short:
565     log_error("buffer shorter than subpacket\n");
566     return NULL;
567 }
568
569
570 static int
571 parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
572                                           PKT_signature *sig )
573 {
574     int md5_len=0;
575     unsigned n;
576     int is_v4=0;
577     int rc=0;
578
579     if( pktlen < 16 ) {
580         log_error("packet(%d) too short\n", pkttype);
581         goto leave;
582     }
583     sig->version = iobuf_get_noeof(inp); pktlen--;
584     if( sig->version == 4 )
585         is_v4=1;
586     else if( sig->version != 2 && sig->version != 3 ) {
587         log_error("packet(%d) with unknown version %d\n", pkttype, sig->version);
588         goto leave;
589     }
590
591     if( !is_v4 ) {
592         md5_len = iobuf_get_noeof(inp); pktlen--;
593     }
594     sig->sig_class = iobuf_get_noeof(inp); pktlen--;
595     if( !is_v4 ) {
596         sig->timestamp = read_32(inp); pktlen -= 4;
597         sig->keyid[0] = read_32(inp); pktlen -= 4;
598         sig->keyid[1] = read_32(inp); pktlen -= 4;
599     }
600     sig->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
601     sig->digest_algo = iobuf_get_noeof(inp); pktlen--;
602     if( is_v4 ) { /* read subpackets */
603         n = read_16(inp); pktlen -= 2; /* length of hashed data */
604         if( n > 10000 ) {
605             log_error("signature packet: hashed data too long\n");
606             rc = G10ERR_INVALID_PACKET;
607             goto leave;
608         }
609         if( n ) {
610             sig->hashed_data = m_alloc( n + 2 );
611             sig->hashed_data[0] = n << 8;
612             sig->hashed_data[1] = n;
613             if( iobuf_read(inp, sig->hashed_data+2, n ) != n ) {
614                 log_error("premature eof while reading hashed signature data\n");
615                 rc = -1;
616                 goto leave;
617             }
618             pktlen -= n;
619         }
620         n = read_16(inp); pktlen -= 2; /* length of unhashed data */
621         if( n > 10000 ) {
622             log_error("signature packet: unhashed data too long\n");
623             rc = G10ERR_INVALID_PACKET;
624             goto leave;
625         }
626         if( n ) {
627             sig->unhashed_data = m_alloc( n + 2 );
628             sig->unhashed_data[0] = n << 8;
629             sig->unhashed_data[1] = n;
630             if( iobuf_read(inp, sig->unhashed_data+2, n ) != n ) {
631                 log_error("premature eof while reading unhashed signature data\n");
632                 rc = -1;
633                 goto leave;
634             }
635             pktlen -= n;
636         }
637     }
638
639     if( pktlen < 5 ) { /* sanity check */
640         log_error("packet(%d) too short\n", pkttype);
641         rc = G10ERR_INVALID_PACKET;
642         goto leave;
643     }
644
645     sig->digest_start[0] = iobuf_get_noeof(inp); pktlen--;
646     sig->digest_start[1] = iobuf_get_noeof(inp); pktlen--;
647
648     if( is_v4 ) { /*extract required informations */
649         const byte *p;
650         p = parse_subpkt( sig->hashed_data, 2 );
651         if( !p )
652             log_error("signature packet without timestamp\n");
653         else
654             sig->timestamp = buffer_to_u32(p);
655         p = parse_subpkt( sig->unhashed_data, 16 );
656         if( !p )
657             log_error("signature packet without keyid\n");
658         else {
659             sig->keyid[0] = buffer_to_u32(p);
660             sig->keyid[1] = buffer_to_u32(p+4);
661         }
662     }
663
664     if( list_mode ) {
665         printf(":signature packet: keyid %08lX%08lX\n"
666                "\tversion %d, created %lu, md5len %d, sigclass %02x\n"
667                "\tdigest algo %d, begin of digest %02x %02x\n",
668                 (ulong)sig->keyid[0], (ulong)sig->keyid[1],
669                 sig->version, (ulong)sig->timestamp, md5_len, sig->sig_class,
670                 sig->digest_algo,
671                 sig->digest_start[0], sig->digest_start[1] );
672         if( is_v4 ) {
673             parse_subpkt( sig->hashed_data, -1 );
674             parse_subpkt( sig->unhashed_data, -2 );
675         }
676     }
677     if( sig->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
678         n = pktlen;
679         sig->d.elg.a = mpi_read(inp, &n, 0 ); pktlen -=n;
680         n = pktlen;
681         sig->d.elg.b = mpi_read(inp, &n, 0 ); pktlen -=n;
682         if( list_mode ) {
683             printf("\telg a: ");
684             mpi_print(stdout, sig->d.elg.a, mpi_print_mode );
685             printf("\n\telg b: ");
686             mpi_print(stdout, sig->d.elg.b, mpi_print_mode );
687             putchar('\n');
688         }
689     }
690     else if( sig->pubkey_algo == PUBKEY_ALGO_DSA ) {
691         n = pktlen;
692         sig->d.dsa.r = mpi_read(inp, &n, 0 ); pktlen -=n;
693         n = pktlen;
694         sig->d.dsa.s = mpi_read(inp, &n, 0 ); pktlen -=n;
695         if( list_mode ) {
696             printf("\tdsa r: ");
697             mpi_print(stdout, sig->d.elg.a, mpi_print_mode );
698             printf("\n\tdsa s: ");
699             mpi_print(stdout, sig->d.elg.b, mpi_print_mode );
700             putchar('\n');
701         }
702     }
703     else if( sig->pubkey_algo == PUBKEY_ALGO_RSA ) {
704         n = pktlen;
705         sig->d.rsa.rsa_integer = mpi_read(inp, &n, 0 ); pktlen -=n;
706         if( list_mode ) {
707             printf("\trsa integer: ");
708             mpi_print(stdout, sig->d.rsa.rsa_integer, mpi_print_mode );
709             putchar('\n');
710         }
711     }
712     else if( list_mode )
713         printf("\tunknown algorithm %d\n", sig->pubkey_algo );
714
715
716   leave:
717     skip_rest(inp, pktlen);
718     return rc;
719 }
720
721
722 static int
723 parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen,
724                                              PKT_onepass_sig *ops )
725 {
726     int version;
727
728     if( pktlen < 13 ) {
729         log_error("packet(%d) too short\n", pkttype);
730         goto leave;
731     }
732     version = iobuf_get_noeof(inp); pktlen--;
733     if( version != 3 ) {
734         log_error("onepass_sig with unknown version %d\n", version);
735         goto leave;
736     }
737     ops->sig_class = iobuf_get_noeof(inp); pktlen--;
738     ops->digest_algo = iobuf_get_noeof(inp); pktlen--;
739     ops->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
740     ops->keyid[0] = read_32(inp); pktlen -= 4;
741     ops->keyid[1] = read_32(inp); pktlen -= 4;
742     ops->last = iobuf_get_noeof(inp); pktlen--;
743     if( list_mode )
744         printf(":onepass_sig packet: keyid %08lX%08lX\n"
745                "\tversion %d, sigclass %02x, digest %d, pubkey %d, last=%d\n",
746                 (ulong)ops->keyid[0], (ulong)ops->keyid[1],
747                 version, ops->sig_class,
748                 ops->digest_algo, ops->pubkey_algo, ops->last );
749
750
751   leave:
752     skip_rest(inp, pktlen);
753     return 0;
754 }
755
756
757
758
759 static int
760 parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
761                               byte *hdr, int hdrlen, PACKET *pkt )
762 {
763     int i, version, algorithm;
764     unsigned n;
765     unsigned long timestamp;
766     unsigned short valid_period;
767     int is_v4=0;
768     int rc=0;
769
770
771     if( pktlen < 12 ) {
772         log_error("packet(%d) too short\n", pkttype);
773         goto leave;
774     }
775     version = iobuf_get_noeof(inp); pktlen--;
776     if( version == 4 )
777         is_v4=1;
778     else if( version != 2 && version != 3 ) {
779         log_error("packet(%d) with unknown version %d\n", pkttype, version);
780         goto leave;
781     }
782
783     timestamp = read_32(inp); pktlen -= 4;
784     if( is_v4 )
785         valid_period = 0;
786     else {
787         valid_period = read_16(inp); pktlen -= 2;
788     }
789     algorithm = iobuf_get_noeof(inp); pktlen--;
790     if( list_mode )
791         printf(":%s key packet:\n"
792                "\tversion %d, created %lu, valid for %hu days\n",
793                 pkttype == PKT_PUBLIC_CERT? "public" :
794                 pkttype == PKT_SECRET_CERT? "secret" :
795                 pkttype == PKT_PUBKEY_SUBCERT? "public sub" :
796                 pkttype == PKT_SECKEY_SUBCERT? "secret sub" : "??",
797                 version, timestamp, valid_period );
798     if( pkttype == PKT_SECRET_CERT )  {
799         pkt->pkt.secret_cert->timestamp = timestamp;
800         pkt->pkt.secret_cert->valid_days = valid_period;
801         pkt->pkt.secret_cert->hdrbytes = hdrlen;
802         pkt->pkt.secret_cert->version = version;
803         pkt->pkt.secret_cert->pubkey_algo = algorithm;
804     }
805     else {
806         pkt->pkt.public_cert->timestamp = timestamp;
807         pkt->pkt.public_cert->valid_days = valid_period;
808         pkt->pkt.public_cert->hdrbytes    = hdrlen;
809         pkt->pkt.public_cert->version     = version;
810         pkt->pkt.public_cert->pubkey_algo = algorithm;
811     }
812
813     if( algorithm == PUBKEY_ALGO_ELGAMAL ) {
814         MPI elg_p, elg_g, elg_y;
815         n = pktlen; elg_p = mpi_read(inp, &n, 0 ); pktlen -=n;
816         n = pktlen; elg_g = mpi_read(inp, &n, 0 ); pktlen -=n;
817         n = pktlen; elg_y = mpi_read(inp, &n, 0 ); pktlen -=n;
818         if( list_mode ) {
819             printf(  "\telg p: ");
820             mpi_print(stdout, elg_p, mpi_print_mode  );
821             printf("\n\telg g: ");
822             mpi_print(stdout, elg_g, mpi_print_mode  );
823             printf("\n\telg y: ");
824             mpi_print(stdout, elg_y, mpi_print_mode  );
825             putchar('\n');
826         }
827         if( pkttype == PKT_PUBLIC_CERT ) {
828             pkt->pkt.public_cert->d.elg.p = elg_p;
829             pkt->pkt.public_cert->d.elg.g = elg_g;
830             pkt->pkt.public_cert->d.elg.y = elg_y;
831         }
832         else {
833             PKT_secret_cert *cert = pkt->pkt.secret_cert;
834             byte temp[8];
835
836             pkt->pkt.secret_cert->d.elg.p = elg_p;
837             pkt->pkt.secret_cert->d.elg.g = elg_g;
838             pkt->pkt.secret_cert->d.elg.y = elg_y;
839             cert->d.elg.protect.algo = iobuf_get_noeof(inp); pktlen--;
840             if( cert->d.elg.protect.algo ) {
841                 cert->d.elg.is_protected = 1;
842                 cert->d.elg.protect.count = 0;
843                 if( cert->d.elg.protect.algo == 255 ) {
844                     if( pktlen < 3 ) {
845                         rc = G10ERR_INVALID_PACKET;
846                         goto leave;
847                     }
848                     cert->d.elg.protect.algo = iobuf_get_noeof(inp); pktlen--;
849                     cert->d.elg.protect.s2k  = iobuf_get_noeof(inp); pktlen--;
850                     cert->d.elg.protect.hash = iobuf_get_noeof(inp); pktlen--;
851                     switch( cert->d.elg.protect.s2k ) {
852                       case 1:
853                       case 3:
854                         for(i=0; i < 8 && pktlen; i++, pktlen-- )
855                             temp[i] = iobuf_get_noeof(inp);
856                         memcpy(cert->d.elg.protect.salt, temp, 8 );
857                         break;
858                     }
859                     switch( cert->d.elg.protect.s2k ) {
860                       case 0: if( list_mode ) printf(  "\tsimple S2K" );
861                         break;
862                       case 1: if( list_mode ) printf(  "\tsalted S2K" );
863                         break;
864                       case 3: if( list_mode ) printf(  "\titer+salt S2K" );
865                         break;
866                       default:
867                         if( list_mode )
868                             printf(  "\tunknown S2K %d\n",
869                                                 cert->d.elg.protect.s2k );
870                         rc = G10ERR_INVALID_PACKET;
871                         goto leave;
872                     }
873
874                     if( list_mode ) {
875                         printf(", algo: %d, hash: %d",
876                                          cert->d.elg.protect.algo,
877                                          cert->d.elg.protect.hash );
878                         if( cert->d.elg.protect.s2k == 1
879                             || cert->d.elg.protect.s2k == 3 ) {
880                             printf(", salt: ");
881                             for(i=0; i < 8; i++ )
882                                 printf("%02x", cert->d.elg.protect.salt[i]);
883                         }
884                         putchar('\n');
885                     }
886
887                     if( cert->d.elg.protect.s2k == 3 ) {
888                         if( !pktlen ) {
889                             rc = G10ERR_INVALID_PACKET;
890                             goto leave;
891                         }
892                         cert->d.elg.protect.count = iobuf_get_noeof(inp);
893                         pktlen--;
894                     }
895
896                 }
897                 else {
898                     if( list_mode )
899                         printf(  "\tprotect algo: %d\n",
900                                                 cert->d.elg.protect.algo);
901                     /* old version, we don't have a S2K, so we fake one */
902                     cert->d.elg.protect.s2k = 0;
903                     /* We need this kludge to cope with old GNUPG versions */
904                     cert->d.elg.protect.hash =
905                          cert->d.elg.protect.algo == CIPHER_ALGO_BLOWFISH?
906                                       DIGEST_ALGO_RMD160 : DIGEST_ALGO_MD5;
907                 }
908                 if( pktlen < 8 ) {
909                     rc = G10ERR_INVALID_PACKET;
910                     goto leave;
911                 }
912                 for(i=0; i < 8 && pktlen; i++, pktlen-- )
913                     temp[i] = iobuf_get_noeof(inp);
914                 if( list_mode ) {
915                     printf(  "\tprotect IV: ");
916                     for(i=0; i < 8; i++ )
917                         printf(" %02x", temp[i] );
918                     putchar('\n');
919                 }
920                 memcpy(cert->d.elg.protect.iv, temp, 8 );
921             }
922             else
923                 cert->d.elg.is_protected = 0;
924             /* It does not make sense to read it into secure memory.
925              * If the user is so careless, not to protect his secret key,
926              * we can assume, that he operates an open system :=(.
927              * So we put the key into secure memory when we unprotect him. */
928             n = pktlen; cert->d.elg.x = mpi_read(inp, &n, 0 ); pktlen -=n;
929
930             cert->d.elg.csum = read_16(inp); pktlen -= 2;
931             if( list_mode ) {
932                 printf("\t[secret value x is not shown]\n"
933                        "\tchecksum: %04hx\n", cert->d.elg.csum);
934             }
935           /*log_mpidump("elg p=", cert->d.elg.p );
936             log_mpidump("elg g=", cert->d.elg.g );
937             log_mpidump("elg y=", cert->d.elg.y );
938             log_mpidump("elg x=", cert->d.elg.x ); */
939         }
940     }
941     else if( algorithm == PUBKEY_ALGO_DSA ) {
942         MPI dsa_p, dsa_q, dsa_g, dsa_y;
943         n = pktlen; dsa_p = mpi_read(inp, &n, 0 ); pktlen -=n;
944         n = pktlen; dsa_q = mpi_read(inp, &n, 0 ); pktlen -=n;
945         n = pktlen; dsa_g = mpi_read(inp, &n, 0 ); pktlen -=n;
946         n = pktlen; dsa_y = mpi_read(inp, &n, 0 ); pktlen -=n;
947         if( list_mode ) {
948             printf(  "\tdsa p: ");
949             mpi_print(stdout, dsa_p, mpi_print_mode  );
950             printf("\n\tdsa q: ");
951             mpi_print(stdout, dsa_q, mpi_print_mode  );
952             printf("\n\tdsa g: ");
953             mpi_print(stdout, dsa_g, mpi_print_mode  );
954             printf("\n\tdsa y: ");
955             mpi_print(stdout, dsa_y, mpi_print_mode  );
956             putchar('\n');
957         }
958         if( pkttype == PKT_PUBLIC_CERT ) {
959             pkt->pkt.public_cert->d.dsa.p = dsa_p;
960             pkt->pkt.public_cert->d.dsa.q = dsa_q;
961             pkt->pkt.public_cert->d.dsa.g = dsa_g;
962             pkt->pkt.public_cert->d.dsa.y = dsa_y;
963         }
964         else {
965             PKT_secret_cert *cert = pkt->pkt.secret_cert;
966             byte temp[8];
967
968             pkt->pkt.secret_cert->d.dsa.p = dsa_p;
969             pkt->pkt.secret_cert->d.dsa.q = dsa_q;
970             pkt->pkt.secret_cert->d.dsa.g = dsa_g;
971             pkt->pkt.secret_cert->d.dsa.y = dsa_y;
972             cert->d.dsa.protect.algo = iobuf_get_noeof(inp); pktlen--;
973             if( cert->d.dsa.protect.algo ) {
974                 cert->d.dsa.is_protected = 1;
975                 cert->d.dsa.protect.count = 0;
976                 if( cert->d.dsa.protect.algo == 255 ) {
977                     if( pktlen < 3 ) {
978                         rc = G10ERR_INVALID_PACKET;
979                         goto leave;
980                     }
981                     cert->d.dsa.protect.algo = iobuf_get_noeof(inp); pktlen--;
982                     cert->d.dsa.protect.s2k  = iobuf_get_noeof(inp); pktlen--;
983                     cert->d.dsa.protect.hash = iobuf_get_noeof(inp); pktlen--;
984                     switch( cert->d.dsa.protect.s2k ) {
985                       case 1:
986                       case 3:
987                         for(i=0; i < 8 && pktlen; i++, pktlen-- )
988                             temp[i] = iobuf_get_noeof(inp);
989                         memcpy(cert->d.dsa.protect.salt, temp, 8 );
990                         break;
991                     }
992                     switch( cert->d.dsa.protect.s2k ) {
993                       case 0: if( list_mode ) printf(  "\tsimple S2K" );
994                         break;
995                       case 1: if( list_mode ) printf(  "\tsalted S2K" );
996                         break;
997                       case 3: if( list_mode ) printf(  "\titer+salt S2K" );
998                         break;
999                       default:
1000                         if( list_mode )
1001                             printf(  "\tunknown S2K %d\n",
1002                                                 cert->d.dsa.protect.s2k );
1003                         rc = G10ERR_INVALID_PACKET;
1004                         goto leave;
1005                     }
1006
1007                     if( list_mode ) {
1008                         printf(", algo: %d, hash: %d",
1009                                          cert->d.dsa.protect.algo,
1010                                          cert->d.dsa.protect.hash );
1011                         if( cert->d.dsa.protect.s2k == 1
1012                             || cert->d.dsa.protect.s2k == 3 ) {
1013                             printf(", salt: ");
1014                             for(i=0; i < 8; i++ )
1015                                 printf("%02x", cert->d.dsa.protect.salt[i]);
1016                         }
1017                         putchar('\n');
1018                     }
1019
1020                     if( cert->d.dsa.protect.s2k == 3 ) {
1021                         if( !pktlen ) {
1022                             rc = G10ERR_INVALID_PACKET;
1023                             goto leave;
1024                         }
1025                         cert->d.dsa.protect.count = iobuf_get_noeof(inp);
1026                         pktlen--;
1027                     }
1028
1029                 }
1030                 else {
1031                     if( list_mode )
1032                         printf(  "\tprotect algo: %d\n",
1033                                                 cert->d.dsa.protect.algo);
1034                     /* old version, we don't have a S2K, so we fake one */
1035                     cert->d.dsa.protect.s2k = 0;
1036                     cert->d.dsa.protect.hash = DIGEST_ALGO_MD5;
1037                 }
1038                 if( pktlen < 8 ) {
1039                     rc = G10ERR_INVALID_PACKET;
1040                     goto leave;
1041                 }
1042                 for(i=0; i < 8 && pktlen; i++, pktlen-- )
1043                     temp[i] = iobuf_get_noeof(inp);
1044                 if( list_mode ) {
1045                     printf(  "\tprotect IV: ");
1046                     for(i=0; i < 8; i++ )
1047                         printf(" %02x", temp[i] );
1048                     putchar('\n');
1049                 }
1050                 memcpy(cert->d.dsa.protect.iv, temp, 8 );
1051             }
1052             else
1053                 cert->d.dsa.is_protected = 0;
1054             /* It does not make sense to read it into secure memory.
1055              * If the user is so careless, not to protect his secret key,
1056              * we can assume, that he operates an open system :=(.
1057              * So we put the key into secure memory when we unprotect him. */
1058             n = pktlen; cert->d.dsa.x = mpi_read(inp, &n, 0 ); pktlen -=n;
1059
1060             cert->d.dsa.csum = read_16(inp); pktlen -= 2;
1061             if( list_mode ) {
1062                 printf("\t[secret value x is not shown]\n"
1063                        "\tchecksum: %04hx\n", cert->d.dsa.csum);
1064             }
1065           /*log_mpidump("dsa p=", cert->d.dsa.p );
1066             log_mpidump("dsa q=", cert->d.dsa.q );
1067             log_mpidump("dsa g=", cert->d.dsa.g );
1068             log_mpidump("dsa y=", cert->d.dsa.y );
1069             log_mpidump("dsa x=", cert->d.dsa.x ); */
1070         }
1071     }
1072     else if( algorithm == PUBKEY_ALGO_RSA ) {
1073         MPI rsa_pub_mod, rsa_pub_exp;
1074
1075         n = pktlen; rsa_pub_mod = mpi_read(inp, &n, 0); pktlen -=n;
1076         n = pktlen; rsa_pub_exp = mpi_read(inp, &n, 0 ); pktlen -=n;
1077         if( list_mode ) {
1078             printf(  "\tpublic modulus  n:  ");
1079             mpi_print(stdout, rsa_pub_mod, mpi_print_mode  );
1080             printf("\n\tpublic exponent e: ");
1081             mpi_print(stdout, rsa_pub_exp, mpi_print_mode  );
1082             putchar('\n');
1083         }
1084         if( pkttype == PKT_PUBLIC_CERT ) {
1085             pkt->pkt.public_cert->d.rsa.rsa_n = rsa_pub_mod;
1086             pkt->pkt.public_cert->d.rsa.rsa_e = rsa_pub_exp;
1087         }
1088         else {
1089             PKT_secret_cert *cert = pkt->pkt.secret_cert;
1090             byte temp[8];
1091
1092             pkt->pkt.secret_cert->d.rsa.rsa_n = rsa_pub_mod;
1093             pkt->pkt.secret_cert->d.rsa.rsa_e = rsa_pub_exp;
1094             cert->d.rsa.protect_algo = iobuf_get_noeof(inp); pktlen--;
1095             if( list_mode )
1096                 printf(  "\tprotect algo: %d\n", cert->d.rsa.protect_algo);
1097             if( cert->d.rsa.protect_algo ) {
1098                 cert->d.rsa.is_protected = 1;
1099                 for(i=0; i < 8 && pktlen; i++, pktlen-- )
1100                     temp[i] = iobuf_get_noeof(inp);
1101                 if( list_mode ) {
1102                     printf(  "\tprotect IV: ");
1103                     for(i=0; i < 8; i++ )
1104                         printf(" %02x", temp[i] );
1105                     putchar('\n');
1106                 }
1107                 if( cert->d.rsa.protect_algo == CIPHER_ALGO_BLOWFISH )
1108                     memcpy(cert->d.rsa.protect.blowfish.iv, temp, 8 );
1109             }
1110             else
1111                 cert->d.rsa.is_protected = 0;
1112             /* (See comments at the code for elg keys) */
1113             n = pktlen; cert->d.rsa.rsa_d = mpi_read(inp, &n, 0 ); pktlen -=n;
1114             n = pktlen; cert->d.rsa.rsa_p = mpi_read(inp, &n, 0 ); pktlen -=n;
1115             n = pktlen; cert->d.rsa.rsa_q = mpi_read(inp, &n, 0 ); pktlen -=n;
1116             n = pktlen; cert->d.rsa.rsa_u = mpi_read(inp, &n, 0 ); pktlen -=n;
1117
1118             cert->d.rsa.csum = read_16(inp); pktlen -= 2;
1119             if( list_mode ) {
1120                 printf("\t[secret values d,p,q,u are not shown]\n"
1121                        "\tchecksum: %04hx\n", cert->d.rsa.csum);
1122             }
1123          /* log_mpidump("rsa n=", cert->d.rsa.rsa_n );
1124             log_mpidump("rsa e=", cert->d.rsa.rsa_e );
1125             log_mpidump("rsa d=", cert->d.rsa.rsa_d );
1126             log_mpidump("rsa p=", cert->d.rsa.rsa_p );
1127             log_mpidump("rsa q=", cert->d.rsa.rsa_q );
1128             log_mpidump("rsa u=", cert->d.rsa.rsa_u ); */
1129         }
1130     }
1131     else if( list_mode )
1132         printf("\tunknown algorithm %d\n", algorithm );
1133
1134
1135   leave:
1136     skip_rest(inp, pktlen);
1137     return rc;
1138 }
1139
1140
1141 static int
1142 parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
1143 {
1144     byte *p;
1145
1146     packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id  + pktlen - 1);
1147     packet->pkt.user_id->len = pktlen;
1148     p = packet->pkt.user_id->name;
1149     for( ; pktlen; pktlen--, p++ )
1150         *p = iobuf_get_noeof(inp);
1151
1152     if( list_mode ) {
1153         int n = packet->pkt.user_id->len;
1154         printf(":user id packet: \"");
1155         for(p=packet->pkt.user_id->name; n; p++, n-- ) {
1156             if( *p >= ' ' && *p <= 'z' )
1157                 putchar(*p);
1158             else
1159                 printf("\\x%02x", *p );
1160         }
1161         printf("\"\n");
1162     }
1163     return 0;
1164 }
1165
1166
1167 static void
1168 parse_subkey( IOBUF inp, int pkttype, unsigned long pktlen )
1169 {
1170     int version;
1171
1172     version = iobuf_get_noeof(inp); pktlen--;
1173     if( pkttype == PKT_PUBKEY_SUBCERT && version == '#' ) {
1174         /* early versions of G10 use old comments packets; luckily all those
1175          * comments are started by a hash */
1176         if( list_mode ) {
1177             printf(":old comment packet: \"" );
1178             for( ; pktlen; pktlen-- ) {
1179                 int c;
1180                 c = iobuf_get_noeof(inp);
1181                 if( c >= ' ' && c <= 'z' )
1182                     putchar(c);
1183                 else
1184                     printf("\\x%02x", c );
1185             }
1186             printf("\"\n");
1187         }
1188         skip_rest(inp, pktlen);
1189         return;
1190     }
1191
1192     if( list_mode )
1193         printf(":public subkey packet: \"" );
1194     skip_rest(inp, pktlen);
1195 }
1196
1197
1198
1199 static int
1200 parse_comment( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
1201 {
1202     byte *p;
1203
1204     packet->pkt.comment = m_alloc(sizeof *packet->pkt.comment + pktlen - 1);
1205     packet->pkt.comment->len = pktlen;
1206     p = packet->pkt.comment->data;
1207     for( ; pktlen; pktlen--, p++ )
1208         *p = iobuf_get_noeof(inp);
1209
1210     if( list_mode ) {
1211         int n = packet->pkt.comment->len;
1212         printf(":comment packet: \"");
1213         for(p=packet->pkt.comment->data; n; p++, n-- ) {
1214             if( *p >= ' ' && *p <= 'z' )
1215                 putchar(*p);
1216             else
1217                 printf("\\x%02x", *p );
1218         }
1219         printf("\"\n");
1220     }
1221     return 0;
1222 }
1223
1224
1225 static void
1226 parse_trust( IOBUF inp, int pkttype, unsigned long pktlen )
1227 {
1228     int c;
1229
1230     c = iobuf_get_noeof(inp);
1231     if( list_mode )
1232         printf(":trust packet: flag=%02x\n", c );
1233 }
1234
1235
1236 static int
1237 parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
1238 {
1239     int mode, namelen;
1240     PKT_plaintext *pt;
1241     byte *p;
1242     int c, i;
1243
1244     if( pktlen && pktlen < 6 ) {
1245         log_error("packet(%d) too short (%lu)\n", pkttype, (ulong)pktlen);
1246         goto leave;
1247     }
1248     mode = iobuf_get_noeof(inp); if( pktlen ) pktlen--;
1249     namelen = iobuf_get_noeof(inp); if( pktlen ) pktlen--;
1250     pt = pkt->pkt.plaintext = m_alloc(sizeof *pkt->pkt.plaintext + namelen -1);
1251     pt->mode = mode;
1252     pt->namelen = namelen;
1253     if( pktlen ) {
1254         for( i=0; pktlen > 4 && i < namelen; pktlen--, i++ )
1255             pt->name[i] = iobuf_get_noeof(inp);
1256     }
1257     else {
1258         for( i=0; i < namelen; i++ )
1259             if( (c=iobuf_get(inp)) == -1 )
1260                 break;
1261             else
1262                 pt->name[i] = c;
1263     }
1264     pt->timestamp = read_32(inp); if( pktlen) pktlen -= 4;
1265     pt->len = pktlen;
1266     pt->buf = inp;
1267     pktlen = 0;
1268
1269     if( list_mode ) {
1270         printf(":literal data packet:\n"
1271                "\tmode %c, created %lu, name=\"",
1272                     mode >= ' ' && mode <'z'? mode : '?',
1273                     (ulong)pt->timestamp );
1274         for(p=pt->name,i=0; i < namelen; p++, i++ ) {
1275             if( *p >= ' ' && *p <= 'z' )
1276                 putchar(*p);
1277             else
1278                 printf("\\x%02x", *p );
1279         }
1280         printf("\",\n\traw data: %lu bytes\n", (ulong)pt->len );
1281     }
1282
1283   leave:
1284     return 0;
1285 }
1286
1287
1288 static int
1289 parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
1290 {
1291     PKT_compressed *zd;
1292
1293     /* pktlen is here 0, but data follows
1294      * (this should be the last object in a file or
1295      *  the compress algorithm should know the length)
1296      */
1297     zd = pkt->pkt.compressed =  m_alloc(sizeof *pkt->pkt.compressed );
1298     zd->len = 0; /* not yet used */
1299     zd->algorithm = iobuf_get_noeof(inp);
1300     zd->buf = inp;
1301     if( list_mode )
1302         printf(":compressed packet: algo=%d\n", zd->algorithm);
1303     return 0;
1304 }
1305
1306
1307 static int
1308 parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
1309 {
1310     PKT_encrypted *ed;
1311
1312     ed = pkt->pkt.encrypted =  m_alloc(sizeof *pkt->pkt.encrypted );
1313     ed->len = pktlen;
1314     ed->buf = NULL;
1315     if( pktlen && pktlen < 10 ) {
1316         log_error("packet(%d) too short\n", pkttype);
1317         skip_rest(inp, pktlen);
1318         goto leave;
1319     }
1320     if( list_mode )
1321         if( pktlen )
1322             printf(":encrypted data packet:\n\tlength: %lu\n", pktlen-10);
1323         else
1324             printf(":encrypted data packet:\n\tlength: unknown\n");
1325
1326     ed->buf = inp;
1327     pktlen = 0;
1328
1329   leave:
1330     return 0;
1331 }
1332
1333
1334