more cert info
authorSteffen Hansen <hansen@kde.org>
Fri, 31 May 2002 15:34:39 +0000 (15:34 +0000)
committerSteffen Hansen <hansen@kde.org>
Fri, 31 May 2002 15:34:39 +0000 (15:34 +0000)
gpgmeplug/cryptplug.h
gpgmeplug/gpgmeplug.c

index f90bcbdc94919ea4dd6e4db6a59e2a229e1c3417..026be5e8b844488bad73585c78d44c9d54ea2e55 100644 (file)
@@ -1713,7 +1713,23 @@ struct DnPair {
 
 struct CertificateInfo {
   char** userid;
+  char* serial;
+  char* fingerprint;
+
   char* issuer;
+  char* chainid;
+
+  char* caps;
+
+  unsigned long created;
+  unsigned long expire;
+
+  int secret   : 1;
+  int invalid  : 1;
+  int expired  : 1;
+  int disabled : 1;
+  
+
   struct DnPair *dnarray; /* parsed values from userid[0] */
 };
 
index b8424788ebc716f5994e1e2b3fcb45b15d8bc157..ffc86c9b16e5f7c294b51ece1fa8db3dada879cc 100644 (file)
@@ -1700,8 +1700,8 @@ bool requestDecentralCertificate( const char* certparms,
     }
 
     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 ) {
@@ -1740,3 +1740,338 @@ bool archiveCertificate( const char* certificate ){ 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 )*/
+
+/* 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 DnPair *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 DnPair *
+parse_dn (const unsigned char *string)
+{
+  struct DnPair *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 DnPair *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 );
+  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) );
+  while( a && a->key && a->value ) {
+    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;
+    unsigned long u;
+    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;
+
+    s = gpgme_key_get_string_attr (key, GPGME_ATTR_SERIAL, 0, 0); 
+    it->info.serial = xstrdup(s);
+
+    s = gpgme_key_get_string_attr (key, GPGME_ATTR_FPR, 0, 0); 
+    it->info.fingerprint = xstrdup(s);
+
+    s = gpgme_key_get_string_attr (key, GPGME_ATTR_ISSUER, 0, 0); 
+    it->info.issuer = xstrdup(s);
+
+    s = gpgme_key_get_string_attr (key, GPGME_ATTR_CHAINID, 0, 0); 
+    it->info.chainid = xstrdup(s);
+
+    s = gpgme_key_get_string_attr (key, GPGME_ATTR_KEY_CAPS, 0, 0); 
+    it->info.caps = xstrdup(s);
+
+    u = gpgme_key_get_ulong_attr (key, GPGME_ATTR_CREATED, 0, 0); 
+    it->info.created = u;
+
+    u = gpgme_key_get_ulong_attr (key, GPGME_ATTR_EXPIRE, 0, 0); 
+    it->info.expire = u;
+
+    u = gpgme_key_get_ulong_attr (key, GPGME_ATTR_IS_SECRET, 0, 0); 
+    it->info.secret = u;
+
+    u = gpgme_key_get_ulong_attr (key, GPGME_ATTR_UID_INVALID, 0, 0); 
+    it->info.invalid = u;
+
+    u = gpgme_key_get_ulong_attr (key, GPGME_ATTR_KEY_EXPIRED, 0, 0); 
+    it->info.expired = u;
+
+    u = gpgme_key_get_ulong_attr (key, GPGME_ATTR_KEY_DISABLED, 0, 0); 
+    it->info.disabled = u;
+
+    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 );
+}