1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-22 10:19:57 +01:00

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

View File

@ -376,7 +376,7 @@ gpgsm_add_to_certlist (ctrl_t ctrl, const char *name, int secret,
next_ambigious: next_ambigious:
rc = keydb_search (ctrl, kh, &desc, 1); rc = keydb_search (ctrl, kh, &desc, 1);
if (rc == -1) if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
rc = 0; rc = 0;
else if (!rc) 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); certlist_t cl = xtrycalloc (1, sizeof *cl);
if (!cl) if (!cl)
rc = out_of_core (); rc = gpg_error_from_syserror ();
else else
{ {
cl->cert = cert; cert = NULL; cl->cert = cert; cert = NULL;
@ -465,7 +465,8 @@ gpgsm_add_to_certlist (ctrl_t ctrl, const char *name, int secret,
keydb_release (kh); keydb_release (kh);
ksba_cert_release (cert); 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: next_ambiguous:
rc = keydb_search (ctrl, kh, &desc, 1); rc = keydb_search (ctrl, kh, &desc, 1);
if (rc == -1) if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
rc = 0; rc = 0;
else else
{ {
@ -603,5 +604,6 @@ gpgsm_find_cert (ctrl_t ctrl,
} }
keydb_release (kh); 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: next_ambigious:
rc = keydb_search (ctrl, kh, &desc, 1); rc = keydb_search (ctrl, kh, &desc, 1);
if (rc == -1) if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
rc = 0; rc = 0;
else if (!rc) else if (!rc)
{ {
@ -104,7 +104,7 @@ delete_one (ctrl_t ctrl, const char *username)
} }
if (rc) if (rc)
{ {
if (rc == -1) if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
rc = gpg_error (GPG_ERR_NO_PUBKEY); rc = gpg_error (GPG_ERR_NO_PUBKEY);
log_error (_("certificate '%s' not found: %s\n"), log_error (_("certificate '%s' not found: %s\n"),
username, gpg_strerror (rc)); 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); ksba_cert_release (cert);
cert = NULL; 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)); log_error ("keydb_search failed: %s\n", gpg_strerror (rc));
else if (b64writer) 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); 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; err = 0;
if (err) if (err)
{ {

View File

@ -36,8 +36,14 @@
#include "../common/ksba-io-support.h" #include "../common/ksba-io-support.h"
#include "../common/compliance.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 struct keyserver_spec
{ {
@ -353,8 +359,8 @@ int gpgsm_create_cms_signature (ctrl_t ctrl,
#define VALIDATE_FLAG_CHAIN_MODEL 2 #define VALIDATE_FLAG_CHAIN_MODEL 2
#define VALIDATE_FLAG_STEED 4 #define VALIDATE_FLAG_STEED 4
int gpgsm_walk_cert_chain (ctrl_t ctrl, gpg_error_t gpgsm_walk_cert_chain (ctrl_t ctrl,
ksba_cert_t start, ksba_cert_t *r_next); ksba_cert_t start, ksba_cert_t *r_next);
int gpgsm_is_root_cert (ksba_cert_t cert); int gpgsm_is_root_cert (ksba_cert_t cert);
int gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, int gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert,
ksba_isotime_t checktime, ksba_isotime_t checktime,

View File

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

View File

@ -68,7 +68,10 @@ struct keydb_local_s
/* I/O buffer with the last search result or NULL. Used if /* I/O buffer with the last search result or NULL. Used if
* D-lines are used to convey the keyblocks. */ * 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. */ /* This flag set while an operation is running on this context. */
unsigned int is_active : 1; unsigned int is_active : 1;
@ -931,15 +934,11 @@ keydb_pop_found_state (KEYDB_HANDLE hd)
/* /* Return the last found certificate. Caller must free it. */
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. */
int int
keydb_get_cert (KEYDB_HANDLE hd, ksba_cert_t *r_cert) keydb_get_cert (KEYDB_HANDLE hd, ksba_cert_t *r_cert)
{ {
int rc = 0; int err = 0;
if (!hd) if (!hd)
return gpg_error (GPG_ERR_INV_VALUE); 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) 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; goto leave;
} }
if ( hd->found < 0 || hd->found >= hd->used) 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; goto leave;
} }
rc = GPG_ERR_BUG; err = GPG_ERR_BUG;
switch (hd->active[hd->found].type) switch (hd->active[hd->found].type)
{ {
case KEYDB_RESOURCE_TYPE_NONE: case KEYDB_RESOURCE_TYPE_NONE:
rc = gpg_error (GPG_ERR_GENERAL); /* oops */ err = gpg_error (GPG_ERR_GENERAL); /* oops */
break; break;
case KEYDB_RESOURCE_TYPE_KEYBOX: 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; break;
} }
leave: leave:
if (DBG_CLOCK) if (DBG_CLOCK)
log_clock ("%s: leave (rc=%d)\n", __func__, rc); log_clock ("%s: leave (rc=%d)\n", __func__, err);
return rc; return err;
} }
@ -995,6 +1025,8 @@ keydb_get_flags (KEYDB_HANDLE hd, int which, int idx, unsigned int *value)
if (hd->use_keyboxd) if (hd->use_keyboxd)
{ {
/* FIXME */ /* FIXME */
*value = 0;
err = 0;
goto leave; goto leave;
} }
@ -1073,6 +1105,36 @@ keydb_set_flags (KEYDB_HANDLE hd, int which, int idx, unsigned int value)
return err; 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. * 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) 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; goto leave;
} }
@ -1246,7 +1321,7 @@ keydb_delete (KEYDB_HANDLE hd)
* operation (which is only relevant for inserts) will be done on this * operation (which is only relevant for inserts) will be done on this
* resource. * resource.
*/ */
int static gpg_error_t
keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved) keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved)
{ {
int rc; 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; hd->found = -1;
if (hd->use_keyboxd) 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 else
{ {
/* and reset all resources */ /* Reset all resources */
for (i=0; !err && i < hd->used; i++) for (i=0; !err && i < hd->used; i++)
{ {
switch (hd->active[i].type) 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, /* Status callback for SEARCH and NEXT operaions. */
* for a keyblock which contains one of the keys described in the DESC array. static gpg_error_t
*/ search_status_cb (void *opaque, const char *line)
int {
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 (ctrl_t ctrl, KEYDB_HANDLE hd,
KEYDB_SEARCH_DESC *desc, size_t ndesc) KEYDB_SEARCH_DESC *desc, size_t ndesc)
{ {
int rc = -1; gpg_error_t err = gpg_error (GPG_ERR_EOF);
unsigned long skipped; unsigned long skipped;
int i; int i;
@ -1442,11 +1566,164 @@ keydb_search (ctrl_t ctrl, KEYDB_HANDLE hd,
if (hd->use_keyboxd) 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) && hd->current >= 0 && hd->current < hd->used)
{ {
switch (hd->active[hd->current].type) 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 */ BUG(); /* we should never see it here */
break; break;
case KEYDB_RESOURCE_TYPE_KEYBOX: case KEYDB_RESOURCE_TYPE_KEYBOX:
rc = keybox_search (hd->active[hd->current].u.kr, desc, ndesc, err = keybox_search (hd->active[hd->current].u.kr, desc, ndesc,
KEYBOX_BLOBTYPE_X509, KEYBOX_BLOBTYPE_X509,
NULL, &skipped); NULL, &skipped);
if (err == -1) /* Map legacy code. */
err = gpg_error (GPG_ERR_EOF);
break; break;
} }
@ -1466,21 +1745,25 @@ keydb_search (ctrl_t ctrl, KEYDB_HANDLE hd,
__func__, __func__,
hd->active[hd->current].type==KEYDB_RESOURCE_TYPE_KEYBOX hd->active[hd->current].type==KEYDB_RESOURCE_TYPE_KEYBOX
? "keybox" : "unknown type", ? "keybox" : "unknown type",
hd->current, hd->used, hd->current, hd->used, gpg_strerror (err));
rc == -1 ? "EOF" : gpg_strerror (rc));
if (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF) if (gpg_err_code (err) == GPG_ERR_EOF)
{ /* EOF -> switch to next resource */ { /* EOF -> switch to next resource */
hd->current++; hd->current++;
} }
else if (!rc) else if (!err)
hd->found = hd->current; 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) if (DBG_CLOCK)
log_clock ("%s: leave (rc=%d)\n", __func__, rc); log_clock ("%s: leave (%s)\n", __func__, gpg_strerror (err));
return rc; 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); rc = keydb_search_fpr (ctrl, kh, fpr);
if (rc != -1) if (gpg_err_code (rc) != GPG_ERR_NOT_FOUND)
{ {
keydb_release (kh); keydb_release (kh);
if (!rc) 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); err = keydb_search_fpr (ctrl, kh, fpr);
if (err) if (err)
{ {
if (err == -1) if (gpg_err_code (err) != gpg_error (GPG_ERR_NOT_FOUND))
err = gpg_error (GPG_ERR_NOT_FOUND);
else
log_error (_("problem re-searching certificate: %s\n"), log_error (_("problem re-searching certificate: %s\n"),
gpg_strerror (err)); gpg_strerror (err));
keydb_release (kh); 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)); log_error ("keydb_search failed: %s\n", gpg_strerror (rc));
leave: 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); gpg_error_t keydb_delete (KEYDB_HANDLE hd);
int keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved);
void keydb_rebuild_caches (void); void keydb_rebuild_caches (void);
gpg_error_t keydb_search_reset (KEYDB_HANDLE hd); 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); KEYDB_SEARCH_DESC *desc, size_t ndesc);
int keydb_search_first (ctrl_t ctrl, KEYDB_HANDLE hd); int keydb_search_first (ctrl_t ctrl, KEYDB_HANDLE hd);
int keydb_search_next (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; chain_id = chain_id_buffer;
ksba_cert_release (next); 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; chain_id = fpr;
is_root = 1; is_root = 1;
} }
@ -1603,7 +1604,7 @@ list_internal_keys (ctrl_t ctrl, strlist_t names, estream_t fp,
lastcert = cert; lastcert = cert;
cert = NULL; cert = NULL;
} }
if (gpg_err_code (rc) == GPG_ERR_EOF || rc == -1 ) if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
rc = 0; rc = 0;
if (rc) if (rc)
log_error ("keydb_search failed: %s\n", gpg_strerror (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); ksba_cert_release (cert);
return rc == -1? 0: rc; return gpg_err_code (rc) == GPG_ERR_NOT_FOUND? 0 : rc;
ksba_failure: ksba_failure:
ksba_cert_release (cert); ksba_cert_release (cert);