0055200b4782389c289d69d807bdaf89ad0a0439
[gnupg.git] / g10 / mainproc.c
1 /* mainproc.c - handle 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
25 #include "packet.h"
26 #include "iobuf.h"
27 #include "memory.h"
28 #include "options.h"
29 #include "util.h"
30 #include "cipher.h"
31 #include "keydb.h"
32
33
34 static int opt_list=1;  /* and list the data packets to stdout */
35
36 int
37 proc_packets( IOBUF a )
38 {
39     PACKET *pkt;
40     PKT_pubkey_cert *last_pubkey = NULL;
41     PKT_seckey_cert *last_seckey = NULL;
42     PKT_user_id     *last_user_id = NULL;
43     DEK *dek = NULL;
44     PKT_signature *sig; /* CHECK: "might be used uninitialied" */
45     int rc, result;
46     MD_HANDLE md_handle; /* union to pass handles */
47     char *ustr;
48     int lvl0, lvl1;
49     int last_was_pubkey_enc = 0;
50     u32 keyid[2];
51
52     lvl0 = opt.check_sigs? 1:0; /* stdout or /dev/null */
53     lvl1 = opt.check_sigs? 1:3; /* stdout or error */
54     pkt = m_alloc( sizeof *pkt );
55     init_packet(pkt);
56     while( (rc=parse_packet(a, pkt)) != -1 ) {
57         if( dek && pkt->pkttype != PKT_ENCR_DATA ) {
58             log_error("oops: valid pubkey enc packet not followed by data\n");
59             m_free(dek); dek = NULL; /* burn it */
60         }
61
62         if( rc )
63             free_packet(pkt);
64         else if( pkt->pkttype == PKT_PUBKEY_CERT ) {
65             if( last_user_id ) {
66                 free_user_id( last_user_id );
67                 last_user_id = NULL;
68             }
69             if( last_pubkey ) {
70                 free_pubkey_cert( last_pubkey );
71                 last_pubkey = NULL;
72             }
73             if( opt.check_sigs ) {
74                 ustr = get_user_id_string(sig->keyid);
75                 printstr(lvl0, "pub: %s\n", ustr );
76                 m_free(ustr);
77             }
78             else
79                 fputs( "pub: [Public Key Cerificate]\n", stdout );
80             last_pubkey = pkt->pkt.pubkey_cert;
81             pkt->pkt.pubkey_cert = NULL;
82             free_packet(pkt);
83             pkt->pkc_parent = last_pubkey; /* set this as parent */
84         }
85         else if( pkt->pkttype == PKT_SECKEY_CERT ) {
86             if( last_user_id ) {
87                 free_user_id( last_user_id );
88                 last_user_id = NULL;
89             }
90             if( last_seckey ) {
91                 free_seckey_cert( last_seckey );
92                 last_seckey = NULL;
93             }
94             if( opt_list )
95                 fputs( "sec: (secret key certificate)\n", stdout );
96             rc = check_secret_key( pkt->pkt.seckey_cert );
97             if( opt_list ) {
98                 if( !rc )
99                     fputs( "     Secret key is good", stdout );
100                 else
101                     fputs( g10_errstr(rc), stdout);
102                 putchar('\n');
103             }
104             else if( rc )
105                 log_error("secret key certificate error: %s\n", g10_errstr(rc));
106             last_seckey = pkt->pkt.seckey_cert;
107             pkt->pkt.seckey_cert = NULL;
108             free_packet(pkt);
109             pkt->skc_parent = last_seckey; /* set this as parent */
110         }
111         else if( pkt->pkttype == PKT_USER_ID ) {
112             if( last_user_id ) {
113                 free_user_id( last_user_id );
114                 last_user_id = NULL;
115             }
116             if( opt_list ) {
117                  printf("uid: '%.*s'\n", pkt->pkt.user_id->len,
118                                          pkt->pkt.user_id->name );
119                  if( !pkt->pkc_parent && !pkt->skc_parent )
120                      puts("      (orphaned)");
121             }
122             if( pkt->pkc_parent ) {
123                 if( pkt->pkc_parent->pubkey_algo == PUBKEY_ALGO_RSA ) {
124                     mpi_get_keyid( pkt->pkc_parent->d.rsa.rsa_n, keyid );
125                     cache_user_id( pkt->pkt.user_id, keyid );
126                 }
127             }
128
129             last_user_id = pkt->pkt.user_id;  /* save */
130             pkt->pkt.user_id = NULL;
131             free_packet(pkt);   /* fixme: free_packet is not a good name */
132             pkt->user_parent = last_user_id;  /* and set this as user */
133         }
134         else if( pkt->pkttype == PKT_SIGNATURE ) {
135             sig = pkt->pkt.signature;
136             ustr = get_user_id_string(sig->keyid);
137             result = -1;
138             if( sig->sig_class != 0x10 )
139                 printstr(lvl1,"sig?: %s: unknown signature class %02x\n",
140                                         ustr, sig->sig_class);
141             else if( !pkt->pkc_parent || !pkt->user_parent )
142                 printstr(lvl1,"sig?: %s: orphaned encoded packet\n", ustr);
143             else
144                 result = 0;
145
146             if( result )
147                 ;
148             else if( !opt.check_sigs ) {
149                 result = -1;
150                 printstr(lvl0, "sig: from %s\n", ustr );
151             }
152             else if(sig->pubkey_algo == PUBKEY_ALGO_RSA ) {
153                 md_handle.algo = sig->d.rsa.digest_algo;
154                 if( sig->d.rsa.digest_algo == DIGEST_ALGO_RMD160 ) {
155                     md_handle.u.rmd = rmd160_copy(pkt->pkc_parent->mfx.rmd160);
156                     rmd160_write(md_handle.u.rmd, pkt->user_parent->name,
157                                                   pkt->user_parent->len);
158                     result = signature_check( sig, md_handle );
159                     rmd160_close(md_handle.u.rmd);
160                 }
161                 else if( sig->d.rsa.digest_algo == DIGEST_ALGO_MD5 ) {
162                     md_handle.u.md5 = md5_copy(pkt->pkc_parent->mfx.md5);
163                     md5_write(md_handle.u.md5, pkt->user_parent->name,
164                                                pkt->user_parent->len);
165                     result = signature_check( sig, md_handle );
166                     md5_close(md_handle.u.md5);
167                 }
168                 else
169                     result = G10ERR_DIGEST_ALGO;
170             }
171             else
172                 result = G10ERR_PUBKEY_ALGO;
173
174             if( result == -1 )
175                 ;
176             else if( !result )
177                 printstr(lvl0, "sig: good signature from %s\n", ustr );
178             else
179                 printstr(lvl1, "sig? %s: %s\n", ustr, g10_errstr(result));
180             free_packet(pkt);
181             m_free(ustr);
182         }
183         else if( pkt->pkttype == PKT_PUBKEY_ENC ) {
184             PKT_pubkey_enc *enc;
185
186             last_was_pubkey_enc = 1;
187             result = 0;
188             enc = pkt->pkt.pubkey_enc;
189             printf("enc: encrypted by a pubkey with keyid %08lX\n",
190                                                         enc->keyid[1] );
191             if( enc->pubkey_algo == PUBKEY_ALGO_RSA ) {
192                 m_free(dek ); /* paranoid: delete a pending DEK */
193                 dek = m_alloc_secure( sizeof *dek );
194                 if( (result = get_session_key( enc, dek )) ) {
195                     /* error: delete the DEK */
196                     m_free(dek); dek = NULL;
197                 }
198             }
199             else
200                 result = G10ERR_PUBKEY_ALGO;
201
202             if( result == -1 )
203                 ;
204             else if( !result )
205                 fputs(  "     DEK is good", stdout );
206             else
207                 printf( "     %s", g10_errstr(result));
208             putchar('\n');
209             free_packet(pkt);
210         }
211         else if( pkt->pkttype == PKT_ENCR_DATA ) {
212             result = 0;
213             printf("dat: %sencrypted data\n", dek?"":"conventional ");
214             if( !dek && !last_was_pubkey_enc ) {
215                 /* assume this is conventional encrypted data */
216                 dek = m_alloc_secure( sizeof *dek );
217                 dek->algo = DEFAULT_CIPHER_ALGO;
218                 result = make_dek_from_passphrase( dek, 0 );
219             }
220             else if( !dek )
221                 result = G10ERR_NO_SECKEY;
222             if( !result )
223                 result = decrypt_data( pkt->pkt.encr_data, dek );
224             m_free(dek); dek = NULL;
225             if( result == -1 )
226                 ;
227             else if( !result )
228                 fputs(  "     encryption okay",stdout);
229             else
230                 printf( "     %s", g10_errstr(result));
231             putchar('\n');
232             free_packet(pkt);
233             last_was_pubkey_enc = 0;
234         }
235         else if( pkt->pkttype == PKT_PLAINTEXT ) {
236             PKT_plaintext *pt = pkt->pkt.plaintext;
237             printf("txt: plain text data name='%.*s'\n", pt->namelen, pt->name);
238             result = handle_plaintext( pt );
239             if( !result )
240                 fputs(  "     okay",stdout);
241             else
242                 printf( "     %s", g10_errstr(result));
243             putchar('\n');
244             free_packet(pkt);
245             last_was_pubkey_enc = 0;
246         }
247         else if( pkt->pkttype == PKT_COMPR_DATA ) {
248             PKT_compressed *zd = pkt->pkt.compressed;
249             printf("zip: compressed data packet\n");
250             result = handle_compressed( zd );
251             if( !result )
252                 fputs(  "     okay",stdout);
253             else
254                 printf( "     %s", g10_errstr(result));
255             putchar('\n');
256             free_packet(pkt);
257             last_was_pubkey_enc = 0;
258         }
259         else
260             free_packet(pkt);
261     }
262
263     if( last_user_id )
264         free_user_id( last_user_id );
265     if( last_seckey )
266         free_seckey_cert( last_seckey );
267     if( last_pubkey )
268         free_pubkey_cert( last_pubkey );
269     m_free(dek);
270     free_packet( pkt );
271     m_free( pkt );
272     return 0;
273 }
274
275