5badb0ec43f830c6f0a78adcedd37b2de4fa16f9
[gnupg.git] / g10 / parse-packet.c
1 /* parse-packet.c  - read packets
2  *      Copyright (c) 1997 by Werner Koch (dd9jn)
3  *
4  * This file is part of G10.
5  *
6  * G10 is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * G10 is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <assert.h>
26
27 #include "packet.h"
28 #include "iobuf.h"
29 #include "mpi.h"
30 #include "util.h"
31 #include "cipher.h"
32 #include "memory.h"
33 #include "filter.h"
34 #include "options.h"
35
36 static mpi_print_mode = 0;
37 static list_mode = 0;
38
39 static void skip_packet( IOBUF inp, int pkttype, unsigned long pktlen );
40 static void skip_rest( IOBUF inp, unsigned long pktlen );
41 static int  parse_publickey( IOBUF inp, int pkttype, unsigned long pktlen,
42                                                              PACKET *packet );
43 static int  parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
44                                                          PKT_signature *sig );
45 static int  parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen,
46                                                         PKT_onepass_sig *ops );
47 static int  parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
48                                       byte *hdr, int hdrlen, PACKET *packet );
49 static int  parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen,
50                                                            PACKET *packet );
51 static void parse_comment( IOBUF inp, int pkttype, unsigned long pktlen );
52 static void parse_trust( IOBUF inp, int pkttype, unsigned long pktlen );
53 static int  parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen,
54                                                                 PACKET *pkt );
55 static int  parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen,
56                                                            PACKET *packet );
57 static int  parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
58                                                            PACKET *packet );
59
60 static u16
61 checksum( byte *p )
62 {
63     u16 n, a;
64
65     n = *p++ << 8;
66     n |= *p++;
67     for(a=0; n; n-- )
68         a += *p++;
69     return a;
70 }
71
72 static unsigned short
73 read_16(IOBUF inp)
74 {
75     unsigned short a;
76     a = iobuf_get_noeof(inp) << 8;
77     a |= iobuf_get_noeof(inp);
78     return a;
79 }
80
81 static unsigned long
82 read_32(IOBUF inp)
83 {
84     unsigned long a;
85     a =  iobuf_get_noeof(inp) << 24;
86     a |= iobuf_get_noeof(inp) << 16;
87     a |= iobuf_get_noeof(inp) << 8;
88     a |= iobuf_get_noeof(inp);
89     return a;
90 }
91
92 int
93 set_packet_list_mode( int mode )
94 {
95     int old = list_mode;
96     list_mode = mode;
97     mpi_print_mode = DBG_MPI;
98     return old;
99 }
100
101 /****************
102  * Parse a Packet and return it in packet
103  * Returns: 0 := valid packet in pkt
104  *         -1 := no more packets
105  *         >0 := error
106  * Note: The function may return an error and a partly valid packet;
107  * caller must free this packet.
108  */
109 int
110 parse_packet( IOBUF inp, PACKET *pkt )
111 {
112     int rc, ctb, pkttype, lenbytes;
113     unsigned long pktlen;
114     byte hdr[5];
115     int hdrlen;
116
117     assert( !pkt->pkt.generic );
118     if( (ctb = iobuf_get(inp)) == -1 )
119         return -1;
120     hdrlen=0;
121     hdr[hdrlen++] = ctb;
122     if( !(ctb & 0x80) ) {
123         log_error("invalid packet at '%s'\n", iobuf_where(inp) );
124         return G10ERR_INVALID_PACKET;
125     }
126     /* we handle the pgp 3 extensions here, so that we can skip such packets*/
127     pkttype =  ctb & 0x40 ? (ctb & 0x3f) : ((ctb>>2)&0xf);
128     lenbytes = (ctb & 0x40) || ((ctb&3)==3)? 0 : (1<<(ctb & 3));
129     pktlen = 0;
130     if( !lenbytes ) {
131         pktlen = 0; /* don't know the value */
132         if( pkttype != PKT_COMPRESSED )
133             iobuf_set_block_mode(inp, 1);
134     }
135     else {
136         for( ; lenbytes; lenbytes-- ) {
137             pktlen <<= 8;
138             pktlen |= hdr[hdrlen++] = iobuf_get_noeof(inp);
139         }
140     }
141
142     if( DBG_PACKET )
143         log_debug("parse_packet(iob=%d): type=%d length=%lu\n",
144                                             iobuf_id(inp), pkttype, pktlen );
145     pkt->pkttype = pkttype;
146     rc = G10ERR_UNKNOWN_PACKET; /* default to no error */
147     switch( pkttype ) {
148       case PKT_PUBLIC_CERT:
149         pkt->pkt.public_cert = m_alloc_clear(sizeof *pkt->pkt.public_cert );
150         rc = parse_certificate(inp, pkttype, pktlen, hdr, hdrlen, pkt );
151         break;
152       case PKT_SECRET_CERT:
153       case PKT_SECKEY_SUBCERT:
154         pkt->pkt.secret_cert = m_alloc_clear(sizeof *pkt->pkt.secret_cert );
155         rc = parse_certificate(inp, pkttype, pktlen, hdr, hdrlen, pkt );
156         break;
157       case PKT_PUBKEY_ENC:
158         rc = parse_publickey(inp, pkttype, pktlen, pkt );
159         break;
160       case PKT_SIGNATURE:
161         pkt->pkt.signature = m_alloc_clear(sizeof *pkt->pkt.signature );
162         rc = parse_signature(inp, pkttype, pktlen, pkt->pkt.signature );
163         break;
164       case PKT_ONEPASS_SIG:
165         pkt->pkt.onepass_sig = m_alloc_clear(sizeof *pkt->pkt.onepass_sig );
166         rc = parse_onepass_sig(inp, pkttype, pktlen, pkt->pkt.onepass_sig );
167         break;
168       case PKT_USER_ID:
169         rc = parse_user_id(inp, pkttype, pktlen, pkt );
170         break;
171       case PKT_COMMENT:
172         parse_comment(inp, pkttype, pktlen);
173         break;
174       case PKT_RING_TRUST:
175         parse_trust(inp, pkttype, pktlen);
176         break;
177       case PKT_PLAINTEXT:
178         rc = parse_plaintext(inp, pkttype, pktlen, pkt );
179         break;
180       case PKT_COMPRESSED:
181         rc = parse_compressed(inp, pkttype, pktlen, pkt );
182         break;
183       case PKT_ENCRYPTED:
184         rc = parse_encrypted(inp, pkttype, pktlen, pkt );
185         break;
186       default:
187         skip_packet(inp, pkttype, pktlen);
188         break;
189     }
190
191     return rc;
192 }
193
194
195 static void
196 skip_packet( IOBUF inp, int pkttype, unsigned long pktlen )
197 {
198     if( list_mode )
199         printf(":unknown packet: type %2d, length %lu\n", pkttype, pktlen );
200     skip_rest(inp,pktlen);
201 }
202
203 static void
204 skip_rest( IOBUF inp, unsigned long pktlen )
205 {
206     if( iobuf_in_block_mode(inp) ) {
207         while( iobuf_get(inp) != -1 )
208                 ;
209     }
210     else {
211         for( ; pktlen; pktlen-- )
212             iobuf_get(inp);
213     }
214 }
215
216
217 static int
218 parse_publickey( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
219 {
220     int version;
221     unsigned n;
222     PKT_pubkey_enc *k;
223
224     k = packet->pkt.pubkey_enc = m_alloc(sizeof *packet->pkt.pubkey_enc );
225     if( pktlen < 12 ) {
226         log_error("packet(%d) too short\n", pkttype);
227         goto leave;
228     }
229     version = iobuf_get_noeof(inp); pktlen--;
230     if( version != 2 && version != 3 ) {
231         log_error("packet(%d) with unknown version %d\n", pkttype, version);
232         goto leave;
233     }
234     k->keyid[0] = read_32(inp); pktlen -= 4;
235     k->keyid[1] = read_32(inp); pktlen -= 4;
236     k->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
237     if( list_mode )
238         printf(":public key packet: keyid %08lX%08lX\n",
239                                         k->keyid[0], k->keyid[1]);
240     if( k->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
241         n = pktlen;
242         k->d.elg.a = mpi_read(inp, &n, 0); pktlen -=n;
243         k->d.elg.b = mpi_read(inp, &n, 0 ); pktlen -=n;
244         if( list_mode ) {
245             printf("\telg a: ");
246             mpi_print(stdout, k->d.elg.a, mpi_print_mode );
247             printf("\n\telg b: ");
248             mpi_print(stdout, k->d.elg.b, mpi_print_mode );
249             putchar('\n');
250         }
251     }
252     else if( k->pubkey_algo == PUBKEY_ALGO_RSA ) {
253         n = pktlen;
254         k->d.rsa.rsa_integer = mpi_read(inp, &n, 0 ); pktlen -=n;
255         if( list_mode ) {
256             printf("\trsa integer: ");
257             mpi_print(stdout, k->d.rsa.rsa_integer, mpi_print_mode );
258             putchar('\n');
259         }
260     }
261     else if( list_mode )
262         printf("\tunknown algorithm %d\n", k->pubkey_algo );
263
264
265   leave:
266     skip_rest(inp, pktlen);
267     return 0;
268 }
269
270
271 static int
272 parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
273                                           PKT_signature *sig )
274 {
275     int version, md5_len;
276     unsigned n;
277
278     if( pktlen < 16 ) {
279         log_error("packet(%d) too short\n", pkttype);
280         goto leave;
281     }
282     version = iobuf_get_noeof(inp); pktlen--;
283     if( version != 2 && version != 3 ) {
284         log_error("packet(%d) with unknown version %d\n", pkttype, version);
285         goto leave;
286     }
287     md5_len = iobuf_get_noeof(inp); pktlen--;
288     sig->sig_class = iobuf_get_noeof(inp); pktlen--;
289     sig->timestamp = read_32(inp); pktlen -= 4;
290     sig->keyid[0] = read_32(inp); pktlen -= 4;
291     sig->keyid[1] = read_32(inp); pktlen -= 4;
292     sig->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
293     if( list_mode )
294         printf(":signature packet: keyid %08lX%08lX\n"
295                "\tversion %d, created %lu, md5len %d, sigclass %02x\n",
296                 sig->keyid[0], sig->keyid[1],
297                 version, sig->timestamp, md5_len, sig->sig_class );
298     if( sig->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
299         if( pktlen < 5 ) {
300             log_error("packet(%d) too short\n", pkttype);
301             goto leave;
302         }
303         sig->d.elg.digest_algo = iobuf_get_noeof(inp); pktlen--;
304         sig->d.elg.digest_start[0] = iobuf_get_noeof(inp); pktlen--;
305         sig->d.elg.digest_start[1] = iobuf_get_noeof(inp); pktlen--;
306         n = pktlen;
307         sig->d.elg.a = mpi_read(inp, &n, 0 ); pktlen -=n;
308         sig->d.elg.b = mpi_read(inp, &n, 0 ); pktlen -=n;
309         if( list_mode ) {
310             printf("\tdigest algo %d, begin of digest %02x %02x\n",
311                     sig->d.elg.digest_algo,
312                     sig->d.elg.digest_start[0], sig->d.elg.digest_start[1] );
313             printf("\telg a: ");
314             mpi_print(stdout, sig->d.elg.a, mpi_print_mode );
315             printf("\n\telg b: ");
316             mpi_print(stdout, sig->d.elg.b, mpi_print_mode );
317             putchar('\n');
318         }
319     }
320     else if( sig->pubkey_algo == PUBKEY_ALGO_RSA ) {
321         if( pktlen < 5 ) {
322             log_error("packet(%d) too short\n", pkttype);
323             goto leave;
324         }
325         sig->d.rsa.digest_algo = iobuf_get_noeof(inp); pktlen--;
326         sig->d.rsa.digest_start[0] = iobuf_get_noeof(inp); pktlen--;
327         sig->d.rsa.digest_start[1] = iobuf_get_noeof(inp); pktlen--;
328         n = pktlen;
329         sig->d.rsa.rsa_integer = mpi_read(inp, &n, 0 ); pktlen -=n;
330         if( list_mode ) {
331             printf("\tdigest algo %d, begin of digest %02x %02x\n",
332                     sig->d.rsa.digest_algo,
333                     sig->d.rsa.digest_start[0], sig->d.rsa.digest_start[1] );
334             printf("\trsa integer: ");
335             mpi_print(stdout, sig->d.rsa.rsa_integer, mpi_print_mode );
336             putchar('\n');
337         }
338     }
339     else if( list_mode )
340         printf("\tunknown algorithm %d\n", sig->pubkey_algo );
341
342
343   leave:
344     skip_rest(inp, pktlen);
345     return 0;
346 }
347
348
349 static int
350 parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen,
351                                              PKT_onepass_sig *ops )
352 {
353     int version;
354     unsigned n;
355
356     if( pktlen < 13 ) {
357         log_error("packet(%d) too short\n", pkttype);
358         goto leave;
359     }
360     version = iobuf_get_noeof(inp); pktlen--;
361     if( version != 3 ) {
362         log_error("onepass_sig with unknown version %d\n", version);
363         goto leave;
364     }
365     ops->sig_class = iobuf_get_noeof(inp); pktlen--;
366     ops->digest_algo = iobuf_get_noeof(inp); pktlen--;
367     ops->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
368     ops->keyid[0] = read_32(inp); pktlen -= 4;
369     ops->keyid[1] = read_32(inp); pktlen -= 4;
370     ops->last = iobuf_get_noeof(inp); pktlen--;
371     if( list_mode )
372         printf(":onepass_sig packet: keyid %08lX%08lX\n"
373                "\tversion %d, sigclass %02x, digest %d, pubkey %d, last=%d\n",
374                 ops->keyid[0], ops->keyid[1],
375                 version, ops->sig_class,
376                 ops->digest_algo, ops->pubkey_algo, ops->last );
377
378
379   leave:
380     skip_rest(inp, pktlen);
381     return 0;
382 }
383
384
385
386
387 static int
388 parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
389                               byte *hdr, int hdrlen, PACKET *pkt )
390 {
391     int i, version, algorithm;
392     unsigned n;
393     unsigned long timestamp;
394     unsigned short valid_period;
395     int is_v4=0;
396
397     if( pkttype == PKT_PUBLIC_CERT ) {
398         pkt->pkt.public_cert->mfx.md5 = md5_open(0);
399         pkt->pkt.public_cert->mfx.rmd160 = rmd160_open(0);
400         pkt->pkt.public_cert->mfx.maxbuf_size = 1;
401         md5_write(pkt->pkt.public_cert->mfx.md5, hdr, hdrlen);
402         rmd160_write(pkt->pkt.public_cert->mfx.rmd160, hdr, hdrlen);
403         iobuf_push_filter( inp, md_filter, &pkt->pkt.public_cert->mfx );
404     }
405
406     if( pktlen < 12 ) {
407         log_error("packet(%d) too short\n", pkttype);
408         goto leave;
409     }
410     version = iobuf_get_noeof(inp); pktlen--;
411     if( version == 4 )
412         is_v4=1;
413     else if( version != 2 && version != 3 ) {
414         log_error("packet(%d) with unknown version %d\n", pkttype, version);
415         goto leave;
416     }
417
418     timestamp = read_32(inp); pktlen -= 4;
419     if( is_v4 )
420         valid_period = 0;
421     else
422         valid_period = read_16(inp); pktlen -= 2;
423     algorithm = iobuf_get_noeof(inp); pktlen--;
424     if( list_mode )
425         printf(":%s key certification packet:\n"
426                "\tversion %d, created %lu, valid for %hu days\n",
427                 pkttype == PKT_PUBLIC_CERT? "public": "secret",
428                 version, timestamp, valid_period );
429     if( pkttype == PKT_SECRET_CERT )  {
430         pkt->pkt.secret_cert->timestamp = timestamp;
431         pkt->pkt.secret_cert->valid_days = valid_period;
432         pkt->pkt.secret_cert->pubkey_algo = algorithm;
433     }
434     else {
435         pkt->pkt.public_cert->timestamp = timestamp;
436         pkt->pkt.public_cert->valid_days = valid_period;
437         pkt->pkt.public_cert->pubkey_algo = algorithm;
438     }
439
440     if( algorithm == PUBKEY_ALGO_ELGAMAL ) {
441         MPI elg_p, elg_g, elg_y;
442         n = pktlen; elg_p = mpi_read(inp, &n, 0 ); pktlen -=n;
443         n = pktlen; elg_g = mpi_read(inp, &n, 0 ); pktlen -=n;
444         n = pktlen; elg_y = mpi_read(inp, &n, 0 ); pktlen -=n;
445         if( list_mode ) {
446             printf(  "\telg p:  ");
447             mpi_print(stdout, elg_p, mpi_print_mode  );
448             printf("\n\telg g: ");
449             mpi_print(stdout, elg_g, mpi_print_mode  );
450             printf("\n\telg y: ");
451             mpi_print(stdout, elg_y, mpi_print_mode  );
452             putchar('\n');
453         }
454         if( pkttype == PKT_PUBLIC_CERT ) {
455             pkt->pkt.public_cert->d.elg.p = elg_p;
456             pkt->pkt.public_cert->d.elg.g = elg_g;
457             pkt->pkt.public_cert->d.elg.y = elg_y;
458         }
459         else {
460             PKT_secret_cert *cert = pkt->pkt.secret_cert;
461             byte temp[8];
462             byte *mpibuf;
463
464             pkt->pkt.secret_cert->d.elg.p = elg_p;
465             pkt->pkt.secret_cert->d.elg.g = elg_g;
466             pkt->pkt.secret_cert->d.elg.y = elg_y;
467             cert->d.elg.protect_algo = iobuf_get_noeof(inp); pktlen--;
468             if( list_mode )
469                 printf(  "\tprotect algo: %d\n", cert->d.elg.protect_algo);
470             if( cert->d.elg.protect_algo ) {
471                 cert->d.elg.is_protected = 1;
472                 for(i=0; i < 8 && pktlen; i++, pktlen-- )
473                     temp[i] = iobuf_get_noeof(inp);
474                 if( list_mode ) {
475                     printf(  "\tprotect IV: ");
476                     for(i=0; i < 8; i++ )
477                         printf(" %02x", temp[i] );
478                     putchar('\n');
479                 }
480                 if( cert->d.elg.protect_algo == CIPHER_ALGO_BLOWFISH )
481                     memcpy(cert->d.elg.protect.blowfish.iv, temp, 8 );
482             }
483             else
484                 cert->d.elg.is_protected = 0;
485
486             n = pktlen; cert->d.elg.x = mpi_read(inp, &n, 1 ); pktlen -=n;
487
488             cert->d.elg.csum = read_16(inp); pktlen -= 2;
489             if( list_mode ) {
490                 printf("\t[secret value x is not shown]\n"
491                        "\tchecksum: %04hx\n", cert->d.elg.csum);
492             }
493           /*log_mpidump("elg p=", cert->d.elg.p );
494             log_mpidump("elg g=", cert->d.elg.g );
495             log_mpidump("elg y=", cert->d.elg.y );
496             log_mpidump("elg x=", cert->d.elg.x ); */
497         }
498     }
499     else if( algorithm == PUBKEY_ALGO_RSA ) {
500         MPI rsa_pub_mod, rsa_pub_exp;
501
502         n = pktlen; rsa_pub_mod = mpi_read(inp, &n, 0); pktlen -=n;
503         n = pktlen; rsa_pub_exp = mpi_read(inp, &n, 0 ); pktlen -=n;
504         if( list_mode ) {
505             printf(  "\tpublic modulus  n:  ");
506             mpi_print(stdout, rsa_pub_mod, mpi_print_mode  );
507             printf("\n\tpublic exponent e: ");
508             mpi_print(stdout, rsa_pub_exp, mpi_print_mode  );
509             putchar('\n');
510         }
511         if( pkttype == PKT_PUBLIC_CERT ) {
512             pkt->pkt.public_cert->d.rsa.rsa_n = rsa_pub_mod;
513             pkt->pkt.public_cert->d.rsa.rsa_e = rsa_pub_exp;
514         }
515         else {
516             PKT_secret_cert *cert = pkt->pkt.secret_cert;
517             byte temp[8];
518             byte *mpibuf;
519
520             pkt->pkt.secret_cert->d.rsa.rsa_n = rsa_pub_mod;
521             pkt->pkt.secret_cert->d.rsa.rsa_e = rsa_pub_exp;
522             cert->d.rsa.protect_algo = iobuf_get_noeof(inp); pktlen--;
523             if( list_mode )
524                 printf(  "\tprotect algo: %d\n", cert->d.rsa.protect_algo);
525             if( cert->d.rsa.protect_algo ) {
526                 cert->d.rsa.is_protected = 1;
527                 for(i=0; i < 8 && pktlen; i++, pktlen-- )
528                     temp[i] = iobuf_get_noeof(inp);
529                 if( list_mode ) {
530                     printf(  "\tprotect IV: ");
531                     for(i=0; i < 8; i++ )
532                         printf(" %02x", temp[i] );
533                     putchar('\n');
534                 }
535                 if( cert->d.rsa.protect_algo == CIPHER_ALGO_BLOWFISH )
536                     memcpy(cert->d.rsa.protect.blowfish.iv, temp, 8 );
537             }
538             else
539                 cert->d.rsa.is_protected = 0;
540
541             n = pktlen; cert->d.rsa.rsa_d = mpi_read(inp, &n, 1 ); pktlen -=n;
542             n = pktlen; cert->d.rsa.rsa_p = mpi_read(inp, &n, 1 ); pktlen -=n;
543             n = pktlen; cert->d.rsa.rsa_q = mpi_read(inp, &n, 1 ); pktlen -=n;
544             n = pktlen; cert->d.rsa.rsa_u = mpi_read(inp, &n, 1 ); pktlen -=n;
545
546             cert->d.rsa.csum = read_16(inp); pktlen -= 2;
547             if( list_mode ) {
548                 printf("\t[secret values d,p,q,u are not shown]\n"
549                        "\tchecksum: %04hx\n", cert->d.rsa.csum);
550             }
551          /* log_mpidump("rsa n=", cert->d.rsa.rsa_n );
552             log_mpidump("rsa e=", cert->d.rsa.rsa_e );
553             log_mpidump("rsa d=", cert->d.rsa.rsa_d );
554             log_mpidump("rsa p=", cert->d.rsa.rsa_p );
555             log_mpidump("rsa q=", cert->d.rsa.rsa_q );
556             log_mpidump("rsa u=", cert->d.rsa.rsa_u ); */
557         }
558     }
559     else if( list_mode )
560         printf("\tunknown algorithm %d\n", algorithm );
561
562
563   leave:
564     if( pkttype == PKT_PUBLIC_CERT )
565         iobuf_pop_filter( inp, md_filter, &pkt->pkt.public_cert->mfx );
566     skip_rest(inp, pktlen);
567     return 0;
568 }
569
570
571 static int
572 parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
573 {
574     byte *p;
575
576     packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id  + pktlen - 1);
577     packet->pkt.user_id->len = pktlen;
578     p = packet->pkt.user_id->name;
579     for( ; pktlen; pktlen--, p++ )
580         *p = iobuf_get_noeof(inp);
581
582     if( list_mode ) {
583         int n = packet->pkt.user_id->len;
584         printf(":user id packet: \"");
585         for(p=packet->pkt.user_id->name; n; p++, n-- ) {
586             if( *p >= ' ' && *p <= 'z' )
587                 putchar(*p);
588             else
589                 printf("\\x%02x", *p );
590         }
591         printf("\"\n");
592     }
593     return 0;
594 }
595
596 static void
597 parse_comment( IOBUF inp, int pkttype, unsigned long pktlen )
598 {
599     if( list_mode ) {
600         printf(":comment packet: \"" );
601         for( ; pktlen; pktlen-- ) {
602             int c;
603             c = iobuf_get_noeof(inp);
604             if( c >= ' ' && c <= 'z' )
605                 putchar(c);
606             else
607                 printf("\\x%02x", c );
608         }
609         printf("\"\n");
610     }
611     skip_rest(inp, pktlen);
612 }
613
614
615 static void
616 parse_trust( IOBUF inp, int pkttype, unsigned long pktlen )
617 {
618     int c;
619
620     c = iobuf_get_noeof(inp);
621     if( list_mode )
622         printf(":trust packet: flag=%02x\n", c );
623   #if 0 /* fixme: depending on the context we have different interpretations*/
624     if( prev_packet_is_a_key_packet ) {
625         int ot = c & 7;   /* ownertrust bits (for the key owner) */
626
627             !ot ? "undefined" :
628         ot == 1 ? "unknown"   : /* we don't know the owner of this key */
629         ot == 2 ? "no"        : /* usually we do not trust this key owner */
630                                 /* to sign other keys */
631         ot == 5 ? "usually"   : /* usually we trust this key owner to sign */
632         ot == 6 ? "always"    : /* always trust this key owner to sign */
633         ot == 7 ? "ultimate"  : /* also present in the secret keyring */
634               ""                /* reserved value */
635         if( c & (1<<5) )
636             "key is disabled"
637         if( c & (1<<7) )
638             "buckstop"
639     else if( prev_packet_is_user_is_packet ) {
640             int kl = c & 3; /* keylegit bits */
641         0 = "unknown, undefined, or uninitialized trust"
642         1 = "we do not trust this key's ownership"
643         2 = "we have marginal confidence of this key's ownership"
644         3 = "we completely trust this key's ownership."
645         if( c & 0x80 )
646             "warnonly"
647     else if( prev_packet_is_a_signature ) {
648     }
649   #endif
650 }
651
652
653 static int
654 parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
655 {
656     int mode, namelen;
657     PKT_plaintext *pt;
658     byte *p;
659     int c, i;
660
661     if( pktlen && pktlen < 6 ) {
662         log_error("packet(%d) too short (%lu)\n", pkttype, (ulong)pktlen);
663         goto leave;
664     }
665     mode = iobuf_get_noeof(inp); if( pktlen ) pktlen--;
666     namelen = iobuf_get_noeof(inp); if( pktlen ) pktlen--;
667     pt = pkt->pkt.plaintext = m_alloc(sizeof *pkt->pkt.plaintext + namelen -1);
668     pt->mode = mode;
669     pt->namelen = namelen;
670     if( pktlen ) {
671         for( i=0; pktlen > 4 && i < namelen; pktlen--, i++ )
672             pt->name[i] = iobuf_get_noeof(inp);
673     }
674     else {
675         for( i=0; i < namelen; i++ )
676             if( (c=iobuf_get(inp)) == -1 )
677                 break;
678             else
679                 pt->name[i] = c;
680     }
681     pt->timestamp = read_32(inp); if( pktlen) pktlen -= 4;
682     pt->len = pktlen;
683     pt->buf = inp;
684     pktlen = 0;
685
686     if( list_mode ) {
687         printf(":literal data packet:\n"
688                "\tmode %c, created %lu, name=\"",
689                     mode >= ' ' && mode <'z'? mode : '?',
690                     pt->timestamp );
691         for(p=pt->name,i=0; i < namelen; p++, i++ ) {
692             if( *p >= ' ' && *p <= 'z' )
693                 putchar(*p);
694             else
695                 printf("\\x%02x", *p );
696         }
697         printf("\",\n\traw data: %lu bytes\n", pt->len );
698     }
699
700   leave:
701     return 0;
702 }
703
704
705 static int
706 parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
707 {
708     PKT_compressed *zd;
709     int algorithm;
710
711     /* pktlen is here 0, but data follows
712      * (this should be the last object in a file or
713      *  the compress algorithm should know the length)
714      */
715     zd = pkt->pkt.compressed =  m_alloc(sizeof *pkt->pkt.compressed );
716     zd->len = 0; /* not yet used */
717     zd->algorithm = iobuf_get_noeof(inp);
718     zd->buf = inp;
719     if( list_mode )
720         printf(":compressed packet: algo=%d\n", zd->algorithm);
721     return 0;
722 }
723
724
725 static int
726 parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
727 {
728     PKT_encrypted *ed;
729
730     ed = pkt->pkt.encrypted =  m_alloc(sizeof *pkt->pkt.encrypted );
731     ed->len = pktlen;
732     ed->buf = NULL;
733     if( pktlen && pktlen < 10 ) {
734         log_error("packet(%d) too short\n", pkttype);
735         skip_rest(inp, pktlen);
736         goto leave;
737     }
738     if( list_mode )
739         if( pktlen )
740             printf(":encrypted data packet:\n\tlength: %lu\n", pktlen-10);
741         else
742             printf(":encrypted data packet:\n\tlength: unknown\n");
743
744     ed->buf = inp;
745     pktlen = 0;
746
747   leave:
748     return 0;
749 }
750
751