* 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.
This commit is contained in:
Werner Koch 2004-02-02 17:09:35 +00:00
parent bdae155c7b
commit 5bda9a8e74
12 changed files with 439 additions and 30 deletions

View 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.

View 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?)

View 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);

View 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.
*
@ -26,12 +26,15 @@
#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;
}

View 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)

View File

@ -42,11 +42,21 @@ extern "C" {
# include <ksba.h>
#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);

View 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.

View 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"));

View 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);

View 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);
}
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;
}

View 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*/

View 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