#endif
#include <stdlib.h>
-//#include <string.h>
-//#include <ctype.h>
-
/*! \file cryptplug.h
\brief Common API header for CRYPTPLUG.
plugin <b>you should ignore this</b> section!
*/
+/*! \defgroup certList Certificate Info listing functions
+ */
+
typedef enum {
Feature_undef = 0,
Feature_StoreMessagesEncrypted = 13,
Feature_CheckCertificatePath = 14,
Feature_CertificateDirectoryService = 15,
- Feature_CRLDirectoryService = 16
+ Feature_CRLDirectoryService = 16,
+ Feature_CertificateInfo = 17
} Feature;
-// dummy values
+/* dummy values */
typedef enum {
PinRequest_undef = 0,
PinRequest_AfterMinutes = 5
} PinRequests;
-// dummy values:
+/* dummy values: */
typedef enum {
SendCert_undef = 0,
SendCert_SendChainWithRoot = 4
} SendCertificates;
-// dummy values:
+/* dummy values: */
typedef enum {
SignAlg_undef = 0,
FALSE) */
bool makeMimeObject; /*!< specifies whether we should create a MIME
object or a flat text message body */
- // the following are used for MIME messages only
+ /* the following are used for MIME messages only */
bool makeMultiMime; /*!< specifies whether we should create a
'Multipart' MIME object or a single part
object, if FALSE only \c contentTypeMain,
\c makeMimeObject or \c makeMultiMime
is FALSE or if \c contentTypeCode does
not return a non-zero-length string) */
- // the following are used for flat non-MIME messages only
+ /* the following are used for flat non-MIME messages only */
char* flatTextPrefix; /*!< text to preceed the main text (or the
code bloc containing the encrypted main
text, resp.)<br>
\see free_StructuringInfo, StructuringInfo
\see signMessage, encryptMessage, encryptAndSignMessage
*/
- void init_StructuringInfo( struct StructuringInfo* s )
+ static void init_StructuringInfo( struct StructuringInfo* s )
{
if( ! s ) return;
\see StructuringInfo
*/
- void free_StructuringInfo( struct StructuringInfo* s )
+ static void free_StructuringInfo( struct StructuringInfo* s )
{
if( ! s ) return;
if( s->contentTypeMain ) free( s->contentTypeMain );
*/
void updateCRL( void );
+struct CertIterator;
+
+struct DnPair {
+ char *key;
+ char *value;
+};
+
+struct CertificateInfo {
+ char** userid;
+ char** issuer;
+ struct DnPair *dnarray;
+};
+
+/*! \function struct CertIterator* startListCertificates( void );
+ \function struct CertificateInfo* nextCertificate( struct CertIterator* );
+ \function void endListCertificates( struct CertIterator* );
+
+ \ingroup certList
+ Example:
+\verbatim
+ struct CertificateInfo* info;
+ struct CertIterator* it = startListCertificates();
+ while( info = nextCertificate( it ) ) {
+ do something with info.
+ dont free() it, the struct will be reused
+ by the next call to nextCertificate()
+ }
+ endListCertificates( it );
+\endverbatim
+*/
+struct CertIterator* startListCertificates( void );
+struct CertificateInfo* nextCertificate( struct CertIterator* );
+void endListCertificates( struct CertIterator* );
+
+
#ifdef __cplusplus
}
#endif
case Feature_CheckCertificatePath: return true;
case Feature_CertificateDirectoryService: return true;
case Feature_CRLDirectoryService: return true;
+ case Feature_CertificateInfo: return true;
/* undefined or not yet implemented: */
case Feature_undef: return false;
default: return false;
int signatureCertificateDaysLeftToExpiry( const char* certificate )
{
- // pending (khz): make this work!
+ /* pending (khz): make this work! */
/*
GpgmeCtx ctx;
GpgmeError err;
}
gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS);
- // Don't ASCII-armor, the MUA will use base64 encoding
- // gpgme_set_armor (ctx, 1);
+ /* Don't ASCII-armor, the MUA will use base64 encoding */
+ /* gpgme_set_armor (ctx, 1); */
err = gpgme_op_genkey (ctx, certparms, pub, NULL );
fprintf( stderr, "3: gpgme returned %d\n", err );
if( err != GPGME_No_Error ) {
*length = len;
/* The buffer generatedKey contains the LEN bytes you want */
- // Caller is responsible for freeing
+ /* Caller is responsible for freeing */
return true;
}
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.
+ */
+
+/* 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))
+
+#define safe_malloc( x ) malloc( x )
+
+static void safe_free( void** x )
+{
+ free( *x );
+ *x = 0;
+}
+/*#define safe_free( x ) free( x )*/
+
+
+struct dn_array_s {
+ char *key;
+ char *value;
+};
+
+
+/* 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
+ expected to return only rfc2253 compatible strings. */
+static const unsigned char *
+parse_dn_part (struct dn_array_s *array, const unsigned char *string)
+{
+ const unsigned char *s, *s1;
+ size_t n;
+ unsigned char *p;
+
+ /* parse attributeType */
+ for (s = string+1; *s && *s != '='; s++)
+ ;
+ if (!*s)
+ return NULL; /* error */
+ n = s - string;
+ if (!n)
+ return NULL; /* empty key */
+ array->key = p = safe_malloc (n+1);
+ memcpy (p, string, n); /* fixme: trim trailing spaces */
+ p[n] = 0;
+ string = s + 1;
+
+ if (*string == '#')
+ { /* hexstring */
+ string++;
+ for (s=string; hexdigitp (s); s++)
+ s++;
+ n = s - string;
+ if (!n || (n & 1))
+ return NULL; /* empty or odd number of digits */
+ n /= 2;
+ array->value = p = safe_malloc (n+1);
+ for (s1=string; n; s1 += 2, n--)
+ *p++ = xtoi_2 (s1);
+ *p = 0;
+ }
+ else
+ { /* regular v3 quoted string */
+ for (n=0, s=string; *s; s++)
+ {
+ if (*s == '\\')
+ { /* pair */
+ s++;
+ if (*s == ',' || *s == '=' || *s == '+'
+ || *s == '<' || *s == '>' || *s == '#' || *s == ';'
+ || *s == '\\' || *s == '\"' || *s == ' ')
+ n++;
+ else if (hexdigitp (s) && hexdigitp (s+1))
+ {
+ s++;
+ n++;
+ }
+ else
+ return NULL; /* invalid escape sequence */
+ }
+ else if (*s == '\"')
+ return NULL; /* invalid encoding */
+ else if (*s == ',' || *s == '=' || *s == '+'
+ || *s == '<' || *s == '>' || *s == '#' || *s == ';' )
+ break;
+ else
+ n++;
+ }
+
+ array->value = p = safe_malloc (n+1);
+ for (s=string; n; s++, n--)
+ {
+ if (*s == '\\')
+ {
+ s++;
+ if (hexdigitp (s))
+ {
+ *p++ = xtoi_2 (s);
+ s++;
+ }
+ else
+ *p++ = *s;
+ }
+ else
+ *p++ = *s;
+ }
+ *p = 0;
+ }
+ return s;
+}
+
+
+/* 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
+ expected to return only rfc2253 compatible strings. */
+static struct dn_array_s *
+parse_dn (const unsigned char *string)
+{
+ struct dn_array_s *array;
+ size_t arrayidx, arraysize;
+ int i;
+
+ arraysize = 7; /* C,ST,L,O,OU,CN,email */
+ array = safe_malloc ((arraysize+1) * sizeof *array);
+ arrayidx = 0;
+ while (*string)
+ {
+ while (*string == ' ')
+ string++;
+ if (!*string)
+ break; /* ready */
+ if (arrayidx >= arraysize)
+ { /* mutt lacks a real safe_realoc - so we need to copy */
+ struct dn_array_s *a2;
+
+ arraysize += 5;
+ a2 = safe_malloc ((arraysize+1) * sizeof *array);
+ for (i=0; i < arrayidx; i++)
+ {
+ a2[i].key = array[i].key;
+ a2[i].value = array[i].value;
+ }
+ safe_free ((void **)&array);
+ array = a2;
+ }
+ array[arrayidx].key = NULL;
+ array[arrayidx].value = NULL;
+ string = parse_dn_part (array+arrayidx, string);
+ arrayidx++;
+ if (!string)
+ goto failure;
+ while (*string == ' ')
+ string++;
+ if (*string && *string != ',' && *string != ';' && *string != '+')
+ goto failure; /* invalid delimiter */
+ if (*string)
+ string++;
+ }
+ array[arrayidx].key = NULL;
+ array[arrayidx].value = NULL;
+ return array;
+
+ failure:
+ for (i=0; i < arrayidx; i++)
+ {
+ safe_free ((void**)&array[i].key);
+ safe_free ((void**)&array[i].value);
+ }
+ safe_free ((void**)&array);
+ return NULL;
+}
+
+
+
+struct CertIterator {
+ GpgmeCtx ctx;
+ struct CertificateInfo info;
+};
+
+struct CertIterator* startListCertificates( void )
+{
+ GpgmeError err;
+ struct CertIterator* it;
+ /*fprintf( stderr, "startListCertificates()" );*/
+
+ it = (struct CertIterator*)safe_malloc( sizeof( struct CertIterator ) );
+
+ err = gpgme_new (&(it->ctx));
+ /*fprintf( stderr, "2: gpgme returned %d\n", err );*/
+ if( err != GPGME_No_Error ) {
+ free( it );
+ return NULL;
+ }
+
+ gpgme_set_protocol (it->ctx, GPGME_PROTOCOL_CMS);
+ err = gpgme_op_keylist_start ( it->ctx, NULL, 0);
+ if( err != GPGME_No_Error ) {
+ endListCertificates( it );
+ return NULL;
+ }
+ memset( &(it->info), 0, sizeof( struct CertificateInfo ) );
+ return it;
+}
+
+#define MAX_GPGME_IDX 20
+
+static void freeStringArray( char** c )
+{
+ char** _c = c;
+ while( c && *c ) {
+ /*fprintf( stderr, "freeing \"%s\"\n", *c );*/
+ safe_free( (void**)&(*c) );
+ ++c;
+ }
+ safe_free( (void**)&_c );
+}
+
+static void freeInfo( struct CertificateInfo* info )
+{
+ struct DnPair* a = info->dnarray;
+ assert( info );
+ /*fprintf( stderr, "freeing info->userid\n" );*/
+ if( info->userid ) freeStringArray( info->userid );
+ /*fprintf( stderr, "freeing info->issuer\n" );*/
+ if( info->issuer ) freeStringArray( info->issuer );
+ /*fprintf( stderr, "freed\n" );*/
+ while( a && a->key && a->value ) {
+ /*fprintf( stderr, "freeing %s\n", a->key );*/
+ safe_free ((void**)&(a->key));
+ safe_free ((void**)&(a->value));
+ ++a;
+ }
+ if( info->dnarray ) safe_free ((void**)&(info->dnarray));
+ memset( info, 0, sizeof( *info ) );
+}
+
+#define xstrdup( x ) (x)?strdup(x):0
+
+struct CertificateInfo* nextCertificate( struct CertIterator* it )
+{
+ GpgmeError err;
+ GpgmeKey key;
+ assert( it );
+ err = gpgme_op_keylist_next ( it->ctx, &key);
+ if( err != GPGME_EOF ) {
+ int idx;
+ const char* s;
+ char* names[MAX_GPGME_IDX+1];
+ memset( names, 0, sizeof( names ) );
+ freeInfo( &(it->info) );
+
+ for( idx = 0; (s = gpgme_key_get_string_attr (key, GPGME_ATTR_USERID, 0, idx)) && idx < MAX_GPGME_IDX;
+ ++idx ) {
+ names[idx] = xstrdup( s );
+ }
+
+ it->info.userid = safe_malloc( sizeof( char* ) * (idx+1) );
+ memset( it->info.userid, 0, sizeof( char* ) * (idx+1) );
+ it->info.dnarray = 0;
+ for( idx = 0; names[idx] != 0; ++idx ) {
+ struct DnPair* a = parse_dn( names[idx] );
+ it->info.userid[idx] = names[idx];
+ it->info.dnarray = a;
+ }
+ it->info.userid[idx] = 0;
+
+ memset( names, 0, sizeof( names ) );
+ for( idx = 0; (s = gpgme_key_get_string_attr (key, GPGME_ATTR_ISSUER, 0, idx)) && idx < MAX_GPGME_IDX;
+ ++idx ) {
+ /*fprintf(stderr, "Got issuer \"%s\"\n", s );*/
+ names[idx] = xstrdup( s );
+ }
+ it->info.issuer = safe_malloc( sizeof( char* ) * (idx+1) );
+ memset( it->info.issuer, 0, sizeof( char* ) * (idx+1) );
+ for( idx = 0; names[idx] != 0; ++idx ) {
+ it->info.issuer[idx] = names[idx];
+ }
+ it->info.issuer[idx] = 0;
+
+ gpgme_key_release (key);
+ return &(it->info);
+ } else return NULL;
+}
+
+void endListCertificates( struct CertIterator* it )
+{
+ /*fprintf( stderr, "endListCertificates()\n" );*/
+ assert(it);
+ freeInfo( &(it->info) );
+ gpgme_op_keylist_end(it->ctx);
+ gpgme_release (it->ctx);
+ free( it );
+}