IMPORTANT BUGFIX: Avoid random crashes in findCertificates. (This also fixes bug #1088.)

This commit is contained in:
Karl-Heinz Zimmer 2002-06-26 04:44:58 +00:00
parent 0a4a00821d
commit f97a834df6
2 changed files with 108 additions and 69 deletions

View File

@ -1575,11 +1575,15 @@ bool storeCertificatesFromMessage( const char* ciphertext );
/*! \ingroup groupCryptAct /*! \ingroup groupCryptAct
\brief Find all certificate for a given addressee. \brief Find all certificate for a given addressee.
NOTE: The \c certificate parameter must point to an allready allocated NOTE: The certificate parameter must point to a not-yet allocated
block of memory which is large enough to hold the complete list. char*. The function will allocate the memory needed and
return the size in newSize.
If secretOnly is true, only secret keys are returned. 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 /*! \ingroup groupCryptAct
\brief Encrypts an email message in \brief Encrypts an email message in

View File

@ -1989,6 +1989,9 @@ parse_dn (const unsigned char *string)
size_t arrayidx, arraysize; size_t arrayidx, arraysize;
int i; int i;
if( !string )
return NULL;
arraysize = 7; /* C,ST,L,O,OU,CN,email */ arraysize = 7; /* C,ST,L,O,OU,CN,email */
arrayidx = 0; arrayidx = 0;
array = safe_malloc ((arraysize+1) * sizeof *array); 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; int any = 0;
for(; dn->key; ++dn ) { if( dn ) {
if( !strcmp( dn->key, part ) ) { for(; dn->key; ++dn ) {
if( any ) strcat( result, "+" ); if( !strcmp( dn->key, part ) ) {
/* email hack */ if( any ) strcat( result, "+" );
if( !strcmp( part, "1.2.840.113549.1.9.1" ) ) strcat( result, "EMail" ); /* email hack */
else strcat( result, part ); if( !strcmp( part, "1.2.840.113549.1.9.1" ) ) strcat( result, "EMail" );
strcat( result, "=" ); else strcat( result, part );
strcat( result, dn->value ); strcat( result, "=" );
any = 1; strcat( result, dn->value );
any = 1;
}
} }
} }
return any; return any;
@ -2075,10 +2080,12 @@ reorder_dn( struct DnPair *dn )
}; };
int any=0, any2=0, len=0, i; int any=0, any2=0, len=0, i;
char* result; char* result;
for( i = 0; dn[i].key; ++i ) { if( dn ) {
len += strlen( dn[i].key ); for( i = 0; dn[i].key; ++i ) {
len += strlen( dn[i].value ); len += strlen( dn[i].key );
len += 4; /* ',' and '=', and possibly "(" and ")" */ len += strlen( dn[i].value );
len += 4; /* ',' and '=', and possibly "(" and ")" */
}
} }
result = (char*)safe_malloc( (len+1)*sizeof(char) ); result = (char*)safe_malloc( (len+1)*sizeof(char) );
*result = 0; *result = 0;
@ -2092,17 +2099,19 @@ reorder_dn( struct DnPair *dn )
} }
/* add remaining parts in no particular order */ /* add remaining parts in no particular order */
for(; dn->key; ++dn ) { if( dn ) {
for( i = 0; stdpart[i]; ++i ) { for(; dn->key; ++dn ) {
if( !strcmp( dn->key, stdpart[i] ) ) { for( i = 0; stdpart[i]; ++i ) {
break; 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, ")"); if( any2 ) strcat( result, ")");
@ -2396,9 +2405,15 @@ importCertificate( const char* fingerprint )
*/ */
bool findCertificates( const char* addressee, bool findCertificates( const char* addressee,
char** certificates, char** certificates,
/*int* newSize,*/ int* newSize,
bool secretOnly ) 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; GpgmeCtx ctx;
GpgmeError err; GpgmeError err;
GpgmeKey rKey; GpgmeKey rKey;
@ -2407,68 +2422,88 @@ bool findCertificates( const char* addressee,
char* dn; char* dn;
struct DnPair* a; struct DnPair* a;
int nFound = 0; int nFound = 0;
/* int iFound = 0;
if( ! newSize ){ int siz = 0;
fprintf( stderr, "findCertificates called without valid newSize pointer\n" ); char* DNs[maxCerts];
char* FPRs[maxCerts];
if( ! certificates ){
fprintf( stderr, "gpgme: findCertificates called with invalid *certificates pointer\n" );
return false; return false;
} }
*/
strcpy( *certificates, "" );
if( ! newSize ){
fprintf( stderr, "gpgme: findCertificates called with invalid newSize pointer\n" );
return false;
}
*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_new (&ctx);
gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL); gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
/*
(*newSize) = 0;
err = gpgme_op_keylist_start(ctx, addressee, secretOnly ? 1 : 0); err = gpgme_op_keylist_start(ctx, addressee, secretOnly ? 1 : 0);
while( GPGME_No_Error == err ) { while( GPGME_No_Error == err ) {
err = gpgme_op_keylist_next(ctx, &rKey); err = gpgme_op_keylist_next(ctx, &rKey);
if( GPGME_No_Error == err ) { if( GPGME_No_Error == err ) {
s = gpgme_key_get_string_attr (rKey, GPGME_ATTR_USERID, NULL, 0); s = gpgme_key_get_string_attr (rKey, GPGME_ATTR_USERID, NULL, 0);
if( s ) { if( s ) {
dn = xstrdup( s );
s2 = gpgme_key_get_string_attr (rKey, GPGME_ATTR_FPR, NULL, 0); s2 = gpgme_key_get_string_attr (rKey, GPGME_ATTR_FPR, NULL, 0);
if( s2 ) { if( s2 ) {
if( nFound ) if( nFound )
++(*newSize); siz += strlen( delimiter );
(*newSize) += strlen( s );
a = parse_dn( dn ); a = parse_dn( dn );
free( dn );
dn = reorder_dn( a ); dn = reorder_dn( a );
(*newSize) += strlen( dn ); siz += strlen( dn );
safe_free( (void **)&dn ); siz += strlen( openBracket );
++nFound; siz += strlen( s2 );
} siz += strlen( closeBracket );
} DNs[ nFound ] = xstrdup( dn );
} FPRs[nFound ] = xstrdup( s2 );
}
*/
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; ++nFound;
if( nFound >= maxCerts ) {
fprintf( stderr,
"gpgme: findCertificates found too many certificates (%d)\n",
maxCerts );
break;
}
} }
free( dn );
} }
} }
} }
gpgme_op_keylist_end( ctx ); gpgme_op_keylist_end( ctx );
gpgme_release (ctx); 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 ] );
}
}
return ( 0 < nFound ); return ( 0 < nFound );
} }