* keybox.h (keybox_flag_t): New.
authorWerner Koch <wk@gnupg.org>
Mon, 2 Feb 2004 17:09:35 +0000 (17:09 +0000)
committerWerner Koch <wk@gnupg.org>
Mon, 2 Feb 2004 17:09:35 +0000 (17:09 +0000)
* keybox-search.c (get_flag_from_image, keybox_get_flags): New.
(_keybox_get_flag_location): New.

* certchain.c (gpgsm_validate_chain): Mark revoked certs in the
keybox.

* keylist.c (list_cert_colon): New arg VALIDITY; use it to print a
revoked flag.
(list_internal_keys): Retrieve validity flag.
(list_external_cb): Pass 0 as validity flag.
* keydb.c (keydb_get_flags, keydb_set_flags): New.
(keydb_set_cert_flags): New.
(lock_all): Return a proper error code.
(keydb_lock): New.
(keydb_delete): Don't lock but check that it has been locked.
(keydb_update_keyblock): Ditto.
* delete.c (delete_one): Take a lock.

12 files changed:
kbx/ChangeLog
kbx/keybox-blob.c
kbx/keybox-defs.h
kbx/keybox-search.c
kbx/keybox-update.c
kbx/keybox.h
sm/ChangeLog
sm/certchain.c
sm/delete.c
sm/keydb.c
sm/keydb.h
sm/keylist.c

index 07a1982..a866e04 100644 (file)
@@ -1,3 +1,9 @@
+2004-02-02  Werner Koch  <wk@gnupg.org>
+
+       * keybox.h (keybox_flag_t): New.
+       * keybox-search.c (get_flag_from_image, keybox_get_flags): New.
+       (_keybox_get_flag_location): New.
+
 2003-11-12  Werner Koch  <wk@gnupg.org>
 
        Adjusted for API changes in Libksba.
index 3d81532..9659543 100644 (file)
@@ -39,7 +39,7 @@ The first record of a plain KBX file has a special format:
  byte pgp_completes  ditto.
  byte pgp_cert_depth ditto.
 
-The OpenPGP and X.509 blob are verry similiar, things which are
+The OpenPGP and X.509 blob are very similiar, things which are
 X.509 specific are noted like [X.509: xxx]
 
  u32  length of this blob (including these 4 bytes)
@@ -57,7 +57,7 @@ X.509 specific are noted like [X.509: xxx]
    b20 The keys fingerprint
        (fingerprints are always 20 bytes, MD5 left padded with zeroes)
    u32 offset to the n-th key's keyID (a keyID is always 8 byte)
-        or 0 if not known which is the case opnly for X509.
+        or 0 if not known which is the case only for X509.
    u16 special key flags
         bit 0 =
    u16 reserved
@@ -82,8 +82,11 @@ X.509 specific are noted like [X.509: xxx]
        0x00000002 = bad signature
        0x10000000 = valid and expires at some date in 1978.
        0xffffffff = valid and does not expire
- u8    assigned ownertrust [X509: no used]
- u8    all_validity        [X509: no used]
+ u8    assigned ownertrust [X509: not used]
+ u8    all_validity 
+           OpenPGP:  see ../g10/trustdb/TRUST_* [not yet used]
+           X509: Bit 4 set := key has been revoked.  nOte that this value
+                              matches TRUST_FLAG_REVOKED
  u16   reserved
  u32   recheck_after
  u32   Newest timestamp in the keyblock (useful for KS syncronsiation?)
index fa145f7..1743150 100644 (file)
@@ -116,6 +116,12 @@ off_t _keybox_get_blob_fileoffset (KEYBOXBLOB blob);
 int _keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp);
 int _keybox_write_blob (KEYBOXBLOB blob, FILE *fp);
 
+/*-- keybox-search.c --*/
+gpg_err_code_t _keybox_get_flag_location (const unsigned char *buffer,
+                                          size_t length,
+                                          int what,
+                                          size_t *flag_off, size_t *flag_size);
+
 /*-- keybox-dump.c --*/
 int _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp);
 int _keybox_dump_file (const char *filename, FILE *outfp);
index b8add5a..f23bfda 100644 (file)
@@ -1,5 +1,5 @@
 /* keybox-search.c - Search operations
- *     Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+ * Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
 #include <errno.h>
 
 #include "../jnlib/stringhelp.h" /* ascii_xxxx() */
+
 #include "keybox-defs.h"
 
+
 #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))
 
+
 struct sn_array_s {
     int snlen;
     unsigned char *sn;
@@ -88,6 +91,97 @@ blob_get_blob_flags (KEYBOXBLOB blob)
 }
 
 
+/* Return information on the flag WHAT within the blob BUFFER,LENGTH.
+   Return the offset and the length (in bytes) of the flag in
+   FLAGOFF,FLAG_SIZE. */
+gpg_err_code_t
+_keybox_get_flag_location (const unsigned char *buffer, size_t length,
+                           int what, size_t *flag_off, size_t *flag_size)
+{
+  size_t pos;
+  size_t nkeys, keyinfolen;
+  size_t nuids, uidinfolen;
+  size_t nserial;
+  size_t nsigs, siginfolen;
+
+  switch (what)
+    {
+    case KEYBOX_FLAG_BLOB:
+      if (length < 8)
+        return GPG_ERR_INV_OBJ;
+      *flag_off = 6;
+      *flag_size = 2;
+      break;
+    
+    case KEYBOX_FLAG_VALIDITY:
+    case KEYBOX_FLAG_OWNERTRUST:
+      if (length < 20)
+        return GPG_ERR_INV_OBJ;
+      /* Key info. */
+      nkeys = get16 (buffer + 16);
+      keyinfolen = get16 (buffer + 18 );
+      if (keyinfolen < 28)
+        return GPG_ERR_INV_OBJ;
+      pos = 20 + keyinfolen*nkeys;
+      if (pos+2 > length)
+        return GPG_ERR_INV_OBJ; /* Out of bounds. */
+      /* Serial number. */
+      nserial = get16 (buffer+pos); 
+      pos += 2 + nserial;
+      if (pos+4 > length)
+        return GPG_ERR_INV_OBJ; /* Out of bounds. */
+      /* User IDs. */
+      nuids = get16 (buffer + pos); pos += 2;
+      uidinfolen = get16 (buffer + pos); pos += 2;
+      if (uidinfolen < 12 )
+        return GPG_ERR_INV_OBJ; 
+      pos += uidinfolen*nuids;
+      if (pos+4 > length)
+        return GPG_ERR_INV_OBJ ; /* Out of bounds. */
+      /* Signature info. */
+      nsigs = get16 (buffer + pos); pos += 2;
+      siginfolen = get16 (buffer + pos); pos += 2;
+      if (siginfolen < 4 )
+        return GPG_ERR_INV_OBJ; 
+      pos += siginfolen*nsigs;
+      if (pos+1+1+2+4+4+4+4 > length)
+        return GPG_ERR_INV_OBJ ; /* Out of bounds. */
+      *flag_size = 1;
+      *flag_off = pos;
+      if (what == KEYBOX_FLAG_VALIDITY)
+        ++*flag_off;
+      break;
+
+    default:
+      return GPG_ERR_INV_FLAG;
+    }
+  return 0;
+}
+
+/* Return one of the flags WHAT in VALUE from teh blob BUFFER of
+   LENGTH bytes.  Return 0 on success or an raw error code. */
+static gpg_err_code_t
+get_flag_from_image (const unsigned char *buffer, size_t length,
+                     int what, unsigned int *value)
+{
+  gpg_err_code_t ec;
+  size_t pos, size;
+
+  *value = 0;
+  ec = _keybox_get_flag_location (buffer, length, what, &pos, &size);
+  if (!ec)
+    switch (size)
+      {
+      case 1: *value = buffer[pos]; break;
+      case 2: *value = get16 (buffer + pos); break;
+      case 4: *value = get32 (buffer + pos); break;
+      default: ec = GPG_ERR_BUG; break;
+      }
+  
+  return ec;
+}
+
+
 static int
 blob_cmp_sn (KEYBOXBLOB blob, const unsigned char *sn, int snlen)
 {
@@ -811,3 +905,23 @@ keybox_get_cert (KEYBOX_HANDLE hd, ksba_cert_t *r_cert)
 }
 
 #endif /*KEYBOX_WITH_X509*/
+
+/* Return the flags named WHAT iat the address of VALUE. IDX is used
+   only for certain flags and should be 0 if not required. */
+int
+keybox_get_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int *value)
+{
+  const unsigned char *buffer;
+  size_t length;
+  gpg_err_code_t ec;
+
+  if (!hd)
+    return gpg_error (GPG_ERR_INV_VALUE);
+  if (!hd->found.blob)
+    return gpg_error (GPG_ERR_NOTHING_FOUND);
+
+  buffer = _keybox_get_blob_image (hd->found.blob, &length);
+  ec = get_flag_from_image (buffer, length, what, value);
+  return ec? gpg_error (ec):0;
+}
+
index ed9ca2b..47e5396 100644 (file)
@@ -384,6 +384,88 @@ keybox_update_cert (KEYBOX_HANDLE hd, ksba_cert_t cert,
 
 #endif /*KEYBOX_WITH_X509*/
 
+/* Note: We assume that the keybox has been locked before the current
+   search was executed.  This is needed so that we can depend on the
+   offset information of the flags. */
+int
+keybox_set_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int value)
+{
+  off_t off;
+  const char *fname;
+  FILE *fp;
+  gpg_err_code_t ec;
+  size_t flag_pos, flag_size;
+  const unsigned char *buffer;
+  size_t length;
+
+  if (!hd)
+    return gpg_error (GPG_ERR_INV_VALUE);
+  if (!hd->found.blob)
+    return gpg_error (GPG_ERR_NOTHING_FOUND);
+  if (!hd->kb)
+    return gpg_error (GPG_ERR_INV_HANDLE); 
+  if (!hd->found.blob)
+    return gpg_error (GPG_ERR_NOTHING_FOUND);
+  fname = hd->kb->fname;
+  if (!fname)
+    return gpg_error (GPG_ERR_INV_HANDLE); 
+
+  off = _keybox_get_blob_fileoffset (hd->found.blob);
+  if (off == (off_t)-1)
+    return gpg_error (GPG_ERR_GENERAL);
+
+  buffer = _keybox_get_blob_image (hd->found.blob, &length);
+  ec = _keybox_get_flag_location (buffer, length, what, &flag_pos, &flag_size);
+  if (ec)
+    return gpg_error (ec);
+
+  off += flag_pos;
+
+  if (hd->fp)
+    {
+      fclose (hd->fp);
+      hd->fp = NULL;
+    }
+  fp = fopen (hd->kb->fname, "r+b");
+  if (!fp)
+    return gpg_error (gpg_err_code_from_errno (errno));
+
+  ec = 0;
+  if (fseeko (fp, off, SEEK_SET))
+    ec = gpg_error (gpg_err_code_from_errno (errno));
+  else
+    {
+      unsigned char tmp[4];
+
+      tmp[0] = value >> 24;
+      tmp[1] = value >> 16;
+      tmp[2] = value >>  8;
+      tmp[3] = value;
+
+      switch (flag_size)
+        {
+        case 1: 
+        case 2:
+        case 4:
+          if (fwrite (tmp+4-flag_size, flag_size, 1, fp) != 1)
+            ec = gpg_err_code_from_errno (errno);
+          break;
+        default:
+          ec = GPG_ERR_BUG;
+          break;
+        }
+    }
+
+  if (fclose (fp))
+    {
+      if (!ec)
+        ec = gpg_err_code_from_errno (errno);
+    }
+
+  return gpg_error (ec);
+}
+
+
 
 int
 keybox_delete (KEYBOX_HANDLE hd)
index 5a5ad29..e4dc9d6 100644 (file)
@@ -42,9 +42,19 @@ extern "C" {
 # include <ksba.h>
 #endif
 
+typedef struct keybox_handle *KEYBOX_HANDLE;
 
 
-typedef struct keybox_handle *KEYBOX_HANDLE;
+typedef enum
+  {
+    KEYBOX_FLAG_BLOB,       /* The blob flags. */
+    KEYBOX_FLAG_VALIDITY,   /* The validity of the entire key. */
+    KEYBOX_FLAG_OWNERTRUST, /* The assigned ownertrust. */
+    KEYBOX_FLAG_KEY,        /* The key flags; requires a key index. */
+    KEYBOX_FLAG_UID,        /* The user ID flags; requires an uid index. */
+    KEYBOX_FLAG_UID_VALIDITY/* The validity of a specific uid, requires
+                               an uid index. */
+  } keyxox_flag_t;
 
 
 /*-- keybox-init.c --*/
@@ -61,6 +71,7 @@ int keybox_set_ephemeral (KEYBOX_HANDLE hd, int yes);
 #ifdef KEYBOX_WITH_X509 
 int keybox_get_cert (KEYBOX_HANDLE hd, ksba_cert_t *ret_cert);
 #endif /*KEYBOX_WITH_X509*/
+int keybox_get_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int *value);
 
 int keybox_search_reset (KEYBOX_HANDLE hd);
 int keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc);
@@ -73,6 +84,7 @@ int keybox_insert_cert (KEYBOX_HANDLE hd, ksba_cert_t cert,
 int keybox_update_cert (KEYBOX_HANDLE hd, ksba_cert_t cert,
                         unsigned char *sha1_digest);
 #endif /*KEYBOX_WITH_X509*/
+int keybox_set_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int value);
 
 int keybox_delete (KEYBOX_HANDLE hd);
 
index 2a584e0..cde6e84 100644 (file)
@@ -1,3 +1,20 @@
+2004-02-02  Werner Koch  <wk@gnupg.org>
+
+       * certchain.c (gpgsm_validate_chain): Mark revoked certs in the
+       keybox.
+
+       * keylist.c (list_cert_colon): New arg VALIDITY; use it to print a
+       revoked flag.
+       (list_internal_keys): Retrieve validity flag.
+       (list_external_cb): Pass 0 as validity flag.
+       * keydb.c (keydb_get_flags, keydb_set_flags): New.
+       (keydb_set_cert_flags): New.
+       (lock_all): Return a proper error code.
+       (keydb_lock): New.
+       (keydb_delete): Don't lock but check that it has been locked.
+       (keydb_update_keyblock): Ditto.
+       * delete.c (delete_one): Take a lock.
+
 2004-01-30  Werner Koch  <wk@gnupg.org>
 
        * certchain.c (check_cert_policy): Fixed read error checking.
index a48dbd7..bcc6666 100644 (file)
@@ -32,6 +32,7 @@
 #include <ksba.h>
 
 #include "keydb.h"
+#include "../kbx/keybox.h" /* for KEYBOX_FLAG_* */
 #include "i18n.h"
 
 static int
@@ -535,6 +536,11 @@ gpgsm_validate_chain (CTRL ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime)
                 case GPG_ERR_CERT_REVOKED:
                   log_error (_("the certificate has been revoked\n"));
                   any_revoked = 1;
+                  /* Store that in the keybox so that key listings are
+                     able to return the revoked flag.  We don't care
+                     about error, though. */
+                  keydb_set_cert_flags (subject_cert, KEYBOX_FLAG_VALIDITY, 0,
+                                        VALIDITY_REVOKED);
                   break;
                 case GPG_ERR_NO_CRL_KNOWN:
                   log_error (_("no CRL found for certificate\n"));
index 8b04bc4..11a0a54 100644 (file)
@@ -105,7 +105,14 @@ delete_one (CTRL ctrl, const char *username)
       goto leave;
     }
 
-  /* we need to search again to get back to the right position. */
+  /* We need to search again to get back to the right position. */
+  rc = keydb_lock (kh);
+  if (rc)
+    {
+      log_error (_("error locking keybox: %s\n"), gpg_strerror (rc));
+      goto leave;
+    }
+                   
   do 
     {
       keydb_search_reset (kh);
index 62e3ab2..f770135 100644 (file)
@@ -1,5 +1,5 @@
 /* keydb.c - key database dispatcher
- * Copyright (C) 2001, 2003 Free Software Foundation, Inc.
+ * Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -373,6 +373,21 @@ keydb_set_ephemeral (KEYDB_HANDLE hd, int yes)
 }
 
 
+/* If the keyring has not yet been locked, lock it now.  This
+   operation is required before any update opeations; it is optionaly
+   for an insert operation.  The lock is released with
+   keydb_released. */
+gpg_error_t
+keydb_lock (KEYDB_HANDLE hd)
+{
+  if (!hd)
+    return gpg_error (GPG_ERR_INV_HANDLE);
+  if (hd->locked)
+    return 0; /* Already locked. */
+  return lock_all (hd);
+}
+
+
 \f
 static int 
 lock_all (KEYDB_HANDLE hd)
@@ -380,8 +395,8 @@ lock_all (KEYDB_HANDLE hd)
   int i, rc = 0;
 
   /* Fixme: This locking scheme may lead to deadlock if the resources
-     are not added in the same sequence by all processes.  We are
-     cuurently only allowing one resource so it is not a problem. */
+     are not added in the same order all processes.  We are
+     currently only allowing one resource so it is not a problem. */
   for (i=0; i < hd->used; i++) 
     {
       switch (hd->active[i].type) 
@@ -416,7 +431,10 @@ lock_all (KEYDB_HANDLE hd)
     else
       hd->locked = 1;
 
-    return rc;
+    /* make_dotlock () does not yet guarantee that errno is set, thus
+       we can't rely on the error reason and will simply use
+       EACCES. */
+    return rc? gpg_error (GPG_ERR_EACCES) : 0;
 }
 
 static void
@@ -490,9 +508,8 @@ keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb)
     if( opt.dry_run )
        return 0;
 
-    rc = lock_all (hd);
-    if (rc)
-        return rc;
+    if (!hd->locked)
+      return gpg_error (GPG_ERR_CONFLICT);
 
     switch (hd->active[hd->found].type) {
       case KEYDB_RESOURCE_TYPE_NONE:
@@ -552,7 +569,7 @@ keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb)
 
 \f
 /*
-  Return the last found keybox.  Caller must free it.  The returned
+  Return the last found object.  Caller must free it.  The returned
   keyblock has the kbode flag bit 0 set for the node with the public
   key used to locate the keyblock or flag bit 1 set for the user ID
   node.  */
@@ -580,6 +597,67 @@ keydb_get_cert (KEYDB_HANDLE hd, ksba_cert_t *r_cert)
   return rc;
 }
 
+/* Return a flag of the last found object. WHICH is the flag requested;
+   it should be one of the KEYBOX_FLAG_ values.  If the operation is
+   successful, the flag value will be stored at the address given by
+   VALUE.  Return 0 on success or an error code. */
+gpg_error_t
+keydb_get_flags (KEYDB_HANDLE hd, int which, int idx, unsigned int *value)
+{
+  int err = 0;
+
+  if (!hd)
+    return gpg_error (GPG_ERR_INV_VALUE);
+  
+  if ( hd->found < 0 || hd->found >= hd->used) 
+    return gpg_error (GPG_ERR_NOTHING_FOUND);
+  
+  switch (hd->active[hd->found].type) 
+    {
+    case KEYDB_RESOURCE_TYPE_NONE:
+      err = gpg_error (GPG_ERR_GENERAL); /* oops */
+      break;
+    case KEYDB_RESOURCE_TYPE_KEYBOX:
+      err = keybox_get_flags (hd->active[hd->found].u.kr, which, idx, value);
+      break;
+    }
+  
+  return err;
+}
+
+/* Set a flag of the last found object. WHICH is the flag to be set; it
+   should be one of the KEYBOX_FLAG_ values.  If the operation is
+   successful, the flag value will be stored in the keybox.  Note,
+   that some flag values can't be updated and thus may retrun an
+   error, some other flag values may be masked out before an update.
+   Returns 0 on success or an error code. */
+gpg_error_t
+keydb_set_flags (KEYDB_HANDLE hd, int which, int idx, unsigned int value)
+{
+  int err = 0;
+
+  if (!hd)
+    return gpg_error (GPG_ERR_INV_VALUE);
+  
+  if ( hd->found < 0 || hd->found >= hd->used) 
+    return gpg_error (GPG_ERR_NOTHING_FOUND);
+  
+  if (!hd->locked)
+    return gpg_error (GPG_ERR_CONFLICT);
+
+  switch (hd->active[hd->found].type) 
+    {
+    case KEYDB_RESOURCE_TYPE_NONE:
+      err = gpg_error (GPG_ERR_GENERAL); /* oops */
+      break;
+    case KEYDB_RESOURCE_TYPE_KEYBOX:
+      err = keybox_set_flags (hd->active[hd->found].u.kr, which, idx, value);
+      break;
+    }
+  
+  return err;
+}
+
 /* 
  * Insert a new Certificate into one of the resources. 
  */
@@ -679,9 +757,8 @@ keydb_delete (KEYDB_HANDLE hd)
   if( opt.dry_run )
     return 0;
 
-  rc = lock_all (hd);
-  if (rc)
-    return rc;
+  if (!hd->locked)
+    return gpg_error (GPG_ERR_CONFLICT); /* ...NOT_LOCKED would be better. */
 
   switch (hd->active[hd->found].type)
     {
@@ -1279,4 +1356,65 @@ keydb_store_cert (ksba_cert_t cert, int ephemeral, int *existed)
 }
 
 
+/* This is basically keydb_set_flags but it implements a complete
+   transaction by locating teh certificate in the DB and updating the
+   flags. */
+gpg_error_t
+keydb_set_cert_flags (ksba_cert_t cert, int which, int idx, unsigned int value)
+{
+  KEYDB_HANDLE kh;
+  gpg_error_t err;
+  unsigned char fpr[20];
+  unsigned int old_value;
+
+  if (!gpgsm_get_fingerprint (cert, 0, fpr, NULL))
+    {
+      log_error (_("failed to get the fingerprint\n"));
+      return gpg_error (GPG_ERR_GENERAL);
+    }
+
+  kh = keydb_new (0);
+  if (!kh)
+    {
+      log_error (_("failed to allocate keyDB handle\n"));
+      return gpg_error (GPG_ERR_ENOMEM);;
+    }
+
+  err = keydb_lock (kh);
+  if (err)
+    {
+      log_error (_("error locking keybox: %s\n"), gpg_strerror (err));
+      keydb_release (kh);
+      return err;
+    }
+
+  err = keydb_search_fpr (kh, fpr);
+  if (err)
+    {
+      log_error (_("problem re-searching certificate: %s\n"),
+                 gpg_strerror (err));
+      keydb_release (kh);
+      return err;
+    }
+
+  err = keydb_get_flags (kh, which, idx, &old_value);
+  if (err)
+    {
+      log_error (_("error getting stored flags: %s\n"), gpg_strerror (err));
+      keydb_release (kh);
+      return err;
+    }
+  if (value != old_value)
+    {
+      err = keydb_set_flags (kh, which, idx, value);
+      if (err)
+        {
+          log_error (_("error storing flags: %s\n"), gpg_strerror (err));
+          keydb_release (kh);
+          return err;
+        }
+    }
+  keydb_release (kh);               
+  return 0;
+}
 
index 0133d0c..2e9ed15 100644 (file)
@@ -27,6 +27,9 @@
 
 typedef struct keydb_handle *KEYDB_HANDLE;
 
+/* Flag value used with KEYBOX_FLAG_VALIDITY. */
+#define VALIDITY_REVOKED (1<<5)
+
 
 /*-- keydb.c --*/
 int keydb_add_resource (const char *url, int force, int secret);
@@ -34,6 +37,7 @@ KEYDB_HANDLE keydb_new (int secret);
 void keydb_release (KEYDB_HANDLE hd);
 int keydb_set_ephemeral (KEYDB_HANDLE hd, int yes);
 const char *keydb_get_resource_name (KEYDB_HANDLE hd);
+gpg_error_t keydb_lock (KEYDB_HANDLE hd);
 
 #if 0 /* pgp stuff */
 int keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb);
@@ -41,6 +45,10 @@ int keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb);
 int keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb);
 #endif
 
+gpg_error_t keydb_get_flags (KEYDB_HANDLE hd, int which, int idx,
+                             unsigned int *value);
+gpg_error_t keydb_set_flags (KEYDB_HANDLE hd, int which, int idx,
+                             unsigned int value);
 int keydb_get_cert (KEYDB_HANDLE hd, ksba_cert_t *r_cert);
 int keydb_insert_cert (KEYDB_HANDLE hd, ksba_cert_t cert);
 int keydb_update_cert (KEYDB_HANDLE hd, ksba_cert_t cert);
@@ -64,6 +72,8 @@ int keydb_search_subject (KEYDB_HANDLE hd, const char *issuer);
 int keydb_classify_name (const char *name, KEYDB_SEARCH_DESC *desc);
 
 int keydb_store_cert (ksba_cert_t cert, int ephemeral, int *existed);
+gpg_error_t keydb_set_cert_flags (ksba_cert_t cert, int which, int idx,
+                                  unsigned int value);
 
 
 #endif /*GNUPG_KEYDB_H*/
index 0074007..40fa6b0 100644 (file)
@@ -33,6 +33,7 @@
 #include <ksba.h>
 
 #include "keydb.h"
+#include "../kbx/keybox.h" /* for KEYBOX_FLAG_* */
 #include "i18n.h"
 
 struct list_external_parm_s {
@@ -145,7 +146,8 @@ email_kludge (const char *name)
 
 /* List one certificate in colon mode */
 static void
-list_cert_colon (ksba_cert_t cert, FILE *fp, int have_secret)
+list_cert_colon (ksba_cert_t cert, unsigned int validity,
+                 FILE *fp, int have_secret)
 {
   int idx, trustletter = 0;
   char *p;
@@ -155,19 +157,17 @@ list_cert_colon (ksba_cert_t cert, FILE *fp, int have_secret)
 
   fputs (have_secret? "crs:":"crt:", fp);
   trustletter = 0;
+  if ((validity & VALIDITY_REVOKED))
+    trustletter = 'r';
 #if 0
-  if (is_not_valid (cert))
+  else if (is_not_valid (cert))
     putc ('i', fp);
-  else if ( is_revoked (cert) )
-    putc ('r', fp);
   else if ( has_expired (cert))
     putcr ('e', fp);
-  else
 #endif
-    {
-      trustletter = '?'; /*get_validity_info ( pk, NULL );*/
-      putc (trustletter, fp);
-    }
+  else
+    trustletter = '?';
+  putc (trustletter, fp);
 
   fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
   fprintf (fp, ":%u:%d:%s:",
@@ -481,9 +481,17 @@ list_internal_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode)
   lastresname = NULL;
   while (!(rc = keydb_search (hd, desc, ndesc)))
     {
+      unsigned int validity;
+
       if (!names) 
         desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
 
+      rc = keydb_get_flags (hd, KEYBOX_FLAG_VALIDITY, 0, &validity);
+      if (rc)
+        {
+          log_error ("keydb_get_flags failed: %s\n", gpg_strerror (rc));
+          goto leave;
+        }
       rc = keydb_get_cert (hd, &cert);
       if (rc) 
         {
@@ -524,7 +532,7 @@ list_internal_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode)
           || ((mode & 2) && have_secret)  )
         {
           if (ctrl->with_colons)
-            list_cert_colon (cert, fp, have_secret);
+            list_cert_colon (cert, validity, fp, have_secret);
           else if (ctrl->with_chain)
             list_cert_chain (cert, fp);
           else
@@ -568,7 +576,7 @@ list_external_cb (void *cb_value, ksba_cert_t cert)
     }
 
   if (parm->with_colons)
-    list_cert_colon (cert, parm->fp, 0);
+    list_cert_colon (cert, 0, parm->fp, 0);
   else if (parm->with_chain)
     list_cert_chain (cert, parm->fp);
   else