IMPORTANT BUGFIX: Avoid random crashes in findCertificates. (This also fixes bug...
authorKarl-Heinz Zimmer <khz@kde.org>
Wed, 26 Jun 2002 04:44:58 +0000 (04:44 +0000)
committerKarl-Heinz Zimmer <khz@kde.org>
Wed, 26 Jun 2002 04:44:58 +0000 (04:44 +0000)
gpgmeplug/cryptplug.h
gpgmeplug/gpgmeplug.c

index 27655f5..7b544e6 100644 (file)
@@ -1575,12 +1575,16 @@ bool storeCertificatesFromMessage( const char* ciphertext );
 /*! \ingroup groupCryptAct
    \brief Find all certificate for a given addressee.
 
-   NOTE: The \c certificate parameter must point to an allready allocated
-   block of memory which is large enough to hold the complete list.
+  NOTE: The certificate parameter must point to a not-yet allocated
+        char*.  The function will allocate the memory needed and
+        return the size in newSize.
    If secretOnly is true, only secret keys are returned.
 */
-bool findCertificates( const char* addressee, char** certificates, bool secretOnly );
-
+bool findCertificates( const char* addressee,
+                       char** certificates,
+                       int* newSize,
+                       bool secretOnly );
+                       
 /*! \ingroup groupCryptAct
    \brief Encrypts an email message in
           \c cleartext according to the \c addressee and
index a4c8b50..7e92835 100644 (file)
@@ -1989,6 +1989,9 @@ parse_dn (const unsigned char *string)
   size_t arrayidx, arraysize;
   int i;
 
+  if( !string )
+    return NULL;
+
   arraysize = 7; /* C,ST,L,O,OU,CN,email */
   arrayidx = 0;
   array = safe_malloc ((arraysize+1) * sizeof *array);
@@ -2046,15 +2049,17 @@ add_dn_part( char* result, struct DnPair* dn, const char* part )
 {
   int any = 0;
 
-  for(; dn->key; ++dn ) {
-    if( !strcmp( dn->key, part ) ) {
-      if( any ) strcat( result, "+" );
-      /* email hack */
-      if( !strcmp( part, "1.2.840.113549.1.9.1" ) ) strcat( result, "EMail" );
-      else strcat( result, part );
-      strcat( result, "=" );
-      strcat( result, dn->value );
-      any = 1;
+  if( dn ) {
+    for(; dn->key; ++dn ) {
+      if( !strcmp( dn->key, part ) ) {
+        if( any ) strcat( result, "+" );
+        /* email hack */
+        if( !strcmp( part, "1.2.840.113549.1.9.1" ) ) strcat( result, "EMail" );
+        else strcat( result, part );
+        strcat( result, "=" );
+        strcat( result, dn->value );
+        any = 1;
+      }
     }
   }
   return any;
@@ -2075,10 +2080,12 @@ reorder_dn( struct DnPair *dn )
   };
   int any=0, any2=0, len=0, i;
   char* result;
-  for( i = 0; dn[i].key; ++i ) {
-    len += strlen( dn[i].key );
-    len += strlen( dn[i].value );
-    len += 4; /* ',' and '=', and possibly "(" and ")" */
+  if( dn ) {
+    for( i = 0; dn[i].key; ++i ) {
+      len += strlen( dn[i].key );
+      len += strlen( dn[i].value );
+      len += 4; /* ',' and '=', and possibly "(" and ")" */
+    }
   }
   result = (char*)safe_malloc( (len+1)*sizeof(char) );
   *result = 0;
@@ -2092,17 +2099,19 @@ reorder_dn( struct DnPair *dn )
   }
 
   /* add remaining parts in no particular order */
-  for(; dn->key; ++dn ) {
-    for( i = 0; stdpart[i]; ++i ) {
-      if( !strcmp( dn->key, stdpart[i] ) ) {
-       break;
+  if( dn ) {
+    for(; dn->key; ++dn ) {
+      for( i = 0; stdpart[i]; ++i ) {
+        if( !strcmp( dn->key, stdpart[i] ) ) {
+          break;
+        }
+      }
+      if( !stdpart[i] ) {
+        if( any ) strcat( result, "," );
+        if( !any2 ) strcat( result, "(");
+        any = add_dn_part( result, dn, dn->key );
+        any2 = 1;
       }
-    }
-    if( !stdpart[i] ) {
-      if( any ) strcat( result, "," );
-      if( !any2 ) strcat( result, "(");
-      any = add_dn_part( result, dn, dn->key );
-      any2 = 1;
     }
   }
   if( any2 ) strcat( result, ")");
@@ -2396,9 +2405,15 @@ importCertificate( const char* fingerprint )
 */
 bool findCertificates( const char* addressee,
                        char** certificates,
-                       /*int* newSize,*/
+                       int* newSize,
                        bool secretOnly )
 {
+  static int maxCerts = 1024;
+  // use const char declarations since all of them are needed twice
+  const char* delimiter = "\1";
+  const char* openBracket = "    (";
+  const char* closeBracket = ")";
+
   GpgmeCtx ctx;
   GpgmeError err;
   GpgmeKey rKey;
@@ -2407,68 +2422,88 @@ bool findCertificates( const char* addressee,
   char* dn;
   struct DnPair* a;
   int nFound = 0;
-/*
+  int iFound = 0;
+  int siz = 0;
+  char* DNs[maxCerts];
+  char* FPRs[maxCerts];
+  
+  if( ! certificates ){
+    fprintf( stderr, "gpgme: findCertificates called with invalid *certificates pointer\n" );
+    return false;
+  }
+
   if( ! newSize ){
-    fprintf( stderr, "findCertificates called without valid newSize pointer\n" );
+    fprintf( stderr, "gpgme: findCertificates called with invalid newSize pointer\n" );
     return false;
   }
-*/
-  strcpy( *certificates, "" );
 
+  *certificates = 0;
+  *newSize = 0;
+  
+  // calculate length of buffer needed for certs plus fingerprints
+  memset( DNs,  0, sizeof( DNs  ) );
+  memset( FPRs, 0, sizeof( FPRs ) );
   gpgme_new (&ctx);
   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
-/*
-  (*newSize) = 0;
   err = gpgme_op_keylist_start(ctx, addressee, secretOnly ? 1 : 0);
   while( GPGME_No_Error == err ) {
     err = gpgme_op_keylist_next(ctx, &rKey);
     if( GPGME_No_Error == err ) {
       s = gpgme_key_get_string_attr (rKey, GPGME_ATTR_USERID, NULL, 0);
       if( s ) {
+        dn = xstrdup( s );
         s2 = gpgme_key_get_string_attr (rKey, GPGME_ATTR_FPR, NULL, 0);
         if( s2 ) {
           if( nFound )
-            ++(*newSize);
-          (*newSize) += strlen( s );
-          a = parse_dn( dn ); 
+            siz += strlen( delimiter );
+          a = parse_dn( dn );
+          free( dn );
           dn = reorder_dn( a );
-          (*newSize) += strlen( dn );
-          safe_free( (void **)&dn );
+          siz += strlen( dn );
+          siz += strlen( openBracket );
+          siz += strlen( s2 );
+          siz += strlen( closeBracket );
+          DNs[ nFound ] = xstrdup( dn );
+          FPRs[nFound ] = xstrdup( s2 );
           ++nFound;
+          if( nFound >= maxCerts ) {
+            fprintf( stderr,
+                     "gpgme: findCertificates found too many certificates (%d)\n",
+                     maxCerts );
+            break;
+          }
         }
+        free( dn );
       }
     }
   }
-*/
   gpgme_op_keylist_end( ctx );
-  nFound = 0;
-  err = gpgme_op_keylist_start(ctx, addressee, secretOnly ? 1 : 0);
-  while( GPGME_No_Error == err ) {
-    err = gpgme_op_keylist_next(ctx, &rKey);
-    if( GPGME_No_Error == err ) {
-      s = gpgme_key_get_string_attr (rKey, GPGME_ATTR_USERID, NULL, 0);
-      if( s ) {
-        s2 = gpgme_key_get_string_attr (rKey, GPGME_ATTR_FPR, NULL, 0);
-        if( s2 ) {
-          if( nFound )
-            strcat(*certificates,"\1" );
-          dn = xstrdup( s );
-/*fprintf( stderr, "\n\n\nDN before reordering: \"%s\"\n", dn );*/
-          a = parse_dn( dn ); 
-          dn = reorder_dn( a );
-/*fprintf( stderr, "\nDN after reordering: \"%s\"\n", dn );*/
-          strcat( *certificates, dn );
-          strcat( *certificates, "    (" );
-          strcat( *certificates, s2 );
-          strcat( *certificates, ")" );
-          safe_free( (void **)&dn );
-          ++nFound;
-        }
+  gpgme_release (ctx);
+  
+  
+  if( 0 < siz ) {
+    // add one for trailing ZERO char
+    ++siz;
+    *newSize = siz;
+    // allocate the buffer
+    *certificates = malloc(   sizeof(char) * siz );
+    memset( *certificates, 0, sizeof(char) * siz );
+    // fill the buffer
+    for( iFound=0; iFound < nFound; ++iFound ) {
+      if( !iFound )
+        strcpy(*certificates, DNs[iFound] );
+      else {
+        strcat(*certificates, delimiter );
+        strcat(*certificates, DNs[iFound] );
       }
+      strcat(  *certificates, openBracket );
+      strcat(  *certificates, FPRs[iFound] );
+      strcat(  *certificates, closeBracket );
+      ++iFound;
+      free( DNs[ iFound ] );
+      free( FPRs[iFound ] );
     }
   }
-  gpgme_op_keylist_end( ctx );
-  gpgme_release (ctx);
-
+    
   return ( 0 < nFound );
 }