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