sm: Implement initial support for keyboxd.

* sm/gpgsm.h (MAX_FINGERPRINT_LEN): New.
* sm/keydb.c (struct keydb_local_s): Change definition of
search_result.
(keydb_get_cert): Implement keyboxd mode.
(keydb_get_flags): Temporary hack for keyboxd mode.  Needs to be
fixed.
(struct store_parm_s, store_inq_cb): New.
(keydb_insert_cert): Implement keyboxd mode.
(keydb_locate_writable): Make static.
(keydb_search_reset): Implement keyboxd mode.
(search_status_cb): New.
(keydb_search): Implement keyboxd mode. Replace return code -1 by
GPG_ERR_NOT_FOUND.
(keydb_set_cert_flags): Replace return code -1 by GPG_ERR_NOT_FOUND.
* sm/keylist.c (list_cert_colon): Adjust for replacement of -1 by
GPG_ERR_NOT_FOUND.
(list_internal_keys): Ditto.
* sm/sign.c (add_certificate_list): Ditto.
* sm/certchain.c (find_up_search_by_keyid): Ditto.
(find_up_external, find_up, find_up_dirmngr): Ditto.
(gpgsm_walk_cert_chain): Ditto.
(get_regtp_ca_info): Ditto.
* sm/certlist.c (gpgsm_add_to_certlist): Ditto.
(gpgsm_find_cert): Ditto.
* sm/delete.c (delete_one): Ditto.
* sm/export.c (gpgsm_export): Ditto.
(gpgsm_p12_export): Ditto.
* sm/import.c (gpgsm_import_files): Ditto.
--

Note that keyboxd is not yet able to handle the ephemeral flag.  This
needs fixing here and in keyboxd.  Delete et al. is also not yet
implemented.  A basic key listing works, though.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2020-09-10 13:05:17 +02:00
parent c9677d416e
commit ed6ebb696e
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
10 changed files with 382 additions and 91 deletions

View File

@ -440,7 +440,7 @@ check_cert_policy (ksba_cert_t cert, int listmode, estream_t fplist)
/* Helper function for find_up. This resets the key handle and search
for an issuer ISSUER with a subjectKeyIdentifier of KEYID. Returns
0 on success or -1 when not found. */
0 on success or GPG_ERR_NOT_FOUND when not found. */
static int
find_up_search_by_keyid (ctrl_t ctrl, KEYDB_HANDLE kh,
const char *issuer, ksba_sexp_t keyid)
@ -460,7 +460,7 @@ find_up_search_by_keyid (ctrl_t ctrl, KEYDB_HANDLE kh,
if (rc)
{
log_error ("keydb_get_cert() failed: rc=%d\n", rc);
rc = -1;
rc = gpg_error (GPG_ERR_NOT_FOUND);
goto leave;
}
xfree (subj);
@ -475,7 +475,7 @@ find_up_search_by_keyid (ctrl_t ctrl, KEYDB_HANDLE kh,
if (rc)
{
log_error ("keydb_get_validity() failed: rc=%d\n", rc);
rc = -1;
rc = gpg_error (GPG_ERR_NOT_FOUND);
goto leave;
}
@ -544,7 +544,7 @@ find_up_search_by_keyid (ctrl_t ctrl, KEYDB_HANDLE kh,
if (rc)
{
log_error ("keydb_get_validity() failed: rc=%d\n", rc);
rc = -1;
rc = gpg_error (GPG_ERR_NOT_FOUND);
goto leave;
}
if (*not_after && strcmp (ctrl->current_time, not_after) > 0 )
@ -558,7 +558,7 @@ find_up_search_by_keyid (ctrl_t ctrl, KEYDB_HANDLE kh,
if (rc)
{
log_error ("keydb_search_fpr() failed: rc=%d\n", rc);
rc = -1;
rc = gpg_error (GPG_ERR_NOT_FOUND);
goto leave;
}
/* Ready. The NE_FOUND_CERT is available via keydb_get_cert. */
@ -569,7 +569,7 @@ find_up_search_by_keyid (ctrl_t ctrl, KEYDB_HANDLE kh,
ksba_cert_release (ne_found_cert);
ksba_cert_release (cert);
xfree (subj);
return rc? -1:0;
return rc? gpg_error (GPG_ERR_NOT_FOUND) : 0;
}
@ -646,10 +646,10 @@ find_up_external (ctrl_t ctrl, KEYDB_HANDLE kh,
if (rc)
{
log_error ("external key lookup failed: %s\n", gpg_strerror (rc));
rc = -1;
rc = gpg_error (GPG_ERR_NOT_FOUND);
}
else if (!find_up_store_certs_parm.count)
rc = -1;
rc = gpg_err_code (rc) == GPG_ERR_NOT_FOUND;
else
{
int old;
@ -818,7 +818,8 @@ find_up_dirmngr (ctrl_t ctrl, KEYDB_HANDLE kh,
if (rc && !opt.quiet)
log_info (_("dirmngr cache-only key lookup failed: %s\n"),
gpg_strerror (rc));
return (!rc && find_up_store_certs_parm.count)? 0 : -1;
return ((!rc && find_up_store_certs_parm.count)
? 0 : gpg_error (GPG_ERR_NOT_FOUND));
}
@ -828,7 +829,7 @@ find_up_dirmngr (ctrl_t ctrl, KEYDB_HANDLE kh,
FIND_NEXT is true, the function shall return the next possible
issuer. The certificate itself is not directly returned but a
keydb_get_cert on the keydb context KH will return it. Returns 0
on success, -1 if not found or an error code. */
on success, GPG_ERR_NOT_FOUND if not found or another error code. */
static int
find_up (ctrl_t ctrl, KEYDB_HANDLE kh,
ksba_cert_t cert, const char *issuer, int find_next)
@ -857,13 +858,13 @@ find_up (ctrl_t ctrl, KEYDB_HANDLE kh,
into the ephemeral DB and let the code below do the
actual retrieve. Thus there is no error checking.
Skipped in find_next mode as usual. */
if (rc == -1 && !find_next)
if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND && !find_next)
find_up_dirmngr (ctrl, kh, authidno, s, 0);
/* In case of an error try the ephemeral DB. We can't do
that in find_next mode because we can't keep the search
state then. */
if (rc == -1 && !find_next)
if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND && !find_next)
{
int old = keydb_set_ephemeral (kh, 1);
if (!old)
@ -877,11 +878,11 @@ find_up (ctrl_t ctrl, KEYDB_HANDLE kh,
}
keydb_set_ephemeral (kh, old);
}
if (rc)
rc = -1; /* Need to make sure to have this error code. */
if (rc) /* Need to make sure to have this error code. */
rc = gpg_error (GPG_ERR_NOT_FOUND);
}
if (rc == -1 && keyid && !find_next)
if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND && keyid && !find_next)
{
/* Not found by AKI.issuer_sn. Lets try the AKI.ki
instead. Loop over all certificates with that issuer as
@ -900,13 +901,13 @@ find_up (ctrl_t ctrl, KEYDB_HANDLE kh,
log_debug (" found via authid and keyid (ephem)\n");
keydb_set_ephemeral (kh, old);
}
if (rc)
rc = -1; /* Need to make sure to have this error code. */
if (rc) /* Need to make sure to have this error code. */
rc = gpg_error (GPG_ERR_NOT_FOUND);
}
/* If we still didn't found it, try to find it via the subject
from the dirmngr-cache. */
if (rc == -1 && !find_next)
if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND && !find_next)
{
if (!find_up_dirmngr (ctrl, kh, NULL, issuer, 1))
{
@ -920,15 +921,16 @@ find_up (ctrl_t ctrl, KEYDB_HANDLE kh,
}
keydb_set_ephemeral (kh, old);
}
if (rc)
rc = -1; /* Need to make sure to have this error code. */
if (rc) /* Need to make sure to have this error code. */
rc = gpg_error (GPG_ERR_NOT_FOUND);
if (!rc && DBG_X509)
log_debug (" found via authid and issuer from dirmngr cache\n");
}
/* If we still didn't found it, try an external lookup. */
if (rc == -1 && !find_next && !ctrl->offline)
if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND
&& !find_next && !ctrl->offline)
{
/* We allow AIA also if CRLs are enabled; both can be used
* as a web bug so it does not make sense to not use AIA if
@ -952,9 +954,9 @@ find_up (ctrl_t ctrl, KEYDB_HANDLE kh,
/* Print a note so that the user does not feel too helpless when
an issuer certificate was found and gpgsm prints BAD
signature because it is not the correct one. */
if (rc == -1 && opt.quiet)
if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND && opt.quiet)
;
else if (rc == -1)
else if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
{
log_info ("%sissuer certificate ", find_next?"next ":"");
if (keyid)
@ -982,7 +984,7 @@ find_up (ctrl_t ctrl, KEYDB_HANDLE kh,
if (rc) /* Not found via authorithyKeyIdentifier, try regular issuer name. */
rc = keydb_search_subject (ctrl, kh, issuer);
if (rc == -1 && !find_next)
if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND && !find_next)
{
int old;
@ -1004,7 +1006,7 @@ find_up (ctrl_t ctrl, KEYDB_HANDLE kh,
}
/* Still not found. If enabled, try an external lookup. */
if (rc == -1 && !find_next && !ctrl->offline)
if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND && !find_next && !ctrl->offline)
{
if ((opt.auto_issuer_key_retrieve || !opt.no_crl_check)
&& !find_up_via_auth_info_access (ctrl, kh, cert))
@ -1026,8 +1028,8 @@ find_up (ctrl_t ctrl, KEYDB_HANDLE kh,
/* Return the next certificate up in the chain starting at START.
Returns -1 when there are no more certificates. */
int
Returns GPG_ERR_NOT_FOUND when there are no more certificates. */
gpg_error_t
gpgsm_walk_cert_chain (ctrl_t ctrl, ksba_cert_t start, ksba_cert_t *r_next)
{
int rc = 0;
@ -1060,7 +1062,7 @@ gpgsm_walk_cert_chain (ctrl_t ctrl, ksba_cert_t start, ksba_cert_t *r_next)
if (is_root_cert (start, issuer, subject))
{
rc = -1; /* we are at the root */
rc = gpg_error (GPG_ERR_NOT_FOUND); /* we are at the root */
goto leave;
}
@ -1069,7 +1071,7 @@ gpgsm_walk_cert_chain (ctrl_t ctrl, ksba_cert_t start, ksba_cert_t *r_next)
{
/* It is quite common not to have a certificate, so better don't
print an error here. */
if (rc != -1 && opt.verbose > 1)
if (gpg_err_code (rc) != GPG_ERR_NOT_FOUND && opt.verbose > 1)
log_error ("failed to find issuer's certificate: rc=%d\n", rc);
rc = gpg_error (GPG_ERR_MISSING_ISSUER_CERT);
goto leave;
@ -2340,7 +2342,7 @@ get_regtp_ca_info (ctrl_t ctrl, ksba_cert_t cert, int *chainlen)
cert = next;
}
ksba_cert_release (cert);
if (rc != -1 || !depth || depth == DIM(array) )
if (gpg_err_code (rc) != GPG_ERR_NOT_FOUND || !depth || depth == DIM(array) )
{
/* We did not reached the root. */
goto leave;

View File

@ -376,7 +376,7 @@ gpgsm_add_to_certlist (ctrl_t ctrl, const char *name, int secret,
next_ambigious:
rc = keydb_search (ctrl, kh, &desc, 1);
if (rc == -1)
if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
rc = 0;
else if (!rc)
{
@ -450,7 +450,7 @@ gpgsm_add_to_certlist (ctrl_t ctrl, const char *name, int secret,
{
certlist_t cl = xtrycalloc (1, sizeof *cl);
if (!cl)
rc = out_of_core ();
rc = gpg_error_from_syserror ();
else
{
cl->cert = cert; cert = NULL;
@ -465,7 +465,8 @@ gpgsm_add_to_certlist (ctrl_t ctrl, const char *name, int secret,
keydb_release (kh);
ksba_cert_release (cert);
return rc == -1? gpg_error (GPG_ERR_NO_PUBKEY): rc;
return (gpg_err_code (rc) == GPG_ERR_NOT_FOUND
? gpg_error (GPG_ERR_NO_PUBKEY): rc);
}
@ -549,7 +550,7 @@ gpgsm_find_cert (ctrl_t ctrl,
}
next_ambiguous:
rc = keydb_search (ctrl, kh, &desc, 1);
if (rc == -1)
if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
rc = 0;
else
{
@ -603,5 +604,6 @@ gpgsm_find_cert (ctrl_t ctrl,
}
keydb_release (kh);
return rc == -1? gpg_error (GPG_ERR_NO_PUBKEY): rc;
return (gpg_err_code (rc) == GPG_ERR_NOT_FOUND?
gpg_error (GPG_ERR_NO_PUBKEY): rc);
}

View File

@ -80,7 +80,7 @@ delete_one (ctrl_t ctrl, const char *username)
next_ambigious:
rc = keydb_search (ctrl, kh, &desc, 1);
if (rc == -1)
if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
rc = 0;
else if (!rc)
{
@ -104,7 +104,7 @@ delete_one (ctrl_t ctrl, const char *username)
}
if (rc)
{
if (rc == -1)
if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
rc = gpg_error (GPG_ERR_NO_PUBKEY);
log_error (_("certificate '%s' not found: %s\n"),
username, gpg_strerror (rc));

View File

@ -295,7 +295,7 @@ gpgsm_export (ctrl_t ctrl, strlist_t names, estream_t stream)
ksba_cert_release (cert);
cert = NULL;
}
if (rc && rc != -1)
if (rc && gpg_err_code (rc) != GPG_ERR_NOT_FOUND)
log_error ("keydb_search failed: %s\n", gpg_strerror (rc));
else if (b64writer)
{
@ -389,7 +389,7 @@ gpgsm_p12_export (ctrl_t ctrl, const char *name, estream_t stream, int rawmode)
}
err = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
}
else if (err == -1 || gpg_err_code (err) == GPG_ERR_EOF)
else if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
err = 0;
if (err)
{

View File

@ -36,8 +36,14 @@
#include "../common/ksba-io-support.h"
#include "../common/compliance.h"
/* The maximum length of a binary fingerprints. This is used to
* provide a static buffer and will be increased if we need to support
* longer fingerprints. */
#define MAX_FINGERPRINT_LEN 32
/* The maximum length of a binary digest. */
#define MAX_DIGEST_LEN 64 /* Fits for SHA-512 */
#define MAX_DIGEST_LEN 64
struct keyserver_spec
{
@ -353,8 +359,8 @@ int gpgsm_create_cms_signature (ctrl_t ctrl,
#define VALIDATE_FLAG_CHAIN_MODEL 2
#define VALIDATE_FLAG_STEED 4
int gpgsm_walk_cert_chain (ctrl_t ctrl,
ksba_cert_t start, ksba_cert_t *r_next);
gpg_error_t gpgsm_walk_cert_chain (ctrl_t ctrl,
ksba_cert_t start, ksba_cert_t *r_next);
int gpgsm_is_root_cert (ksba_cert_t cert);
int gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert,
ksba_isotime_t checktime,

View File

@ -550,7 +550,7 @@ gpgsm_import_files (ctrl_t ctrl, int nfiles, char **files,
int fd = of (*files);
rc = import_one (ctrl, &stats, fd);
close (fd);
if (rc == -1)
if (rc == -1/* legacy*/ || gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
rc = 0;
}
}

View File

@ -68,7 +68,10 @@ struct keydb_local_s
/* I/O buffer with the last search result or NULL. Used if
* D-lines are used to convey the keyblocks. */
iobuf_t search_result;
struct {
char *buf;
size_t len;
} search_result;
/* This flag set while an operation is running on this context. */
unsigned int is_active : 1;
@ -931,15 +934,11 @@ keydb_pop_found_state (KEYDB_HANDLE hd)
/*
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. */
/* Return the last found certificate. Caller must free it. */
int
keydb_get_cert (KEYDB_HANDLE hd, ksba_cert_t *r_cert)
{
int rc = 0;
int err = 0;
if (!hd)
return gpg_error (GPG_ERR_INV_VALUE);
@ -949,31 +948,62 @@ keydb_get_cert (KEYDB_HANDLE hd, ksba_cert_t *r_cert)
if (hd->use_keyboxd)
{
/* FIXME */
ksba_cert_t cert;
/* Fixme: We should clear that also in non-keyboxd mode but we
* did not in the past and thus all code should be checked
* whether this is okay. If we run into error in keyboxd mode,
* this is a not as severe because keyboxd is currently
* experimental. */
*r_cert = NULL;
if (!hd->kbl->search_result.buf || !hd->kbl->search_result.len)
{
err = gpg_error (GPG_ERR_VALUE_NOT_FOUND);
goto leave;
}
err = ksba_cert_new (&cert);
if (err)
goto leave;
err = ksba_cert_init_from_mem (cert,
hd->kbl->search_result.buf,
hd->kbl->search_result.len);
if (err)
{
ksba_cert_release (cert);
goto leave;
}
xfree (hd->kbl->search_result.buf);
hd->kbl->search_result.buf = NULL;
hd->kbl->search_result.len = 0;
*r_cert = cert;
goto leave;
}
if ( hd->found < 0 || hd->found >= hd->used)
{
rc = -1; /* nothing found */
/* Fixme: It would be better to use GPG_ERR_VALUE_NOT_FOUND here
* but for now we use NOT_FOUND because that is our standard
* replacement for the formerly used (-1). */
err = gpg_error (GPG_ERR_NOT_FOUND); /* nothing found */
goto leave;
}
rc = GPG_ERR_BUG;
err = GPG_ERR_BUG;
switch (hd->active[hd->found].type)
{
case KEYDB_RESOURCE_TYPE_NONE:
rc = gpg_error (GPG_ERR_GENERAL); /* oops */
err = gpg_error (GPG_ERR_GENERAL); /* oops */
break;
case KEYDB_RESOURCE_TYPE_KEYBOX:
rc = keybox_get_cert (hd->active[hd->found].u.kr, r_cert);
err = keybox_get_cert (hd->active[hd->found].u.kr, r_cert);
break;
}
leave:
if (DBG_CLOCK)
log_clock ("%s: leave (rc=%d)\n", __func__, rc);
return rc;
log_clock ("%s: leave (rc=%d)\n", __func__, err);
return err;
}
@ -995,6 +1025,8 @@ keydb_get_flags (KEYDB_HANDLE hd, int which, int idx, unsigned int *value)
if (hd->use_keyboxd)
{
/* FIXME */
*value = 0;
err = 0;
goto leave;
}
@ -1073,6 +1105,36 @@ keydb_set_flags (KEYDB_HANDLE hd, int which, int idx, unsigned int value)
return err;
}
/* Communication object for Keyboxd STORE commands. */
struct store_parm_s
{
assuan_context_t ctx;
const void *data; /* The certificate in X.509 binary format. */
size_t datalen; /* The length of DATA. */
};
/* Handle the inquiries from the STORE command. */
static gpg_error_t
store_inq_cb (void *opaque, const char *line)
{
struct store_parm_s *parm = opaque;
gpg_error_t err = 0;
if (has_leading_keyword (line, "BLOB"))
{
if (parm->data)
err = assuan_send_data (parm->ctx, parm->data, parm->datalen);
}
else
return gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
return err;
}
/*
* Insert a new Certificate into one of the resources.
*/
@ -1094,7 +1156,20 @@ keydb_insert_cert (KEYDB_HANDLE hd, ksba_cert_t cert)
if (hd->use_keyboxd)
{
/* FIXME */
struct store_parm_s parm;
parm.ctx = hd->kbl->ctx;
parm.data = ksba_cert_get_image (cert, &parm.datalen);
if (!parm.data)
{
log_debug ("broken ksba cert object\n");
err = gpg_error (GPG_ERR_GENERAL);
goto leave;
}
err = assuan_transact (hd->kbl->ctx, "STORE --insert",
NULL, NULL,
store_inq_cb, &parm,
NULL, NULL);
goto leave;
}
@ -1246,7 +1321,7 @@ keydb_delete (KEYDB_HANDLE hd)
* operation (which is only relevant for inserts) will be done on this
* resource.
*/
int
static gpg_error_t
keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved)
{
int rc;
@ -1277,7 +1352,7 @@ keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved)
}
}
return -1;
return gpg_error (GPG_ERR_NOT_FOUND);
}
/*
@ -1328,11 +1403,16 @@ keydb_search_reset (KEYDB_HANDLE hd)
hd->found = -1;
if (hd->use_keyboxd)
{
/* FIXME */
}
/* All we need is to tell search that a reset is pending. Note that
* keydb_new sets this flag as well. To comply with the
* specification of keydb_delete_keyblock we also need to clear the
* ubid flag so that after a reset a delete can't be performed. */
hd->kbl->need_search_reset = 1;
hd->last_ubid_valid = 0;
}
else
{
/* and reset all resources */
/* Reset all resources */
for (i=0; !err && i < hd->used; i++)
{
switch (hd->active[i].type)
@ -1404,15 +1484,59 @@ keydb_search_desc_dump (struct keydb_search_desc *desc)
}
/*
* Search through all keydb resources, starting at the current position,
* for a keyblock which contains one of the keys described in the DESC array.
*/
int
/* Status callback for SEARCH and NEXT operaions. */
static gpg_error_t
search_status_cb (void *opaque, const char *line)
{
KEYDB_HANDLE hd = opaque;
gpg_error_t err = 0;
const char *s;
if ((s = has_leading_keyword (line, "PUBKEY_INFO")))
{
if (atoi (s) != PUBKEY_TYPE_X509)
err = gpg_error (GPG_ERR_WRONG_BLOB_TYPE);
else
{
hd->last_ubid_valid = 0;
while (*s && !spacep (s))
s++;
if (hex2fixedbuf (s, hd->last_ubid, sizeof hd->last_ubid))
hd->last_ubid_valid = 1;
else
err = gpg_error (GPG_ERR_INV_VALUE);
}
}
return err;
}
/* Search through all keydb resources, starting at the current
* position, for a keyblock which contains one of the keys described
* in the DESC array. In keyboxd mode the search is instead delegated
* to the keyboxd.
*
* DESC is an array of search terms with NDESC entries. The search
* terms are or'd together. That is, the next entry in the DB that
* matches any of the descriptions will be returned.
*
* Note: this function resumes searching where the last search left
* off (i.e., at the current file position). If you want to search
* from the start of the database, then you need to first call
* keydb_search_reset().
*
* If no key matches the search description, the error code
* GPG_ERR_NOT_FOUND is retruned. If there was a match, 0 is
* returned. If an error occurred, that error code is returned.
*
* The returned key is considered to be selected and the certificate
* can be detched via keydb_get_cert. */
gpg_error_t
keydb_search (ctrl_t ctrl, KEYDB_HANDLE hd,
KEYDB_SEARCH_DESC *desc, size_t ndesc)
{
int rc = -1;
gpg_error_t err = gpg_error (GPG_ERR_EOF);
unsigned long skipped;
int i;
@ -1442,11 +1566,164 @@ keydb_search (ctrl_t ctrl, KEYDB_HANDLE hd,
if (hd->use_keyboxd)
{
/* FIXME */
char line[ASSUAN_LINELENGTH];
/* Clear the result objects. */
if (hd->kbl->search_result.buf)
{
xfree (hd->kbl->search_result.buf);
hd->kbl->search_result.buf = NULL;
hd->kbl->search_result.len = 0;
}
/* Check whether this is a NEXT search. */
if (!hd->kbl->need_search_reset)
{
/* A reset was not requested thus continue the search. The
* keyboxd keeps the context of the search and thus the NEXT
* operates on the last search pattern. This is the way how
* we always used the keydb functions. In theory we were
* able to modify the search pattern between searches but
* that is not anymore supported by keyboxd and a cursory
* check does not show that we actually made use of that
* misfeature. */
snprintf (line, sizeof line, "NEXT --x509");
goto do_search;
}
hd->kbl->need_search_reset = 0;
if (!ndesc)
{
err = gpg_error (GPG_ERR_INV_ARG);
goto leave;
}
/* FIXME: Implement --multi */
switch (desc->mode)
{
case KEYDB_SEARCH_MODE_EXACT:
snprintf (line, sizeof line, "SEARCH --x509 =%s", desc[0].u.name);
break;
case KEYDB_SEARCH_MODE_SUBSTR:
snprintf (line, sizeof line, "SEARCH --x509 *%s", desc[0].u.name);
break;
case KEYDB_SEARCH_MODE_MAIL:
snprintf (line, sizeof line, "SEARCH --x509 <%s", desc[0].u.name);
break;
case KEYDB_SEARCH_MODE_MAILSUB:
snprintf (line, sizeof line, "SEARCH --x509 @%s", desc[0].u.name);
break;
case KEYDB_SEARCH_MODE_MAILEND:
snprintf (line, sizeof line, "SEARCH --x509 .%s", desc[0].u.name);
break;
case KEYDB_SEARCH_MODE_WORDS:
snprintf (line, sizeof line, "SEARCH --x509 +%s", desc[0].u.name);
break;
case KEYDB_SEARCH_MODE_SHORT_KID:
snprintf (line, sizeof line, "SEARCH --x509 0x%08lX",
(ulong)desc->u.kid[1]);
break;
case KEYDB_SEARCH_MODE_LONG_KID:
snprintf (line, sizeof line, "SEARCH --x509 0x%08lX%08lX",
(ulong)desc->u.kid[0], (ulong)desc->u.kid[1]);
break;
case KEYDB_SEARCH_MODE_FPR:
{
unsigned char hexfpr[MAX_FINGERPRINT_LEN * 2 + 1];
log_assert (desc[0].fprlen <= MAX_FINGERPRINT_LEN);
bin2hex (desc[0].u.fpr, desc[0].fprlen, hexfpr);
snprintf (line, sizeof line, "SEARCH --x509 0x%s", hexfpr);
}
break;
case KEYDB_SEARCH_MODE_ISSUER:
snprintf (line, sizeof line, "SEARCH --x509 #/%s", desc[0].u.name);
break;
case KEYDB_SEARCH_MODE_ISSUER_SN:
if (desc[0].snhex)
snprintf (line, sizeof line, "SEARCH --x509 #%.*s/%s",
(int)desc[0].snlen, desc[0].sn, desc[0].u.name);
else
{
char *hexsn = bin2hex (desc[0].sn, desc[0].snlen, NULL);
if (!hexsn)
{
err = gpg_error_from_syserror ();
goto leave;
}
snprintf (line, sizeof line, "SEARCH --x509 #%s/%s",
hexsn, desc[0].u.name);
xfree (hexsn);
}
break;
case KEYDB_SEARCH_MODE_SN:
snprintf (line, sizeof line, "SEARCH --x509 #%s", desc[0].u.name);
break;
case KEYDB_SEARCH_MODE_SUBJECT:
snprintf (line, sizeof line, "SEARCH --x509 /%s", desc[0].u.name);
break;
case KEYDB_SEARCH_MODE_KEYGRIP:
{
unsigned char hexgrip[KEYGRIP_LEN * 2 + 1];
bin2hex (desc[0].u.grip, KEYGRIP_LEN, hexgrip);
snprintf (line, sizeof line, "SEARCH --x509 &%s", hexgrip);
}
break;
case KEYDB_SEARCH_MODE_UBID:
{
unsigned char hexubid[UBID_LEN * 2 + 1];
bin2hex (desc[0].u.ubid, UBID_LEN, hexubid);
snprintf (line, sizeof line, "SEARCH --x509 ^%s", hexubid);
}
break;
case KEYDB_SEARCH_MODE_FIRST:
snprintf (line, sizeof line, "SEARCH --x509");
break;
case KEYDB_SEARCH_MODE_NEXT:
log_debug ("%s: mode next - we should not get to here!\n", __func__);
snprintf (line, sizeof line, "NEXT --x509");
break;
default:
err = gpg_error (GPG_ERR_INV_ARG);
goto leave;
}
do_search:
hd->last_ubid_valid = 0;
/* To avoid silent truncation we error out on a too long line. */
if (strlen (line) + 5 >= sizeof line)
err = gpg_error (GPG_ERR_ASS_LINE_TOO_LONG);
else
err = kbx_client_data_cmd (hd->kbl->kcd, line, search_status_cb, hd);
if (!err && !(err = kbx_client_data_wait (hd->kbl->kcd,
&hd->kbl->search_result.buf,
&hd->kbl->search_result.len)))
{
/* if (hd->last_ubid_valid) */
/* log_printhex (hd->last_ubid, 20, "found UBID:"); */
}
}
else
else /* Local keyring search. */
{
while ((rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF)
while (gpg_err_code (err) == GPG_ERR_EOF
&& hd->current >= 0 && hd->current < hd->used)
{
switch (hd->active[hd->current].type)
@ -1455,9 +1732,11 @@ keydb_search (ctrl_t ctrl, KEYDB_HANDLE hd,
BUG(); /* we should never see it here */
break;
case KEYDB_RESOURCE_TYPE_KEYBOX:
rc = keybox_search (hd->active[hd->current].u.kr, desc, ndesc,
KEYBOX_BLOBTYPE_X509,
NULL, &skipped);
err = keybox_search (hd->active[hd->current].u.kr, desc, ndesc,
KEYBOX_BLOBTYPE_X509,
NULL, &skipped);
if (err == -1) /* Map legacy code. */
err = gpg_error (GPG_ERR_EOF);
break;
}
@ -1466,21 +1745,25 @@ keydb_search (ctrl_t ctrl, KEYDB_HANDLE hd,
__func__,
hd->active[hd->current].type==KEYDB_RESOURCE_TYPE_KEYBOX
? "keybox" : "unknown type",
hd->current, hd->used,
rc == -1 ? "EOF" : gpg_strerror (rc));
hd->current, hd->used, gpg_strerror (err));
if (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF)
if (gpg_err_code (err) == GPG_ERR_EOF)
{ /* EOF -> switch to next resource */
hd->current++;
}
else if (!rc)
else if (!err)
hd->found = hd->current;
}
}
leave:
/* The NOTHING_FOUND error is triggered by a NEXT command. */
if (gpg_err_code (err) == GPG_ERR_EOF
|| gpg_err_code (err) == GPG_ERR_NOTHING_FOUND)
err = gpg_error (GPG_ERR_NOT_FOUND);
if (DBG_CLOCK)
log_clock ("%s: leave (rc=%d)\n", __func__, rc);
return rc;
log_clock ("%s: leave (%s)\n", __func__, gpg_strerror (err));
return err;
}
@ -1621,7 +1904,7 @@ keydb_store_cert (ctrl_t ctrl, ksba_cert_t cert, int ephemeral, int *existed)
}
rc = keydb_search_fpr (ctrl, kh, fpr);
if (rc != -1)
if (gpg_err_code (rc) != GPG_ERR_NOT_FOUND)
{
keydb_release (kh);
if (!rc)
@ -1715,9 +1998,7 @@ keydb_set_cert_flags (ctrl_t ctrl, ksba_cert_t cert, int ephemeral,
err = keydb_search_fpr (ctrl, kh, fpr);
if (err)
{
if (err == -1)
err = gpg_error (GPG_ERR_NOT_FOUND);
else
if (gpg_err_code (err) != gpg_error (GPG_ERR_NOT_FOUND))
log_error (_("problem re-searching certificate: %s\n"),
gpg_strerror (err));
keydb_release (kh);
@ -1836,7 +2117,7 @@ keydb_clear_some_cert_flags (ctrl_t ctrl, strlist_t names)
}
}
}
if (rc && rc != -1)
if (rc && gpg_err_code (rc) != GPG_ERR_NOT_FOUND)
log_error ("keydb_search failed: %s\n", gpg_strerror (rc));
leave:

View File

@ -52,11 +52,10 @@ gpg_error_t keydb_update_cert (KEYDB_HANDLE hd, ksba_cert_t cert);
gpg_error_t keydb_delete (KEYDB_HANDLE hd);
int keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved);
void keydb_rebuild_caches (void);
gpg_error_t keydb_search_reset (KEYDB_HANDLE hd);
int keydb_search (ctrl_t ctrl, KEYDB_HANDLE hd,
gpg_error_t keydb_search (ctrl_t ctrl, KEYDB_HANDLE hd,
KEYDB_SEARCH_DESC *desc, size_t ndesc);
int keydb_search_first (ctrl_t ctrl, KEYDB_HANDLE hd);
int keydb_search_next (ctrl_t ctrl, KEYDB_HANDLE hd);

View File

@ -452,8 +452,9 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity,
chain_id = chain_id_buffer;
ksba_cert_release (next);
}
else if (rc == -1) /* We have reached the root certificate. */
else if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
{
/* We have reached the root certificate. */
chain_id = fpr;
is_root = 1;
}
@ -1603,7 +1604,7 @@ list_internal_keys (ctrl_t ctrl, strlist_t names, estream_t fp,
lastcert = cert;
cert = NULL;
}
if (gpg_err_code (rc) == GPG_ERR_EOF || rc == -1 )
if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
rc = 0;
if (rc)
log_error ("keydb_search failed: %s\n", gpg_strerror (rc));

View File

@ -291,7 +291,7 @@ add_certificate_list (ctrl_t ctrl, ksba_cms_t cms, ksba_cert_t cert)
}
ksba_cert_release (cert);
return rc == -1? 0: rc;
return gpg_err_code (rc) == GPG_ERR_NOT_FOUND? 0 : rc;
ksba_failure:
ksba_cert_release (cert);