Pth tweaks and improved estream.c
[gnupg.git] / g10 / free-packet.c
1 /* free-packet.c - cleanup stuff for packets
2  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003,
3  *               2005  Free Software Foundation, Inc.
4  *
5  * This file is part of GnuPG.
6  *
7  * GnuPG is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * GnuPG is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20  * USA.
21  */
22
23 #include <config.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <assert.h>
28
29 #include "gpg.h"
30 #include "packet.h"
31 #include "../common/iobuf.h"
32 #include "util.h"
33 #include "cipher.h"
34 #include "options.h" 
35
36
37 void
38 free_symkey_enc( PKT_symkey_enc *enc )
39 {
40     xfree(enc);
41 }
42
43 void
44 free_pubkey_enc( PKT_pubkey_enc *enc )
45 {
46     int n, i;
47     n = pubkey_get_nenc( enc->pubkey_algo );
48     if( !n )
49         mpi_release(enc->data[0]);
50     for(i=0; i < n; i++ )
51         mpi_release( enc->data[i] );
52     xfree(enc);
53 }
54
55 void
56 free_seckey_enc( PKT_signature *sig )
57 {
58   int n, i;
59
60   n = pubkey_get_nsig( sig->pubkey_algo );
61   if( !n )
62     mpi_release(sig->data[0]);
63   for(i=0; i < n; i++ )
64     mpi_release( sig->data[i] );
65
66   xfree(sig->revkey);
67   xfree(sig->hashed);
68   xfree(sig->unhashed);
69
70   if (sig->pka_info)
71     {
72       xfree (sig->pka_info->uri);
73       xfree (sig->pka_info);
74     }
75
76   xfree(sig);
77 }
78
79
80 void
81 release_public_key_parts( PKT_public_key *pk )
82 {
83     int n, i;
84     n = pubkey_get_npkey( pk->pubkey_algo );
85     if( !n )
86         mpi_release(pk->pkey[0]);
87     for(i=0; i < n; i++ ) {
88         mpi_release( pk->pkey[i] );
89         pk->pkey[i] = NULL;
90     }
91     if (pk->prefs) {
92         xfree (pk->prefs);
93         pk->prefs = NULL;
94     }
95     if (pk->user_id) {
96         free_user_id (pk->user_id);
97         pk->user_id = NULL;
98     }
99     if (pk->revkey) {
100         xfree(pk->revkey);
101         pk->revkey=NULL;
102         pk->numrevkeys=0;
103     }
104 }
105
106
107 void
108 free_public_key( PKT_public_key *pk )
109 {
110     release_public_key_parts( pk );
111     xfree(pk);
112 }
113
114
115 static subpktarea_t *
116 cp_subpktarea (subpktarea_t *s )
117 {
118     subpktarea_t *d;
119
120     if( !s )
121         return NULL;
122     d = xmalloc (sizeof (*d) + s->size - 1 );
123     d->size = s->size;
124     d->len = s->len;
125     memcpy (d->data, s->data, s->len);
126     return d;
127 }
128
129 /*
130  * Return a copy of the preferences 
131  */
132 prefitem_t *
133 copy_prefs (const prefitem_t *prefs)
134 {
135     size_t n;
136     prefitem_t *new;
137
138     if (!prefs)
139         return NULL;
140     
141     for (n=0; prefs[n].type; n++)
142         ;
143     new = xmalloc ( sizeof (*new) * (n+1));
144     for (n=0; prefs[n].type; n++) {
145         new[n].type = prefs[n].type;
146         new[n].value = prefs[n].value;
147     }
148     new[n].type = PREFTYPE_NONE;
149     new[n].value = 0;
150
151     return new;
152 }
153
154
155 PKT_public_key *
156 copy_public_key ( PKT_public_key *d, PKT_public_key *s)
157 {
158     int n, i;
159
160     if( !d )
161         d = xmalloc(sizeof *d);
162     memcpy( d, s, sizeof *d );
163     d->user_id = scopy_user_id (s->user_id);
164     d->prefs = copy_prefs (s->prefs);
165     n = pubkey_get_npkey( s->pubkey_algo );
166     if( !n )
167         d->pkey[0] = mpi_copy(s->pkey[0]);
168     else {
169         for(i=0; i < n; i++ )
170             d->pkey[i] = mpi_copy( s->pkey[i] );
171     }
172     if( !s->revkey && s->numrevkeys )
173         BUG();
174     if( s->numrevkeys ) {
175         d->revkey = xmalloc(sizeof(struct revocation_key)*s->numrevkeys);
176         memcpy(d->revkey,s->revkey,sizeof(struct revocation_key)*s->numrevkeys);
177     }
178     else
179         d->revkey = NULL;
180     return d;
181 }
182
183 /****************
184  * Replace all common parts of a sk by the one from the public key.
185  * This is a hack and a better solution will be to just store the real secret
186  * parts somewhere and don't duplicate all the other stuff.
187  */
188 void
189 copy_public_parts_to_secret_key( PKT_public_key *pk, PKT_secret_key *sk )
190 {
191     sk->expiredate  = pk->expiredate;     
192     sk->pubkey_algo = pk->pubkey_algo;    
193     sk->pubkey_usage= pk->pubkey_usage;
194     sk->req_usage   = pk->req_usage;
195     sk->req_algo    = pk->req_algo;
196     sk->has_expired = pk->has_expired;    
197     sk->is_revoked  = pk->is_revoked;     
198     sk->is_valid    = pk->is_valid;    
199     sk->main_keyid[0]= pk->main_keyid[0];
200     sk->main_keyid[1]= pk->main_keyid[1];
201     sk->keyid[0]    = pk->keyid[0];
202     sk->keyid[1]    = pk->keyid[1];
203 }
204
205
206 static pka_info_t *
207 cp_pka_info (const pka_info_t *s)
208 {
209   pka_info_t *d = xmalloc (sizeof *s + strlen (s->email));
210   
211   d->valid = s->valid;
212   d->checked = s->checked;
213   d->uri = s->uri? xstrdup (s->uri):NULL;
214   memcpy (d->fpr, s->fpr, sizeof s->fpr);
215   strcpy (d->email, s->email);
216   return d;
217 }
218
219
220 PKT_signature *
221 copy_signature( PKT_signature *d, PKT_signature *s )
222 {
223     int n, i;
224
225     if( !d )
226         d = xmalloc(sizeof *d);
227     memcpy( d, s, sizeof *d );
228     n = pubkey_get_nsig( s->pubkey_algo );
229     if( !n )
230         d->data[0] = mpi_copy(s->data[0]);
231     else {
232         for(i=0; i < n; i++ )
233             d->data[i] = mpi_copy( s->data[i] );
234     }
235     d->pka_info = s->pka_info? cp_pka_info (s->pka_info) : NULL;
236     d->hashed = cp_subpktarea (s->hashed);
237     d->unhashed = cp_subpktarea (s->unhashed);
238     if(s->numrevkeys)
239       {
240         d->revkey=NULL;
241         d->numrevkeys=0;
242         parse_revkeys(d);
243       }
244     return d;
245 }
246
247
248 /*
249  * shallow copy of the user ID
250  */
251 PKT_user_id *
252 scopy_user_id (PKT_user_id *s)
253 {
254     if (s)
255         s->ref++;
256     return s;
257 }
258
259
260
261 void
262 release_secret_key_parts( PKT_secret_key *sk )
263 {
264     int n, i;
265
266     n = pubkey_get_nskey( sk->pubkey_algo );
267     if( !n )
268         mpi_release(sk->skey[0]);
269     for(i=0; i < n; i++ ) {
270         mpi_release( sk->skey[i] );
271         sk->skey[i] = NULL;
272     }
273 }
274
275 void
276 free_secret_key( PKT_secret_key *sk )
277 {
278     release_secret_key_parts( sk );
279     xfree(sk);
280 }
281
282 PKT_secret_key *
283 copy_secret_key( PKT_secret_key *d, PKT_secret_key *s )
284 {
285     int n, i;
286
287     if( !d )
288         d = xmalloc_secure(sizeof *d);
289     else
290         release_secret_key_parts (d);
291     memcpy( d, s, sizeof *d );
292     n = pubkey_get_nskey( s->pubkey_algo );
293     if( !n )
294         d->skey[0] = mpi_copy(s->skey[0]);
295     else {
296         for(i=0; i < n; i++ )
297             d->skey[i] = mpi_copy( s->skey[i] );
298     }
299
300     return d;
301 }
302
303 void
304 free_comment( PKT_comment *rem )
305 {
306     xfree(rem);
307 }
308
309 void
310 free_attributes(PKT_user_id *uid)
311 {
312   xfree(uid->attribs);
313   xfree(uid->attrib_data);
314
315   uid->attribs=NULL;
316   uid->attrib_data=NULL;
317   uid->attrib_len=0;
318 }
319
320 void
321 free_user_id (PKT_user_id *uid)
322 {
323     assert (uid->ref > 0);
324     if (--uid->ref)
325         return;
326
327     free_attributes(uid);
328     xfree (uid->prefs);
329     xfree (uid->namehash);
330     xfree (uid);
331 }
332
333 void
334 free_compressed( PKT_compressed *zd )
335 {
336     if( zd->buf ) { /* have to skip some bytes */
337         /* don't have any information about the length, so
338          * we assume this is the last packet */
339         while( iobuf_read( zd->buf, NULL, 1<<30 ) != -1 )
340             ;
341     }
342     xfree(zd);
343 }
344
345 void
346 free_encrypted( PKT_encrypted *ed )
347 {
348     if( ed->buf ) { /* have to skip some bytes */
349         if( ed->is_partial ) {
350             while( iobuf_read( ed->buf, NULL, 1<<30 ) != -1 )
351                 ;
352         }
353         else {
354            while( ed->len ) { /* skip the packet */
355                int n = iobuf_read( ed->buf, NULL, ed->len );
356                if( n == -1 )
357                    ed->len = 0;
358                else
359                    ed->len -= n;
360            }
361         }
362     }
363     xfree(ed);
364 }
365
366
367 void
368 free_plaintext( PKT_plaintext *pt )
369 {
370     if( pt->buf ) { /* have to skip some bytes */
371         if( pt->is_partial ) {
372             while( iobuf_read( pt->buf, NULL, 1<<30 ) != -1 )
373                 ;
374         }
375         else {
376            while( pt->len ) { /* skip the packet */
377                int n = iobuf_read( pt->buf, NULL, pt->len );
378                if( n == -1 )
379                    pt->len = 0;
380                else
381                    pt->len -= n;
382            }
383         }
384     }
385     xfree(pt);
386 }
387
388 /****************
389  * Free the packet in pkt.
390  */
391 void
392 free_packet( PACKET *pkt )
393 {
394     if( !pkt || !pkt->pkt.generic )
395         return;
396
397     if( DBG_MEMORY )
398         log_debug("free_packet() type=%d\n", pkt->pkttype );
399
400     switch( pkt->pkttype ) {
401       case PKT_SIGNATURE:
402         free_seckey_enc( pkt->pkt.signature );
403         break;
404       case PKT_PUBKEY_ENC:
405         free_pubkey_enc( pkt->pkt.pubkey_enc );
406         break;
407       case PKT_SYMKEY_ENC:
408         free_symkey_enc( pkt->pkt.symkey_enc );
409         break;
410       case PKT_PUBLIC_KEY:
411       case PKT_PUBLIC_SUBKEY:
412         free_public_key( pkt->pkt.public_key );
413         break;
414       case PKT_SECRET_KEY:
415       case PKT_SECRET_SUBKEY:
416         free_secret_key( pkt->pkt.secret_key );
417         break;
418       case PKT_COMMENT:
419         free_comment( pkt->pkt.comment );
420         break;
421       case PKT_USER_ID:
422         free_user_id( pkt->pkt.user_id );
423         break;
424       case PKT_COMPRESSED:
425         free_compressed( pkt->pkt.compressed);
426         break;
427       case PKT_ENCRYPTED:
428       case PKT_ENCRYPTED_MDC:
429         free_encrypted( pkt->pkt.encrypted );
430         break;
431       case PKT_PLAINTEXT:
432         free_plaintext( pkt->pkt.plaintext );
433         break;
434       default:
435         xfree( pkt->pkt.generic );
436         break;
437     }
438     pkt->pkt.generic = NULL;
439 }
440
441 /****************
442  * returns 0 if they match.
443  */
444 int
445 cmp_public_keys( PKT_public_key *a, PKT_public_key *b )
446 {
447     int n, i;
448
449     if( a->timestamp != b->timestamp )
450         return -1;
451     if( a->version < 4 && a->expiredate != b->expiredate )
452         return -1;
453     if( a->pubkey_algo != b->pubkey_algo )
454         return -1;
455
456     n = pubkey_get_npkey( b->pubkey_algo );
457     if( !n )
458         return -1; /* can't compare due to unknown algorithm */
459     for(i=0; i < n; i++ ) {
460         if( mpi_cmp( a->pkey[i], b->pkey[i] ) )
461             return -1;
462     }
463
464     return 0;
465 }
466
467 /****************
468  * Returns 0 if they match.
469  * We only compare the public parts.
470  */
471 int
472 cmp_secret_keys( PKT_secret_key *a, PKT_secret_key *b )
473 {
474     int n, i;
475
476     if( a->timestamp != b->timestamp )
477         return -1;
478     if( a->version < 4 && a->expiredate != b->expiredate )
479         return -1;
480     if( a->pubkey_algo != b->pubkey_algo )
481         return -1;
482
483     n = pubkey_get_npkey( b->pubkey_algo );
484     if( !n )
485         return -1; /* can't compare due to unknown algorithm */
486     for(i=0; i < n; i++ ) {
487         if( mpi_cmp( a->skey[i], b->skey[i] ) )
488             return -1;
489     }
490
491     return 0;
492 }
493
494 /****************
495  * Returns 0 if they match.
496  */
497 int
498 cmp_public_secret_key( PKT_public_key *pk, PKT_secret_key *sk )
499 {
500     int n, i;
501
502     if( pk->timestamp != sk->timestamp )
503         return -1;
504     if( pk->version < 4 && pk->expiredate != sk->expiredate )
505         return -1;
506     if( pk->pubkey_algo != sk->pubkey_algo )
507         return -1;
508
509     n = pubkey_get_npkey( pk->pubkey_algo );
510     if( !n )
511         return -1; /* can't compare due to unknown algorithm */
512     for(i=0; i < n; i++ ) {
513         if( mpi_cmp( pk->pkey[i] , sk->skey[i] ) )
514             return -1;
515     }
516     return 0;
517 }
518
519
520
521 int
522 cmp_signatures( PKT_signature *a, PKT_signature *b )
523 {
524     int n, i;
525
526     if( a->keyid[0] != b->keyid[0] )
527         return -1;
528     if( a->keyid[1] != b->keyid[1] )
529         return -1;
530     if( a->pubkey_algo != b->pubkey_algo )
531         return -1;
532
533     n = pubkey_get_nsig( a->pubkey_algo );
534     if( !n )
535         return -1; /* can't compare due to unknown algorithm */
536     for(i=0; i < n; i++ ) {
537         if( mpi_cmp( a->data[i] , b->data[i] ) )
538             return -1;
539     }
540     return 0;
541 }
542
543
544 /****************
545  * Returns: true if the user ids do not match
546  */
547 int
548 cmp_user_ids( PKT_user_id *a, PKT_user_id *b )
549 {
550     int res=1;
551
552     if( a == b )
553         return 0;
554
555     if( a->attrib_data && b->attrib_data )
556       {
557         res = a->attrib_len - b->attrib_len;
558         if( !res )
559           res = memcmp( a->attrib_data, b->attrib_data, a->attrib_len );
560       }
561     else if( !a->attrib_data && !b->attrib_data )
562       {
563         res = a->len - b->len;
564         if( !res )
565           res = memcmp( a->name, b->name, a->len );
566       }
567
568     return res;
569 }