From 5bda9a8e74753da5d7ee912c32a0137ebce2abd8 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Mon, 2 Feb 2004 17:09:35 +0000 Subject: [PATCH] * keybox.h (keybox_flag_t): New. * 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. --- kbx/ChangeLog | 6 ++ kbx/keybox-blob.c | 11 +-- kbx/keybox-defs.h | 6 ++ kbx/keybox-search.c | 116 +++++++++++++++++++++++++++++++- kbx/keybox-update.c | 82 +++++++++++++++++++++++ kbx/keybox.h | 16 ++++- sm/ChangeLog | 17 +++++ sm/certchain.c | 6 ++ sm/delete.c | 9 ++- sm/keydb.c | 160 +++++++++++++++++++++++++++++++++++++++++--- sm/keydb.h | 10 +++ sm/keylist.c | 30 ++++++--- 12 files changed, 439 insertions(+), 30 deletions(-) diff --git a/kbx/ChangeLog b/kbx/ChangeLog index 07a198200..a866e04f0 100644 --- a/kbx/ChangeLog +++ b/kbx/ChangeLog @@ -1,3 +1,9 @@ +2004-02-02 Werner Koch + + * 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 Adjusted for API changes in Libksba. diff --git a/kbx/keybox-blob.c b/kbx/keybox-blob.c index 3d815321f..96595436c 100644 --- a/kbx/keybox-blob.c +++ b/kbx/keybox-blob.c @@ -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?) diff --git a/kbx/keybox-defs.h b/kbx/keybox-defs.h index fa145f7e5..17431502f 100644 --- a/kbx/keybox-defs.h +++ b/kbx/keybox-defs.h @@ -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); diff --git a/kbx/keybox-search.c b/kbx/keybox-search.c index b8add5abe..f23bfdada 100644 --- a/kbx/keybox-search.c +++ b/kbx/keybox-search.c @@ -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. * @@ -26,12 +26,15 @@ #include #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; +} + diff --git a/kbx/keybox-update.c b/kbx/keybox-update.c index ed9ca2bf7..47e53966a 100644 --- a/kbx/keybox-update.c +++ b/kbx/keybox-update.c @@ -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) diff --git a/kbx/keybox.h b/kbx/keybox.h index 5a5ad2933..e4dc9d642 100644 --- a/kbx/keybox.h +++ b/kbx/keybox.h @@ -42,11 +42,21 @@ extern "C" { # include #endif - - 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 --*/ void *keybox_register_file (const char *fname, int secret); int keybox_is_writable (void *token); @@ -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); 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 + + * 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 * 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 #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 #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