aboutsummaryrefslogtreecommitdiffstats
path: root/sm
diff options
context:
space:
mode:
Diffstat (limited to 'sm')
-rw-r--r--sm/ChangeLog17
-rw-r--r--sm/certchain.c6
-rw-r--r--sm/delete.c9
-rw-r--r--sm/keydb.c160
-rw-r--r--sm/keydb.h10
-rw-r--r--sm/keylist.c30
6 files changed, 209 insertions, 23 deletions
diff --git a/sm/ChangeLog b/sm/ChangeLog
index 2a584e079..cde6e8439 100644
--- a/sm/ChangeLog
+++ b/sm/ChangeLog
@@ -1,3 +1,20 @@
+2004-02-02 Werner Koch <[email protected]>
+
+ * 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 <[email protected]>
* certchain.c (check_cert_policy): Fixed read error checking.
diff --git a/sm/certchain.c b/sm/certchain.c
index a48dbd737..bcc66660a 100644
--- a/sm/certchain.c
+++ b/sm/certchain.c
@@ -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"));
diff --git a/sm/delete.c b/sm/delete.c
index 8b04bc426..11a0a5476 100644
--- a/sm/delete.c
+++ b/sm/delete.c
@@ -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);
diff --git a/sm/keydb.c b/sm/keydb.c
index 62e3ab2f3..f770135c1 100644
--- a/sm/keydb.c
+++ b/sm/keydb.c
@@ -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);
+}
+
+
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)
/*
- 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;
+}
diff --git a/sm/keydb.h b/sm/keydb.h
index 0133d0ccd..2e9ed1573 100644
--- a/sm/keydb.h
+++ b/sm/keydb.h
@@ -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*/
diff --git a/sm/keylist.c b/sm/keylist.c
index 007400729..40fa6b043 100644
--- a/sm/keylist.c
+++ b/sm/keylist.c
@@ -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