new cryptplug function importCertificateFromMem()
[gpgme.git] / gpgmeplug / gpgmeplug.c
index 9fedff4..f603008 100644 (file)
@@ -6,6 +6,7 @@
               the common CRYPTPLUG specification.
 
   Copyright (C) 2001 by Klarälvdalens Datakonsult AB
+  Copyright (C) 2002 g10 Code GmbH
 
   GPGMEPLUG is free software; you can redistribute it and/or modify
   it under the terms of GNU General Public License as published by
@@ -62,7 +63,7 @@
 #endif
 
 /* definitions for signing */
-// 1. opaque signatures (only used for S/MIME)
+/* 1. opaque signatures (only used for S/MIME). */
 #ifndef GPGMEPLUG_OPA_SIGN_MAKE_MIME_OBJECT
 #define GPGMEPLUG_OPA_SIGN_INCLUDE_CLEARTEXT false
 #define GPGMEPLUG_OPA_SIGN_MAKE_MIME_OBJECT  false
@@ -81,7 +82,7 @@
 #define GPGMEPLUG_OPA_SIGN_FLAT_SEPARATOR    ""
 #define GPGMEPLUG_OPA_SIGN_FLAT_POSTFIX      ""
 #endif
-// 2. detached signatures (used for S/MIME and for OpenPGP)
+/* 2. detached signatures (used for S/MIME and for OpenPGP) */
 #ifndef GPGMEPLUG_DET_SIGN_MAKE_MIME_OBJECT
 #define GPGMEPLUG_DET_SIGN_INCLUDE_CLEARTEXT true
 #define GPGMEPLUG_DET_SIGN_MAKE_MIME_OBJECT  true
 #define GPGMEPLUG_DET_SIGN_FLAT_SEPARATOR    ""
 #define GPGMEPLUG_DET_SIGN_FLAT_POSTFIX      ""
 #endif
-// 3. common definitions for opaque and detached signing
+/* 3. common definitions for opaque and detached signing */
 #ifndef __GPGMEPLUG_SIGNATURE_CODE_IS_BINARY
 #define __GPGMEPLUG_SIGNATURE_CODE_IS_BINARY false
 #endif
@@ -195,7 +196,7 @@ typedef struct {
   bool                    certificateInChainExpiryNearWarning;
   int                     certificateInChainExpiryNearWarningInterval;
   bool                    receiverEmailAddressNotInCertificateWarning;
-  const char* libVersion; // a statically allocated string with the GPGME Version used
+  const char* libVersion; /* a statically allocated string with the GPGME Version used */
 } Config;
 
 
@@ -203,6 +204,48 @@ Config config;
 
 #define NEAR_EXPIRY 14
 
+/* Max number of parts in a DN */
+#define MAX_GPGME_IDX 20
+
+/* some macros to replace ctype ones and avoid locale problems */
+#define spacep(p)   (*(p) == ' ' || *(p) == '\t')
+#define digitp(p)   (*(p) >= '0' && *(p) <= '9')
+#define hexdigitp(a) (digitp (a)                     \
+                      || (*(a) >= 'A' && *(a) <= 'F')  \
+                      || (*(a) >= 'a' && *(a) <= 'f'))
+/* the atoi macros assume that the buffer has only valid digits */
+#define atoi_1(p)   (*(p) - '0' )
+#define atoi_2(p)   ((atoi_1(p) * 10) + atoi_1((p)+1))
+#define atoi_4(p)   ((atoi_2(p) * 100) + atoi_2((p)+2))
+#define xtoi_1(p)   (*(p) <= '9'? (*(p)- '0'): \
+                     *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
+#define xtoi_2(p)   ((xtoi_1(p) * 16) + xtoi_1((p)+1))
+
+static void *
+xmalloc (size_t n)
+{
+  char *p = malloc (n);
+  if (!p)
+    { 
+      fputs ("\nfatal: out of core\n", stderr);
+      exit (4);
+    }
+  return p;
+}
+
+/* Please: Don't call an allocation function xfoo when it may return NULL. */
+/* Wrong: #define xstrdup( x ) (x)?strdup(x):0 */
+/* Right: */
+static char *
+xstrdup (const char *string)
+{
+  char *p = xmalloc (strlen (string)+1);
+  strcpy (p, string);
+  return p;
+}
+
+
+
 bool initialize()
 {
   config.bugURL                               = malloc( strlen( BUG_URL ) + 1 );
@@ -1018,9 +1061,8 @@ bool certificateValidity( const char* certificate,
 void storeNewCharPtr( char** dest, const char* src )
 {
   int sLen = strlen( src );
-  *dest = malloc( sLen + 1 );
+  *dest = xmalloc( sLen + 1 );
   strcpy( *dest, src );
-  (*dest)[sLen] = '\0';
 }
 
 
@@ -1076,17 +1118,27 @@ bool signMessage( const char*  cleartext,
   /* select the signer's key if provided */
   if (certificate != 0) {
       err = gpgme_op_keylist_start(ctx, certificate, 0);
-      if (err == GPGME_No_Error) {
-         /* we only support one signer for now */
-         err = gpgme_op_keylist_next(ctx, &rKey);
-         if (err == GPGME_No_Error) {
-             /* clear existing signers */
-             gpgme_signers_clear(ctx);
-             /* set the signing key */
-             gpgme_signers_add(ctx, rKey);
-         }
-         gpgme_op_keylist_end(ctx);
+      while (err == GPGME_No_Error) {
+          err = gpgme_op_keylist_next(ctx, &rKey);
+          if (err == GPGME_No_Error) {
+              unsigned long u;
+              u = gpgme_key_get_ulong_attr(rKey, GPGME_ATTR_CAN_SIGN, 0, 0);
+              if( u ) {
+
+//                const char* s;
+//                s = gpgme_key_get_string_attr(rKey, GPGME_ATTR_FPR, 0, 0);
+//                fprintf( stderr, "gpgmeplug signMessage signing with key: %s\n", s );
+
+                  /* clear existing signers */
+                  gpgme_signers_clear(ctx);
+                  /* set the signing key */
+                  gpgme_signers_add(ctx, rKey);
+                  /* we only support one signer for now */
+                  break;
+              }
+          }
       }
+      gpgme_op_keylist_end(ctx);
   }
 
   /* PENDING(g10) Implement this
@@ -1099,8 +1151,8 @@ bool signMessage( const char*  cleartext,
                             strlen( cleartext ), 1 );
   gpgme_data_new ( &sig );
 
-  // NOTE: Currently we support Opaque signed messages only for S/MIME,
-  //       but not for OpenPGP mode!
+  /* NOTE: Currently we support Opaque signed messages only for S/MIME,
+     but not for OpenPGP mode! */
   if( GPGMEPLUG_PROTOCOL == GPGME_PROTOCOL_CMS )
     bIsOpaque = (SignatureCompoundMode_Opaque == signatureCompoundMode());
   else
@@ -1252,7 +1304,7 @@ static char* parseAddress( char* address )
   if( i ) {
     j = index( i+1, '>' );
     if( j == NULL ) j = address+strlen(address);
-    result = malloc( j-i );
+    result = xmalloc( j-i );
     strncpy( result, i+1, j-i-1 );
     result[j-i-1] = '\0';
     free( address );
@@ -1267,7 +1319,7 @@ static char* parseAddress( char* address )
     while( isspace( *l ) ) ++l;
     while( isspace( *k ) ) --k;
     if( l != result || k != result+(j-i-1) ) {
-      char* result2 = malloc( k-l+2 );
+      char* result2 = xmalloc( k-l+2 );
       strncpy( result2, l, k-l+1 );
       result2[k-l+1] = '\0';
       free(result);
@@ -1318,7 +1370,7 @@ static char* nextAddress( const char** address )
     len = *address - start;
     if( len > 0 ) {
       if( **address != 0 ) --len;
-      result = malloc( len*sizeof(char)+1 );
+      result = xmalloc( len*sizeof(char)+1 );
       strncpy( result, start, len );
       result[len] = '\0';
     }
@@ -1401,14 +1453,65 @@ bool encryptMessage( const char*  cleartext,
 
   err = gpgme_op_encrypt (ctx, rset, gPlaintext, gCiphertext );
   if( err ) {
-    fprintf( stderr, "\ngpgme_op_encrypt() returned this error code:  %i\n\n", err );
+    fprintf( stderr, "\ngpgme_op_encrypt() returned this error code:  %i\n", err );
     if( errId )
       *errId = err;
     if( errTxt ) {
       const char* _errTxt = gpgme_strerror( err );
-      *errTxt = malloc( strlen( _errTxt ) + 1 );
-      if( *errTxt )
+      *errTxt = malloc( strlen( _errTxt ) + 100 ); // leave room for reason string
+      if( *errTxt ) {
+        char* opInfo;
         strcpy(*errTxt, _errTxt );
+        opInfo = gpgme_get_op_info(ctx, 0);
+        if( NULL != opInfo && *opInfo ){
+          const int opLen = strlen( opInfo );
+          const int reasonLen = 8;
+          char reason[ 1+reasonLen ];
+          char* pos1;
+          strcpy( reason, "<reason>" );
+          pos1 = strstr( opInfo, reason );
+          if( NULL != pos1 && 
+              opLen > reasonLen + (pos1 - opInfo) ){
+            char* pos2;
+            pos1 += reasonLen;
+            pos2 = strchr( pos1, '<' );
+            if( NULL != pos2 &&
+                pos1 < pos2 ){
+              long int reasonId;
+              strcat( *errTxt, " - " );
+              *pos2 = '\0';
+              fprintf( stderr, "                        and this reason code:  %s\n\n", pos1 );
+              reasonId = strtol( pos1, NULL, 10 );
+              switch( reasonId ) {
+                case  0: strcat( *errTxt, "No specific reason given" );
+                         break;
+                case  1: strcat( *errTxt, "Not Found" );
+                         break;
+                case  2: strcat( *errTxt, "Ambigious specification" );
+                         break;
+                case  3: strcat( *errTxt, "Key can't be used for operation" );
+                         break;
+                case  4: strcat( *errTxt, "Key has been revoked" );
+                         break;
+                case  5: strcat( *errTxt, "Key has expired" );
+                         break;
+                case  6: strcat( *errTxt, "No CRL known for certificate" );
+                         break;
+                case  7: strcat( *errTxt, "No current CRL available" );
+                         break;
+                case  8: strcat( *errTxt, "Contraints not matched" );
+                         break;
+                default: {
+                           strcat( *errTxt, "Extended error Id: #" );
+                           strcat( *errTxt, pos1 );
+                         }  
+              }
+              *pos2 = '<';
+            }
+          }
+          free( opInfo );
+        }
+      }
     }
   }
 
@@ -1614,6 +1717,9 @@ bool decryptAndCheckMessage( const char* ciphertext,
 
 const char* requestCertificateDialog(){ return 0; }
 
+
+/* The buffer generatedKey contains the LEN bytes you want.
+   Caller is responsible for freeing. */
 bool requestDecentralCertificate( const char* certparms, 
                                   char** generatedKey, int* length )
 {
@@ -1649,8 +1755,6 @@ bool requestDecentralCertificate( const char* certparms,
     *generatedKey = gpgme_data_release_and_get_mem (pub, &len);
     *length = len;
 
-    /* The buffer generatedKey contains the LEN bytes you want */
-    // Caller is responsible for freeing
     return true;
 }
 
@@ -1676,75 +1780,6 @@ const char* displayCRL(){ return 0; }
 
 void updateCRL(){}
 
-/*
- * Copyright (C) 2002 g10 Code GmbH
- * 
- *     This program is free software; you can redistribute it
- *     and/or modify it under the terms of the GNU General Public
- *     License as published by the Free Software Foundation; either
- *     version 2 of the License, or (at your option) any later
- *     version.
- * 
- *     This program is distributed in the hope that it will be
- *     useful, but WITHOUT ANY WARRANTY; without even the implied
- *     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- *     PURPOSE.  See the GNU General Public License for more
- *     details.
- * 
- *     You should have received a copy of the GNU General Public
- *     License along with this program; if not, write to the Free
- *     Software Foundation, Inc., 59 Temple Place - Suite 330,
- *     Boston, MA  02111, USA.
- */
-
-/* Max number of parts in a DN */
-#define MAX_GPGME_IDX 20
-
-/* some macros to replace ctype ones and avoid locale problems */
-#define spacep(p)   (*(p) == ' ' || *(p) == '\t')
-#define digitp(p)   (*(p) >= '0' && *(p) <= '9')
-#define hexdigitp(a) (digitp (a)                     \
-                      || (*(a) >= 'A' && *(a) <= 'F')  \
-                      || (*(a) >= 'a' && *(a) <= 'f'))
-/* the atoi macros assume that the buffer has only valid digits */
-#define atoi_1(p)   (*(p) - '0' )
-#define atoi_2(p)   ((atoi_1(p) * 10) + atoi_1((p)+1))
-#define atoi_4(p)   ((atoi_2(p) * 100) + atoi_2((p)+2))
-#define xtoi_1(p)   (*(p) <= '9'? (*(p)- '0'): \
-                     *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
-#define xtoi_2(p)   ((xtoi_1(p) * 16) + xtoi_1((p)+1))
-
-static void *
-xmalloc (size_t n)
-{
-  char *p = malloc (n);
-  if (!p)
-    { 
-      fputs ("\nfatal: out of core\n", stderr);
-      exit (4);
-    }
-  return p;
-}
-
-/* Please: Don't call an allocation function xfoo when it may return NULL. */
-/* Wrong: #define xstrdup( x ) (x)?strdup(x):0 */
-/* Right: */
-static char *
-xstrdup (const char *string)
-{
-  char *p = xmalloc (strlen (string));
-  strcpy (p, string);
-  return p;
-}
-    
-
-
-static void 
-safe_free( void** x ) 
-{
-  free( *x );
-  *x = 0;
-}
 
 char *
 trim_trailing_spaces( char *string )
@@ -1764,7 +1799,6 @@ trim_trailing_spaces( char *string )
 
     return string ;
 }
-/*#define safe_free( x ) free( x )*/
 
 /* Parse a DN and return an array-ized one.  This is not a validating
    parser and it does not support any old-stylish syntax; gpgme is
@@ -1898,7 +1932,7 @@ parse_dn (const unsigned char *string)
               a2[i].key = array[i].key;
               a2[i].value = array[i].value;
             }
-          safe_free ((void **)&array);
+          free (array);
           array = a2;
         }
       array[arrayidx].key = NULL;
@@ -1921,10 +1955,10 @@ parse_dn (const unsigned char *string)
  failure:
   for (i=0; i < arrayidx; i++)
     {
-      safe_free ((void**)&array[i].key);
-      safe_free ((void**)&array[i].value);
+      free (array[i].key);
+      free (array[i].value);
     }
-  safe_free ((void**)&array);
+  free (array);
   return NULL;
 }
 
@@ -1952,7 +1986,7 @@ add_dn_part( char* result, struct DnPair* dn, const char* part )
 static char* 
 reorder_dn( struct DnPair *dn )
 {
-  // note: The must parts are: CN, L, OU, O, C
+  /* note: The must parts are: CN, L, OU, O, C */
   const char* stdpart[] = {
     "CN", "S", "SN", "GN", "T", "UID",
           "MAIL", "EMAIL", "MOBILE", "TEL", "FAX", "STREET",
@@ -2013,7 +2047,7 @@ startListCertificates( const char* pattern, int remote )
     GpgmeError err;
     struct CertIterator* it;
     const char* patterns[] = { pattern, NULL };
-    fprintf( stderr,  "startListCertificates( \"%s\", %d )", pattern, remote );
+    fprintf( stderr,  "startListCertificates( \"%s\", %d )\n", pattern, remote );
 
     it = xmalloc( sizeof( struct CertIterator ) );
 
@@ -2029,6 +2063,7 @@ startListCertificates( const char* pattern, int remote )
     else gpgme_set_keylist_mode ( it->ctx, GPGME_KEYLIST_MODE_LOCAL );
     err =  gpgme_op_keylist_ext_start ( it->ctx, patterns, 0, 0);
     if( err != GPGME_No_Error ) {
+      fprintf( stderr,  "gpgme_op_keylist_ext_start returned %d", err );
       endListCertificates( it );
       return NULL;
     }
@@ -2041,12 +2076,13 @@ static void
 freeStringArray( char** c )
 {
     char** _c = c;
+
     while( c && *c ) {
       /*fprintf( stderr, "freeing \"%s\"\n", *c );*/
-      safe_free( (void**)&(*c) );
+      free( *c );
       ++c;
     }
-    safe_free( (void**)&_c );
+    free( _c );
 }
 
 /* free all malloc'ed data in a struct CertificateInfo */
@@ -2055,29 +2091,29 @@ freeInfo( struct CertificateInfo* info )
 {
   struct DnPair* a = info->dnarray;
   assert( info );
-  if( info->userid ) freeStringArray( info->userid );
-  if( info->serial ) safe_free( (void**)&(info->serial) );
-  if( info->fingerprint ) safe_free( (void**)&(info->fingerprint) );
-  if( info->issuer ) safe_free( (void**)&(info->issuer) );
-  if( info->chainid ) safe_free( (void**)&(info->chainid) );
-  if( info->caps ) safe_free( (void**)&(info->caps) );
+  freeStringArray( info->userid );
+  free( info->serial);
+  free( info->fingerprint );
+  free( info->issuer );
+  free( info->chainid );
+  free( info->caps );
   while( a && a->key && a->value ) {
-    safe_free ((void**)&(a->key));
-    safe_free ((void**)&(a->value));
+    free (a->key);
+    free (a->value);
     ++a;
   }
-  if( info->dnarray ) safe_free ((void**)&(info->dnarray));
+  free (info->dnarray);
   memset( info, 0, sizeof( *info ) );
 }
 
 /* Format the fingerprint nicely. The caller should
-   free the returned value with safe_free() */
+   free the returned value using free() */
 static char* make_fingerprint( const char* fpr )
 {
   int len = strlen(fpr);
   int i = 0;
   char* result = xmalloc( (len + len/2 + 1)*sizeof(char) );
-  if( !result ) return NULL;
+
   for(; *fpr; ++fpr, ++i ) {
     if( i%3 == 2) {
       result[i] = ':'; ++i;
@@ -2095,6 +2131,7 @@ nextCertificate( struct CertIterator* it, struct CertificateInfo** result )
   GpgmeKey   key;
   int retval = GPGME_No_Error;
   assert( it );
+  fprintf( stderr,  "nextCertificates( %p, %p )\n", it, result );
   err = gpgme_op_keylist_next ( it->ctx, &key);
   if( err != GPGME_EOF ) {   
     int idx;
@@ -2119,7 +2156,8 @@ nextCertificate( struct CertIterator* it, struct CertificateInfo** result )
       if( idx == 0 ) {
        it->info.userid[idx] = reorder_dn( a );
        it->info.dnarray = a;
-       safe_free( (void **)&(names[idx]) );
+       free (names[idx]);
+        names[idx] = NULL;
       } else {
        it->info.userid[idx] = names[idx];
       }
@@ -2138,11 +2176,12 @@ nextCertificate( struct CertIterator* it, struct CertificateInfo** result )
       /*it->info.issuer = xstrdup(s);*/
       it->info.issuer = reorder_dn( issuer_dn );
       while( tmp_dn->key ) {
-       safe_free( (void**)&issuer_dn->key );
-       safe_free( (void**)&issuer_dn->value );
+       free( tmp_dn->key );
+       free( tmp_dn->value );
        ++tmp_dn;
       }
-      safe_free( (void**)&issuer_dn );
+      free( issuer_dn );
+      issuer_dn = tmp_dn = NULL;
     } else {
       it->info.issuer = NULL;
     }
@@ -2182,9 +2221,9 @@ nextCertificate( struct CertIterator* it, struct CertificateInfo** result )
 int
 endListCertificates( struct CertIterator* it )
 {
-  /*fprintf( stderr,  "endListCertificates()\n" );*/
   char *s = gpgme_get_op_info (it->ctx, 0);
   int truncated = s && strstr (s, "<truncated/>");
+  fprintf( stderr,  "endListCertificates( %p )\n", it );
   if( s ) free( s );
   assert(it);
   freeInfo( &(it->info) );
@@ -2195,7 +2234,7 @@ endListCertificates( struct CertIterator* it )
 }
 
 int
-importCertificate( const char* fingerprint )
+importCertificateWithFPR( const char* fingerprint, char** additional_info )
 {
   GpgmeError err;
   GpgmeCtx  ctx;
@@ -2246,7 +2285,7 @@ importCertificate( const char* fingerprint )
   err = gpgme_recipients_add_name( recips, buf ); 
   if( err ) {
     fprintf( stderr,  "gpgme_recipients_add_name returned %d\n", err );
-    safe_free( (void**)&buf );
+    free (buf);
     gpgme_recipients_release( recips );
     gpgme_data_release( keydata );    
     gpgme_release( ctx );
@@ -2256,19 +2295,22 @@ importCertificate( const char* fingerprint )
   err = gpgme_op_export( ctx, recips, keydata );
   if( err ) {
     fprintf( stderr,  "gpgme_op_export returned %d\n", err );
-    safe_free( (void**)&buf );
+    free (buf);
+    *additional_info = gpgme_get_op_info( ctx, 0 );
     gpgme_recipients_release( recips );
     gpgme_data_release( keydata );    
     gpgme_release( ctx );
     return err;
   }
-  safe_free( (void**)&buf );
+  free (buf);
+  buf = NULL;
 
   err = gpgme_op_import( ctx, keydata );
+  *additional_info = gpgme_get_op_info( ctx, 0 );
   if( err ) {    
     fprintf( stderr,  "gpgme_op_import returned %d\n", err );
     gpgme_recipients_release( recips );
-    gpgme_data_release( keydata );    
+    gpgme_data_release( keydata );
     gpgme_release( ctx );
     return err;
   }
@@ -2278,12 +2320,47 @@ importCertificate( const char* fingerprint )
   gpgme_release( ctx );
   return 0;
 }
+int
+importCertificateFromMem( const char* data, size_t length , char** additional_info )
+{
+  GpgmeError err;
+  GpgmeCtx  ctx;
+  GpgmeData keydata;
 
-    // // // // // // // // // // // // // // // // // // // // // // // // //
-   //                                                                      //
-  //         Continuation of CryptPlug code                               //
- //                                                                      //
-// // // // // // // // // // // // // // // // // // // // // // // // //
+  err = gpgme_new( &ctx );
+  /*fprintf( stderr,  "2: gpgme returned %d\n", err );*/
+  if( err != GPGME_No_Error ) {
+    return err;
+  }
+  gpgme_set_protocol( ctx, GPGME_PROTOCOL_CMS );
+  gpgme_set_keylist_mode( ctx, GPGME_KEYLIST_MODE_LOCAL );
+
+  err = gpgme_data_new_from_mem( &keydata, data, length, 0 );
+  if( err ) {
+    fprintf( stderr,  "gpgme_data_new returned %d\n", err );
+    gpgme_release( ctx );
+    return err;
+  }
+
+  err = gpgme_op_import( ctx, keydata );
+  *additional_info = gpgme_get_op_info( ctx, 0 );
+  if( err ) {    
+    fprintf( stderr,  "gpgme_op_import returned %d\n", err );
+    gpgme_data_release( keydata );    
+    gpgme_release( ctx );
+    return err;
+  }
+
+  gpgme_data_release( keydata );    
+  gpgme_release( ctx );
+  return 0;
+}
+
+/*  == == == == == == == == == == == == == == == == == == == == == == == == ==
+   ==                                                                      ==
+  ==         Continuation of CryptPlug code                               ==
+ ==                                                                      ==
+== == == == == == == == == == == == == == == == == == == == == == == == ==  */
 
 
 /*
@@ -2353,7 +2430,7 @@ bool findCertificates( const char* addressee,
           siz += strlen( s2 );
           siz += strlen( closeBracket );
           DNs[ nFound ] = dn;
-          dn = NULL;
+          dn = NULL; /* prevent it from being free'ed below. */
           FPRs[nFound ] = xstrdup( s2 );
           ++nFound;
           if( nFound >= MAXCERTS ) {
@@ -2363,6 +2440,7 @@ bool findCertificates( const char* addressee,
             break;
           }
         }
+        free (dn); 
       }
     }
   }
@@ -2375,10 +2453,10 @@ bool findCertificates( const char* addressee,
     ++siz;
     *newSize = siz;
     /* allocate the buffer */
-    *certificates = xmalloc(   sizeof(char) * siz );
+    *certificates = xmalloc( sizeof(char) * siz );
     memset( *certificates, 0, sizeof(char) * siz );
     /* fill the buffer */
-    for( iFound=0; iFound < nFound; ++iFound ) {
+    for (iFound=0; iFound < nFound; iFound++) {
       if( !iFound )
         strcpy(*certificates, DNs[iFound] );
       else {
@@ -2388,7 +2466,6 @@ bool findCertificates( const char* addressee,
       strcat(  *certificates, openBracket );
       strcat(  *certificates, FPRs[iFound] );
       strcat(  *certificates, closeBracket );
-      ++iFound;
       free( DNs[ iFound ] );
       free( FPRs[iFound ] );
     }
@@ -2451,7 +2528,6 @@ bool checkMessageSignature( char** cleartext,
   GpgmeKey key;
   time_t created;
   struct DnPair* a;
-  char* dn;
   int sig_idx=0;
   int UID_idx=0;
   const char* statusStr;
@@ -2545,7 +2621,7 @@ bool checkMessageSignature( char** cleartext,
                                            GPGME_ATTR_SIG_SUMMARY,
                                            0 );
       fprintf( stderr, "gpgmeplug checkMessageSignature status flags: %lX\n", sumGPGME );
-      // translate GPGME status flags to common CryptPlug status flags
+      /* translate GPGME status flags to common CryptPlug status flags */
       sumPlug = 0;
       if( sumGPGME & GPGME_SIGSUM_VALID       ) sumPlug |= SigStat_VALID      ;
       if( sumGPGME & GPGME_SIGSUM_GREEN       ) sumPlug |= SigStat_GREEN      ;
@@ -2599,17 +2675,14 @@ bool checkMessageSignature( char** cleartext,
         attr_string = gpgme_key_get_string_attr(key, GPGME_ATTR_USERID, 0, 0);
         if (attr_string != 0) {
             a = parse_dn( attr_string );
-            dn = reorder_dn( a );
-            storeNewCharPtr( &sigmeta->extended_info[sig_idx].userid,
-                             dn );
+            sigmeta->extended_info[sig_idx].userid = reorder_dn( a );
         }
         
         attr_ulong = gpgme_key_get_ulong_attr(key, GPGME_ATTR_USERID, 0, 0);
         sigmeta->extended_info[sig_idx].userid_num = attr_ulong;
 
         /* extract the length */
-        attr_ulong = gpgme_key_get_ulong_attr(key, GPGME_ATTR_LEN, 0, 0);
-        sigmeta->extended_info[sig_idx].keylen = attr_ulong;
+          sigmeta->extended_info[sig_idx].keylen = attr_ulong;
 
         /* extract the creation time of the key */
         attr_ulong = gpgme_key_get_ulong_attr(key, GPGME_ATTR_CREATED, 0, 0);
@@ -2623,9 +2696,7 @@ bool checkMessageSignature( char** cleartext,
         attr_string = gpgme_key_get_string_attr(key, GPGME_ATTR_NAME, 0, 0);
         if (attr_string != 0) {
             a = parse_dn( attr_string );
-            dn = reorder_dn( a );
-            storeNewCharPtr( &sigmeta->extended_info[sig_idx].name,
-                             dn );
+            sigmeta->extended_info[sig_idx].name = reorder_dn( a );
         }
 
         /* extract email(s) */
@@ -2637,7 +2708,7 @@ bool checkMessageSignature( char** cleartext,
              ++UID_idx ){
           if (*attr_string) {
             fprintf( stderr, "gpgmeplug checkMessageSignature found email: %s\n", attr_string );
-            if( sigmeta->extended_info[sig_idx].emailCount )
+            if( !sigmeta->extended_info[sig_idx].emailCount )
                 alloc_return = 
                     malloc( sizeof( char*) );
             else