g10: Fix keybox-related memory leaks.
[gnupg.git] / g10 / free-packet.c
index 2675684..3883f87 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <assert.h>
 
 #include "gpg.h"
 #include "util.h"
 #include "packet.h"
 #include "../common/iobuf.h"
-#include "cipher.h"
 #include "options.h"
 
 
+/* This is mpi_copy with a fix for opaque MPIs which store a NULL
+   pointer.  This will also be fixed in Libggcrypt 1.7.0.  */
+static gcry_mpi_t
+my_mpi_copy (gcry_mpi_t a)
+{
+  if (a
+      && gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE)
+      && !gcry_mpi_get_opaque (a, NULL))
+    return NULL;
+
+  return gcry_mpi_copy (a);
+}
+
+
 void
 free_symkey_enc( PKT_symkey_enc *enc )
 {
@@ -70,6 +82,7 @@ free_seckey_enc( PKT_signature *sig )
       xfree (sig->pka_info->uri);
       xfree (sig->pka_info);
     }
+  xfree (sig->signers_uid);
 
   xfree(sig);
 }
@@ -120,11 +133,16 @@ release_public_key_parts (PKT_public_key *pk)
 }
 
 
+/* Free an allocated public key structure including all parts.
+   Passing NULL is allowed.  */
 void
 free_public_key (PKT_public_key *pk)
 {
-  release_public_key_parts (pk);
-  xfree(pk);
+  if (pk)
+    {
+      release_public_key_parts (pk);
+      xfree(pk);
+    }
 }
 
 
@@ -186,11 +204,11 @@ copy_public_key (PKT_public_key *d, PKT_public_key *s)
   n = pubkey_get_npkey (s->pubkey_algo);
   i = 0;
   if (!n)
-    d->pkey[i++] = mpi_copy (s->pkey[0]);
+    d->pkey[i++] = my_mpi_copy (s->pkey[0]);
   else
     {
       for (; i < n; i++ )
-        d->pkey[i] = mpi_copy( s->pkey[i] );
+        d->pkey[i] = my_mpi_copy (s->pkey[i]);
     }
   for (; i < PUBKEY_MAX_NSKEY; i++)
     d->pkey[i] = NULL;
@@ -233,14 +251,16 @@ copy_signature( PKT_signature *d, PKT_signature *s )
     memcpy( d, s, sizeof *d );
     n = pubkey_get_nsig( s->pubkey_algo );
     if( !n )
-       d->data[0] = mpi_copy(s->data[0]);
+       d->data[0] = my_mpi_copy(s->data[0]);
     else {
        for(i=0; i < n; i++ )
-           d->data[i] = mpi_copy( s->data[i] );
+           d->data[i] = my_mpi_copy( s->data[i] );
     }
     d->pka_info = s->pka_info? cp_pka_info (s->pka_info) : NULL;
     d->hashed = cp_subpktarea (s->hashed);
     d->unhashed = cp_subpktarea (s->unhashed);
+    if (s->signers_uid)
+      d->signers_uid = xstrdup (s->signers_uid);
     if(s->numrevkeys)
       {
        d->revkey=NULL;
@@ -284,7 +304,7 @@ free_attributes(PKT_user_id *uid)
 void
 free_user_id (PKT_user_id *uid)
 {
-    assert (uid->ref > 0);
+    log_assert (uid->ref > 0);
     if (--uid->ref)
         return;
 
@@ -416,11 +436,14 @@ cmp_public_keys( PKT_public_key *a, PKT_public_key *b )
        return -1;
 
     n = pubkey_get_npkey( b->pubkey_algo );
-    if( !n )
-       return -1; /* can't compare due to unknown algorithm */
-    for(i=0; i < n; i++ ) {
-       if( mpi_cmp( a->pkey[i], b->pkey[i] ) )
-           return -1;
+    if( !n ) { /* unknown algorithm, rest is in opaque MPI */
+       if( mpi_cmp( a->pkey[0], b->pkey[0] ) )
+           return -1; /* can't compare due to unknown algorithm */
+    } else {
+       for(i=0; i < n; i++ ) {
+           if( mpi_cmp( a->pkey[i], b->pkey[i] ) )
+               return -1;
+       }
     }
 
     return 0;