Aenderungen in der Eifel
[gnupg.git] / g10 / mainproc.c
1 /* mainproc.c - handle 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 "memory.h"
30 #include "options.h"
31 #include "util.h"
32 #include "cipher.h"
33 #include "keydb.h"
34 #include "filter.h"
35 #include "cipher.h"
36 #include "main.h"
37 #include "status.h"
38
39
40 /****************
41  * Structure to hold the context
42  */
43
44 typedef struct {
45     PKT_public_cert *last_pubkey;
46     PKT_secret_cert *last_seckey;
47     PKT_user_id     *last_user_id;
48     md_filter_context_t mfx;
49     int sigs_only;   /* process only signatures and reject all other stuff */
50     int encrypt_only; /* process only encrytion messages */
51     STRLIST signed_data;
52     DEK *dek;
53     int last_was_session_key;
54     KBNODE list;   /* the current list of packets */
55     int have_data;
56     IOBUF iobuf;    /* used to get the filename etc. */
57 } *CTX;
58
59
60 static int do_proc_packets( CTX c, IOBUF a );
61
62 static void list_node( CTX c, KBNODE node );
63 static void proc_tree( CTX c, KBNODE node );
64
65
66 static void
67 release_list( CTX c )
68 {
69     if( !c->list )
70         return;
71     proc_tree(c, c->list );
72     release_kbnode( c->list );
73     c->list = NULL;
74 }
75
76
77 static int
78 add_onepass_sig( CTX c, PACKET *pkt )
79 {
80     KBNODE node;
81
82     if( c->list ) { /* add another packet */
83         if( c->list->pkt->pkttype != PKT_ONEPASS_SIG ) {
84            log_error("add_onepass_sig: another packet is in the way\n");
85            release_list( c );
86         }
87         add_kbnode( c->list, new_kbnode( pkt ));
88     }
89     else /* insert the first one */
90         c->list = node = new_kbnode( pkt );
91
92     return 1;
93 }
94
95
96
97 static int
98 add_user_id( CTX c, PACKET *pkt )
99 {
100     if( !c->list ) {
101         log_error("orphaned user id\n" );
102         return 0;
103     }
104     add_kbnode( c->list, new_kbnode( pkt ) );
105     return 1;
106 }
107
108 static int
109 add_subkey( CTX c, PACKET *pkt )
110 {
111     if( !c->list ) {
112         log_error("subkey w/o mainkey\n" );
113         return 0;
114     }
115     add_kbnode( c->list, new_kbnode( pkt ) );
116     return 1;
117 }
118
119
120 static int
121 add_signature( CTX c, PACKET *pkt )
122 {
123     KBNODE node;
124
125     if( pkt->pkttype == PKT_SIGNATURE && !c->list ) {
126         /* This is the first signature for the following datafile.
127          * G10 does not write such packets; instead it always uses
128          * onepass-sig packets.  The drawback of PGP's method
129          * of prepending the signature to the data is
130          * that it is not possible to make a signature from data read
131          * from stdin.  (G10 is able to read PGP stuff anyway.) */
132         node = new_kbnode( pkt );
133         c->list = node;
134         return 1;
135     }
136     else if( !c->list )
137         return 0; /* oops (invalid packet sequence)*/
138     else if( !c->list->pkt )
139         BUG();  /* so nicht */
140
141     /* add a new signature node id at the end */
142     node = new_kbnode( pkt );
143     add_kbnode( c->list, node );
144     return 1;
145 }
146
147
148 static void
149 proc_symkey_enc( CTX c, PACKET *pkt )
150 {
151    /* FIXME:   NOT READY */
152    #if 0
153     PKT_symkey_enc *enc;
154     int result = 0;
155
156     c->last_was_session_key = 1;
157     enc = pkt->pkt.symkey_enc;
158     if( enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL
159         || enc->pubkey_algo == PUBKEY_ALGO_DSA
160         || enc->pubkey_algo == PUBKEY_ALGO_RSA  ) {
161         m_free(c->dek ); /* paranoid: delete a pending DEK */
162         c->dek = m_alloc_secure( sizeof *c->dek );
163         if( (result = get_session_key( enc, c->dek )) ) {
164             /* error: delete the DEK */
165             m_free(c->dek); c->dek = NULL;
166         }
167     }
168     else
169         result = G10ERR_PUBKEY_ALGO;
170
171     if( result == -1 )
172         ;
173     else if( !result ) {
174         if( opt.verbose > 1 )
175             log_info( "pubkey_enc packet: Good DEK\n" );
176     }
177     else
178         log_error( "pubkey_enc packet: %s\n", g10_errstr(result));
179     free_packet(pkt);
180   #endif
181 }
182
183 static void
184 proc_pubkey_enc( CTX c, PACKET *pkt )
185 {
186     PKT_pubkey_enc *enc;
187     int result = 0;
188
189     c->last_was_session_key = 1;
190     enc = pkt->pkt.pubkey_enc;
191     /*printf("enc: encrypted by a pubkey with keyid %08lX\n", enc->keyid[1] );*/
192     if( enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL
193         || enc->pubkey_algo == PUBKEY_ALGO_DSA
194         || enc->pubkey_algo == PUBKEY_ALGO_RSA  ) {
195         m_free(c->dek ); /* paranoid: delete a pending DEK */
196         c->dek = m_alloc_secure( sizeof *c->dek );
197         if( (result = get_session_key( enc, c->dek )) ) {
198             /* error: delete the DEK */
199             m_free(c->dek); c->dek = NULL;
200         }
201     }
202     else
203         result = G10ERR_PUBKEY_ALGO;
204
205     if( result == -1 )
206         ;
207     else if( !result ) {
208         if( opt.verbose > 1 )
209             log_info( "pubkey_enc packet: Good DEK\n" );
210     }
211     else
212         log_error( "pubkey_enc packet: %s\n", g10_errstr(result));
213     free_packet(pkt);
214 }
215
216
217 static void
218 proc_encrypted( CTX c, PACKET *pkt )
219 {
220     int result = 0;
221
222     /*printf("dat: %sencrypted data\n", c->dek?"":"conventional ");*/
223     if( !c->dek && !c->last_was_session_key ) {
224         /* assume this is old conventional encrypted data */
225         c->dek = m_alloc_secure( sizeof *c->dek );
226         c->dek->algo = opt.def_cipher_algo;
227         result = make_dek_from_passphrase( c->dek, 0, NULL );
228     }
229     else if( !c->dek )
230         result = G10ERR_NO_SECKEY;
231     if( !result )
232         result = decrypt_data( pkt->pkt.encrypted, c->dek );
233     m_free(c->dek); c->dek = NULL;
234     if( result == -1 )
235         ;
236     else if( !result ) {
237         if( opt.verbose > 1 )
238             log_info("encryption okay\n");
239     }
240     else {
241         log_error("encryption failed: %s\n", g10_errstr(result));
242     }
243     free_packet(pkt);
244     c->last_was_session_key = 0;
245 }
246
247
248 static void
249 proc_plaintext( CTX c, PACKET *pkt )
250 {
251     PKT_plaintext *pt = pkt->pkt.plaintext;
252     int rc;
253
254     if( opt.verbose )
255         log_info("original file name='%.*s'\n", pt->namelen, pt->name);
256     free_md_filter_context( &c->mfx );
257     /* fixme: take the digest algo(s) to use from the
258      * onepass_sig packet (if we have these)
259      * And look at the sigclass to check whether we should use the
260      * textmode filter (sigclass 0x01)
261      */
262     c->mfx.md = md_open( DIGEST_ALGO_RMD160, 0);
263     md_enable( c->mfx.md, DIGEST_ALGO_SHA1 );
264     md_enable( c->mfx.md, DIGEST_ALGO_MD5 );
265     rc = handle_plaintext( pt, &c->mfx );
266     if( rc )
267         log_error( "handle plaintext failed: %s\n", g10_errstr(rc));
268     free_packet(pkt);
269     c->last_was_session_key = 0;
270 }
271
272
273 static int
274 proc_compressed_cb( IOBUF a, void *info )
275 {
276     return proc_signature_packets( a, ((CTX)info)->signed_data );
277 }
278
279 static int
280 proc_encrypt_cb( IOBUF a, void *info )
281 {
282     return proc_encryption_packets( a );
283 }
284
285 static void
286 proc_compressed( CTX c, PACKET *pkt )
287 {
288     PKT_compressed *zd = pkt->pkt.compressed;
289     int rc;
290
291     /*printf("zip: compressed data packet\n");*/
292     if( c->sigs_only )
293         rc = handle_compressed( zd, proc_compressed_cb, c );
294     else if( c->encrypt_only )
295         rc = handle_compressed( zd, proc_encrypt_cb, c );
296     else
297         rc = handle_compressed( zd, NULL, NULL );
298     if( rc )
299         log_error("uncompressing failed: %s\n", g10_errstr(rc));
300     free_packet(pkt);
301     c->last_was_session_key = 0;
302 }
303
304
305
306
307 /****************
308  * check the signature
309  * Returns: 0 = valid signature or an error code
310  */
311 static int
312 do_check_sig( CTX c, KBNODE node )
313 {
314     PKT_signature *sig;
315     MD_HANDLE md;
316     int algo, rc;
317
318     assert( node->pkt->pkttype == PKT_SIGNATURE );
319     sig = node->pkt->pkt.signature;
320
321     algo = digest_algo_from_sig( sig );
322     if( !algo )
323         return G10ERR_PUBKEY_ALGO;
324     if( (rc=check_digest_algo(algo)) )
325         return rc;
326
327     if( sig->sig_class == 0x00 ) {
328         if( c->mfx.md )
329             md = md_copy( c->mfx.md );
330         else /* detached signature */
331             md = md_open( 0, 0 ); /* signature_check() will enable the md*/
332     }
333     else if( sig->sig_class == 0x01 ) {
334         /* how do we know that we have to hash the (already hashed) text
335          * in canonical mode ??? (calculating both modes???) */
336         if( c->mfx.md )
337             md = md_copy( c->mfx.md );
338         else /* detached signature */
339             md = md_open( 0, 0 ); /* signature_check() will enable the md*/
340     }
341     else if( (sig->sig_class&~3) == 0x10
342              || sig->sig_class == 0x18
343              || sig->sig_class == 0x20
344              || sig->sig_class == 0x30  ) { /* classes 0x10..0x17,0x20,0x30 */
345         if( c->list->pkt->pkttype == PKT_PUBLIC_CERT
346             || c->list->pkt->pkttype == PKT_PUBKEY_SUBCERT ) {
347             return check_key_signature( c->list, node, NULL );
348         }
349         else {
350             log_error("invalid root packet for sigclass %02x\n",
351                                                         sig->sig_class);
352             return G10ERR_SIG_CLASS;
353         }
354     }
355     else
356         return G10ERR_SIG_CLASS;
357     rc = signature_check( sig, md );
358     md_close(md);
359
360     return rc;
361 }
362
363
364
365 static void
366 print_userid( PACKET *pkt )
367 {
368     if( !pkt )
369         BUG();
370     if( pkt->pkttype != PKT_USER_ID ) {
371         printf("ERROR: unexpected packet type %d", pkt->pkttype );
372         return;
373     }
374     print_string( stdout,  pkt->pkt.user_id->name, pkt->pkt.user_id->len,
375                                                         opt.with_colons );
376 }
377
378
379 static void
380 print_fingerprint( PKT_public_cert *pkc, PKT_secret_cert *skc )
381 {
382     byte *array, *p;
383     size_t i, n;
384
385     p = array = skc? fingerprint_from_skc( skc, &n )
386                    : fingerprint_from_pkc( pkc, &n );
387     if( opt.with_colons ) {
388         printf("fpr:::::::::");
389         for(i=0; i < n ; i++, p++ )
390             printf("%02X", *p );
391         putchar(':');
392     }
393     else {
394         printf("     Key fingerprint =");
395         if( n == 20 ) {
396             for(i=0; i < n ; i++, i++, p += 2 ) {
397                 if( i == 10 )
398                     putchar(' ');
399                 printf(" %02X%02X", *p, p[1] );
400             }
401         }
402         else {
403             for(i=0; i < n ; i++, p++ ) {
404                 if( i && !(i%8) )
405                     putchar(' ');
406                 printf(" %02X", *p );
407             }
408         }
409     }
410     putchar('\n');
411     m_free(array);
412 }
413
414
415 /****************
416  * List the certificate in a user friendly way
417  */
418
419 static void
420 list_node( CTX c, KBNODE node )
421 {
422     int any=0;
423     int mainkey;
424
425     if( !node )
426         ;
427     else if( (mainkey = (node->pkt->pkttype == PKT_PUBLIC_CERT) )
428              || node->pkt->pkttype == PKT_PUBKEY_SUBCERT ) {
429         PKT_public_cert *pkc = node->pkt->pkt.public_cert;
430
431         if( opt.with_colons ) {
432             u32 keyid[2];
433             keyid_from_pkc( pkc, keyid );
434             printf("%s::%u:%d:%08lX%08lX:%s:%u:::",
435                     mainkey? "pub":"sub",
436                     /* fixme: add trust value here */
437                     nbits_from_pkc( pkc ),
438                     pkc->pubkey_algo,
439                     (ulong)keyid[0],(ulong)keyid[1],
440                     datestr_from_pkc( pkc ),
441                     (unsigned)pkc->valid_days
442                     /* fixme: add LID and ownertrust here */
443                                             );
444         }
445         else
446             printf("%s  %4u%c/%08lX %s ",
447                                       mainkey? "pub":"sub",
448                                       nbits_from_pkc( pkc ),
449                                       pubkey_letter( pkc->pubkey_algo ),
450                                       (ulong)keyid_from_pkc( pkc, NULL ),
451                                       datestr_from_pkc( pkc )     );
452         /* and now list all userids with their signatures */
453         for( node = node->next; node; node = node->next ) {
454             if( any != 2 && node->pkt->pkttype == PKT_SIGNATURE ) {
455                 if( !any ) {
456                     if( node->pkt->pkt.signature->sig_class == 0x20 )
457                         puts("[revoked]");
458                     else
459                         putchar('\n');
460                 }
461                 list_node(c,  node );
462                 any = 1;
463             }
464             else if( node->pkt->pkttype == PKT_USER_ID ) {
465                 KBNODE n;
466
467                 if( any ) {
468                     if( opt.with_colons )
469                         printf("uid:::::::::");
470                     else
471                         printf( "uid%*s", 28, "" );
472                 }
473                 print_userid( node->pkt );
474                 if( opt.with_colons )
475                     putchar(':');
476                 putchar('\n');
477                 if( opt.fingerprint && !any )
478                     print_fingerprint( pkc, NULL );
479                 for( n=node->next; n; n = n->next ) {
480                     if( n->pkt->pkttype == PKT_USER_ID )
481                         break;
482                     if( n->pkt->pkttype == PKT_SIGNATURE )
483                         list_node(c,  n );
484                 }
485                 any=2;
486             }
487             else if( mainkey && node->pkt->pkttype == PKT_PUBKEY_SUBCERT ) {
488                 if( !any ) {
489                     putchar('\n');
490                     any = 1;
491                 }
492                 list_node(c,  node );
493             }
494         }
495         if( any != 2 && mainkey )
496             printf("ERROR: no user id!\n");
497         else if( any != 2 )
498             putchar('\n');
499     }
500     else if( (mainkey = (node->pkt->pkttype == PKT_SECRET_CERT) )
501              || node->pkt->pkttype == PKT_SECKEY_SUBCERT ) {
502         PKT_secret_cert *skc = node->pkt->pkt.secret_cert;
503
504         printf("%s  %4u%c/%08lX %s ",
505                                       mainkey? "sec":"ssb",
506                                        nbits_from_skc( skc ),
507                                       pubkey_letter( skc->pubkey_algo ),
508                                       (ulong)keyid_from_skc( skc, NULL ),
509                                       datestr_from_skc( skc )   );
510         /* and now list all userids */
511         while( (node = find_next_kbnode(node, PKT_USER_ID)) ) {
512             print_userid( node->pkt );
513             putchar('\n');
514             if( opt.fingerprint && !any )
515                 print_fingerprint( NULL, skc );
516             any=1;
517         }
518         if( !any && mainkey )
519             printf("ERROR: no user id!\n");
520         else if( !any )
521             putchar('\n');
522     }
523     else if( node->pkt->pkttype == PKT_SIGNATURE  ) {
524         PKT_signature *sig = node->pkt->pkt.signature;
525         int rc2=0;
526         size_t n;
527         char *p;
528         int sigrc = ' ';
529
530         if( !opt.list_sigs )
531             return;
532
533         if( sig->sig_class == 0x20 || sig->sig_class == 0x30 )
534             fputs("rev", stdout);
535         else
536             fputs("sig", stdout);
537         if( opt.check_sigs ) {
538             fflush(stdout);
539             switch( (rc2=do_check_sig( c, node )) ) {
540               case 0:                  sigrc = '!'; break;
541               case G10ERR_BAD_SIGN:    sigrc = '-'; break;
542               case G10ERR_NO_PUBKEY:   sigrc = '?'; break;
543               default:                 sigrc = '%'; break;
544             }
545         }
546         if( opt.with_colons ) {
547             putchar(':');
548             if( sigrc != ' ' )
549                 putchar(sigrc);
550             printf(":::%08lX%08lX:%s::::", (ulong)sig->keyid[0],
551                        (ulong)sig->keyid[1], datestr_from_sig(sig));
552         }
553         else
554             printf("%c       %08lX %s   ",
555                     sigrc, (ulong)sig->keyid[1], datestr_from_sig(sig));
556         if( sigrc == '%' )
557             printf("[%s] ", g10_errstr(rc2) );
558         else if( sigrc == '?' )
559             ;
560         else {
561             p = get_user_id( sig->keyid, &n );
562             print_string( stdout, p, n, opt.with_colons );
563             m_free(p);
564         }
565         if( opt.with_colons )
566             printf(":%02x:", sig->sig_class );
567         putchar('\n');
568     }
569     else
570         log_error("invalid node with packet of type %d\n", node->pkt->pkttype);
571 }
572
573
574 int
575 proc_packets( IOBUF a )
576 {
577     CTX c = m_alloc_clear( sizeof *c );
578     int rc = do_proc_packets( c, a );
579     m_free( c );
580     return rc;
581 }
582
583 int
584 proc_signature_packets( IOBUF a, STRLIST signedfiles )
585 {
586     CTX c = m_alloc_clear( sizeof *c );
587     int rc;
588     c->sigs_only = 1;
589     c->signed_data = signedfiles;
590     rc = do_proc_packets( c, a );
591     m_free( c );
592     return rc;
593 }
594
595 int
596 proc_encryption_packets( IOBUF a )
597 {
598     CTX c = m_alloc_clear( sizeof *c );
599     int rc;
600     c->encrypt_only = 1;
601     rc = do_proc_packets( c, a );
602     m_free( c );
603     return rc;
604 }
605
606
607 int
608 do_proc_packets( CTX c, IOBUF a )
609 {
610     PACKET *pkt = m_alloc( sizeof *pkt );
611     int rc=0;
612     int newpkt;
613
614     c->iobuf = a;
615     init_packet(pkt);
616     while( (rc=parse_packet(a, pkt)) != -1 ) {
617         /* cleanup if we have an illegal data structure */
618         if( c->dek && pkt->pkttype != PKT_ENCRYPTED ) {
619             log_error("oops: valid pubkey enc packet not followed by data\n");
620             m_free(c->dek); c->dek = NULL; /* burn it */
621         }
622
623         if( rc ) {
624             free_packet(pkt);
625             if( rc == G10ERR_INVALID_PACKET )
626                 break;
627             continue;
628         }
629         newpkt = -1;
630         if( opt.list_packets ) {
631             switch( pkt->pkttype ) {
632               case PKT_PUBKEY_ENC:  proc_pubkey_enc( c, pkt ); break;
633               case PKT_ENCRYPTED:   proc_encrypted( c, pkt ); break;
634               case PKT_COMPRESSED:  proc_compressed( c, pkt ); break;
635               default: newpkt = 0; break;
636             }
637         }
638         else if( c->sigs_only ) {
639             switch( pkt->pkttype ) {
640               case PKT_PUBLIC_CERT:
641               case PKT_SECRET_CERT:
642               case PKT_USER_ID:
643               case PKT_SYMKEY_ENC:
644               case PKT_PUBKEY_ENC:
645               case PKT_ENCRYPTED:
646                 rc = G10ERR_UNEXPECTED;
647                 goto leave;
648               case PKT_SIGNATURE:   newpkt = add_signature( c, pkt ); break;
649               case PKT_PLAINTEXT:   proc_plaintext( c, pkt ); break;
650               case PKT_COMPRESSED:  proc_compressed( c, pkt ); break;
651               case PKT_ONEPASS_SIG: newpkt = add_onepass_sig( c, pkt ); break;
652               default: newpkt = 0; break;
653             }
654         }
655         else if( c->encrypt_only ) {
656             switch( pkt->pkttype ) {
657               case PKT_PUBLIC_CERT:
658               case PKT_SECRET_CERT:
659               case PKT_USER_ID:
660                 rc = G10ERR_UNEXPECTED;
661                 goto leave;
662               case PKT_SIGNATURE:   newpkt = add_signature( c, pkt ); break;
663               case PKT_SYMKEY_ENC:  proc_symkey_enc( c, pkt ); break;
664               case PKT_PUBKEY_ENC:  proc_pubkey_enc( c, pkt ); break;
665               case PKT_ENCRYPTED:   proc_encrypted( c, pkt ); break;
666               case PKT_PLAINTEXT:   proc_plaintext( c, pkt ); break;
667               case PKT_COMPRESSED:  proc_compressed( c, pkt ); break;
668               case PKT_ONEPASS_SIG: newpkt = add_onepass_sig( c, pkt ); break;
669               default: newpkt = 0; break;
670             }
671         }
672         else {
673             switch( pkt->pkttype ) {
674               case PKT_PUBLIC_CERT:
675               case PKT_SECRET_CERT:
676                 release_list( c );
677                 c->list = new_kbnode( pkt );
678                 newpkt = 1;
679                 break;
680               case PKT_PUBKEY_SUBCERT:
681               case PKT_SECKEY_SUBCERT:
682                 newpkt = add_subkey( c, pkt );
683                 break;
684               case PKT_USER_ID:     newpkt = add_user_id( c, pkt ); break;
685               case PKT_SIGNATURE:   newpkt = add_signature( c, pkt ); break;
686               case PKT_PUBKEY_ENC:  proc_pubkey_enc( c, pkt ); break;
687               case PKT_SYMKEY_ENC:  proc_symkey_enc( c, pkt ); break;
688               case PKT_ENCRYPTED:   proc_encrypted( c, pkt ); break;
689               case PKT_PLAINTEXT:   proc_plaintext( c, pkt ); break;
690               case PKT_COMPRESSED:  proc_compressed( c, pkt ); break;
691               case PKT_ONEPASS_SIG: newpkt = add_onepass_sig( c, pkt ); break;
692               default: newpkt = 0; break;
693             }
694         }
695         if( pkt->pkttype != PKT_SIGNATURE )
696             c->have_data = pkt->pkttype == PKT_PLAINTEXT;
697
698         if( newpkt == -1 )
699             ;
700         else if( newpkt ) {
701             pkt = m_alloc( sizeof *pkt );
702             init_packet(pkt);
703         }
704         else
705             free_packet(pkt);
706     }
707     rc = 0;
708
709   leave:
710     release_list( c );
711     m_free(c->dek);
712     free_packet( pkt );
713     m_free( pkt );
714     free_md_filter_context( &c->mfx );
715     return rc;
716 }
717
718
719 static void
720 print_keyid( FILE *fp, u32 *keyid )
721 {
722     size_t n;
723     char *p = get_user_id( keyid, &n );
724     print_string( fp, p, n, opt.with_colons );
725     m_free(p);
726 }
727
728
729
730 static int
731 check_sig_and_print( CTX c, KBNODE node )
732 {
733     PKT_signature *sig = node->pkt->pkt.signature;
734     int rc;
735
736     if( opt.skip_verify ) {
737         log_info("signature verification suppressed\n");
738         return 0;
739     }
740
741     rc = do_check_sig(c, node );
742     if( !rc || rc == G10ERR_BAD_SIGN ) {
743         char *p, *buf;
744
745         p = get_user_id_string( sig->keyid );
746         buf = m_alloc( 20 + strlen(p) );
747         sprintf(buf, "%lu %s", (ulong)sig->timestamp, p );
748         m_free(p);
749         if( (p=strchr(buf,'\n')) )
750             *p = 0; /* just in case ... */
751         write_status_text( rc? STATUS_BADSIG : STATUS_GOODSIG, buf );
752         m_free(buf);
753         log_info("%s signature from ", rc? "BAD":"Good");
754         print_keyid( stderr, sig->keyid );
755         putc('\n', stderr);
756         if( opt.batch && rc )
757             g10_exit(1);
758     }
759     else {
760         write_status( STATUS_ERRSIG );
761         log_error("Can't check signature made by %08lX: %s\n",
762                    (ulong)sig->keyid[1], g10_errstr(rc) );
763     }
764     return rc;
765 }
766
767
768 /****************
769  * Process the tree which starts at node
770  */
771 static void
772 proc_tree( CTX c, KBNODE node )
773 {
774     KBNODE n1;
775     int rc;
776
777     if( opt.list_packets )
778         return;
779
780     if( node->pkt->pkttype == PKT_PUBLIC_CERT
781         || node->pkt->pkttype == PKT_PUBKEY_SUBCERT )
782         list_node( c, node );
783     else if( node->pkt->pkttype == PKT_SECRET_CERT )
784         list_node( c, node );
785     else if( node->pkt->pkttype == PKT_ONEPASS_SIG ) {
786         /* check all signatures */
787         if( !c->have_data ) {
788             free_md_filter_context( &c->mfx );
789             /* prepare to create all requested message digests */
790             c->mfx.md = md_open(0, 0);
791             /* fixme: why looking for the signature packet and not 1passpacket*/
792             for( n1 = node; (n1 = find_next_kbnode(n1, PKT_SIGNATURE )); ) {
793                 md_enable( c->mfx.md,
794                            digest_algo_from_sig(n1->pkt->pkt.signature));
795             }
796             /* ask for file and hash it */
797             if( c->sigs_only )
798                 rc = hash_datafiles( c->mfx.md, c->signed_data,
799                             n1->pkt->pkt.onepass_sig->sig_class == 0x01 );
800             else
801                 rc = ask_for_detached_datafile( &c->mfx,
802                                             iobuf_get_fname(c->iobuf));
803             if( rc ) {
804                 log_error("can't hash datafile: %s\n", g10_errstr(rc));
805                 return;
806             }
807         }
808
809         for( n1 = node; (n1 = find_next_kbnode(n1, PKT_SIGNATURE )); )
810             check_sig_and_print( c, n1 );
811     }
812     else if( node->pkt->pkttype == PKT_SIGNATURE ) {
813         PKT_signature *sig = node->pkt->pkt.signature;
814
815         if( !c->have_data ) {
816             free_md_filter_context( &c->mfx );
817             c->mfx.md = md_open(digest_algo_from_sig(sig), 0);
818             if( c->sigs_only )
819                 rc = hash_datafiles( c->mfx.md, c->signed_data,
820                                      sig->sig_class == 0x01 );
821             else
822                 rc = ask_for_detached_datafile( &c->mfx,
823                                             iobuf_get_fname(c->iobuf));
824             if( rc ) {
825                 log_error("can't hash datafile: %s\n", g10_errstr(rc));
826                 return;
827             }
828         }
829         else
830             log_info("old style signature\n");
831
832         check_sig_and_print( c, node );
833     }
834     else
835         log_error("proc_tree: invalid root packet\n");
836
837 }
838
839
840