mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-03 12:11:33 +01:00
sm: Lookup missing issuers first using authorityInfoAccess.
* sm/call-dirmngr.c (gpgsm_dirmngr_lookup): Add optional arg URL and adjust all callers. * sm/certchain.c (oidstr_caIssuers): New. (struct find_up_store_certs_s): Add additional fields. (find_up_store_certs_cb): Store the fingerprint. (find_up_via_auth_info_access): New. (find_up): Try the AIA URI first. -- Note that --auto-issuer-key-retrieve is required to use that. GnuPG-bug-id: 4898 Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
3b27c26241
commit
d57209553d
@ -756,20 +756,24 @@ lookup_status_cb (void *opaque, const char *line)
|
|||||||
|
|
||||||
|
|
||||||
/* Run the Directory Manager's lookup command using the pattern
|
/* Run the Directory Manager's lookup command using the pattern
|
||||||
compiled from the strings given in NAMES. The caller must provide
|
compiled from the strings given in NAMES or from URI. The caller
|
||||||
the callback CB which will be passed cert by cert. Note that CTRL
|
must provide the callback CB which will be passed cert by cert.
|
||||||
is optional. With CACHE_ONLY the dirmngr will search only its own
|
Note that CTRL is optional. With CACHE_ONLY the dirmngr will
|
||||||
key cache. */
|
search only its own key cache. */
|
||||||
int
|
int
|
||||||
gpgsm_dirmngr_lookup (ctrl_t ctrl, strlist_t names, int cache_only,
|
gpgsm_dirmngr_lookup (ctrl_t ctrl, strlist_t names, const char *uri,
|
||||||
|
int cache_only,
|
||||||
void (*cb)(void*, ksba_cert_t), void *cb_value)
|
void (*cb)(void*, ksba_cert_t), void *cb_value)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
char *pattern;
|
|
||||||
char line[ASSUAN_LINELENGTH];
|
char line[ASSUAN_LINELENGTH];
|
||||||
struct lookup_parm_s parm;
|
struct lookup_parm_s parm;
|
||||||
size_t len;
|
size_t len;
|
||||||
assuan_context_t ctx;
|
assuan_context_t ctx;
|
||||||
|
const char *s;
|
||||||
|
|
||||||
|
if ((names && uri) || (!names && !uri))
|
||||||
|
return gpg_error (GPG_ERR_INV_ARG);
|
||||||
|
|
||||||
/* The lookup function can be invoked from the callback of a lookup
|
/* The lookup function can be invoked from the callback of a lookup
|
||||||
function, for example to walk the chain. */
|
function, for example to walk the chain. */
|
||||||
@ -792,19 +796,35 @@ gpgsm_dirmngr_lookup (ctrl_t ctrl, strlist_t names, int cache_only,
|
|||||||
log_fatal ("both dirmngr contexts are in use\n");
|
log_fatal ("both dirmngr contexts are in use\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
pattern = pattern_from_strlist (names);
|
if (names)
|
||||||
if (!pattern)
|
|
||||||
{
|
{
|
||||||
if (ctx == dirmngr_ctx)
|
char *pattern = pattern_from_strlist (names);
|
||||||
release_dirmngr (ctrl);
|
if (!pattern)
|
||||||
else
|
{
|
||||||
release_dirmngr2 (ctrl);
|
if (ctx == dirmngr_ctx)
|
||||||
|
release_dirmngr (ctrl);
|
||||||
|
else
|
||||||
|
release_dirmngr2 (ctrl);
|
||||||
|
|
||||||
return out_of_core ();
|
return out_of_core ();
|
||||||
|
}
|
||||||
|
snprintf (line, DIM(line), "LOOKUP%s %s",
|
||||||
|
cache_only? " --cache-only":"", pattern);
|
||||||
|
xfree (pattern);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (s=uri; *s; s++)
|
||||||
|
if (*s <= ' ')
|
||||||
|
{
|
||||||
|
if (ctx == dirmngr_ctx)
|
||||||
|
release_dirmngr (ctrl);
|
||||||
|
else
|
||||||
|
release_dirmngr2 (ctrl);
|
||||||
|
return gpg_error (GPG_ERR_INV_URI);
|
||||||
|
}
|
||||||
|
snprintf (line, DIM(line), "LOOKUP --url %s", uri);
|
||||||
}
|
}
|
||||||
snprintf (line, DIM(line), "LOOKUP%s %s",
|
|
||||||
cache_only? " --cache-only":"", pattern);
|
|
||||||
xfree (pattern);
|
|
||||||
|
|
||||||
parm.ctrl = ctrl;
|
parm.ctrl = ctrl;
|
||||||
parm.ctx = ctx;
|
parm.ctx = ctx;
|
||||||
|
149
sm/certchain.c
149
sm/certchain.c
@ -38,6 +38,10 @@
|
|||||||
#include "../common/tlv.h"
|
#include "../common/tlv.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* The OID for the authorityInfoAccess's caIssuers. */
|
||||||
|
static const char oidstr_caIssuers[] = "1.3.6.1.5.5.7.48.2";
|
||||||
|
|
||||||
|
|
||||||
/* Object to keep track of certain root certificates. */
|
/* Object to keep track of certain root certificates. */
|
||||||
struct marktrusted_info_s
|
struct marktrusted_info_s
|
||||||
{
|
{
|
||||||
@ -573,6 +577,9 @@ struct find_up_store_certs_s
|
|||||||
{
|
{
|
||||||
ctrl_t ctrl;
|
ctrl_t ctrl;
|
||||||
int count;
|
int count;
|
||||||
|
unsigned int want_fpr:1;
|
||||||
|
unsigned int got_fpr:1;
|
||||||
|
unsigned char fpr[20];
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -582,6 +589,13 @@ find_up_store_certs_cb (void *cb_value, ksba_cert_t cert)
|
|||||||
|
|
||||||
if (keydb_store_cert (parm->ctrl, cert, 1, NULL))
|
if (keydb_store_cert (parm->ctrl, cert, 1, NULL))
|
||||||
log_error ("error storing issuer certificate as ephemeral\n");
|
log_error ("error storing issuer certificate as ephemeral\n");
|
||||||
|
else if (parm->want_fpr && !parm->got_fpr)
|
||||||
|
{
|
||||||
|
if (!gpgsm_get_fingerprint (cert, 0, parm->fpr, NULL))
|
||||||
|
log_error (_("failed to get the fingerprint\n"));
|
||||||
|
else
|
||||||
|
parm->got_fpr = 1;
|
||||||
|
}
|
||||||
parm->count++;
|
parm->count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -602,6 +616,8 @@ find_up_external (ctrl_t ctrl, KEYDB_HANDLE kh,
|
|||||||
const char *s;
|
const char *s;
|
||||||
|
|
||||||
find_up_store_certs_parm.ctrl = ctrl;
|
find_up_store_certs_parm.ctrl = ctrl;
|
||||||
|
find_up_store_certs_parm.want_fpr = 0;
|
||||||
|
find_up_store_certs_parm.got_fpr = 0;
|
||||||
find_up_store_certs_parm.count = 0;
|
find_up_store_certs_parm.count = 0;
|
||||||
|
|
||||||
if (opt.verbose)
|
if (opt.verbose)
|
||||||
@ -620,7 +636,7 @@ find_up_external (ctrl_t ctrl, KEYDB_HANDLE kh,
|
|||||||
add_to_strlist (&names, pattern);
|
add_to_strlist (&names, pattern);
|
||||||
xfree (pattern);
|
xfree (pattern);
|
||||||
|
|
||||||
rc = gpgsm_dirmngr_lookup (ctrl, names, 0, find_up_store_certs_cb,
|
rc = gpgsm_dirmngr_lookup (ctrl, names, NULL, 0, find_up_store_certs_cb,
|
||||||
&find_up_store_certs_parm);
|
&find_up_store_certs_parm);
|
||||||
free_strlist (names);
|
free_strlist (names);
|
||||||
|
|
||||||
@ -653,6 +669,105 @@ find_up_external (ctrl_t ctrl, KEYDB_HANDLE kh,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Helper for find_up(). Locate the certificate for CERT using the
|
||||||
|
* caIssuer from the authorityInfoAccess. KH is the keydb context we
|
||||||
|
* are currently using. On success 0 is returned and the certificate
|
||||||
|
* may be retrieved from the keydb using keydb_get_cert(). If no
|
||||||
|
* suitable authorityInfoAccess is encoded in the certificate
|
||||||
|
* GPG_ERR_NOT_FOUND is returned. */
|
||||||
|
static gpg_error_t
|
||||||
|
find_up_via_auth_info_access (ctrl_t ctrl, KEYDB_HANDLE kh, ksba_cert_t cert)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
struct find_up_store_certs_s find_up_store_certs_parm;
|
||||||
|
char *url, *ldapurl;
|
||||||
|
int idx, i;
|
||||||
|
char *oid;
|
||||||
|
ksba_name_t name;
|
||||||
|
|
||||||
|
find_up_store_certs_parm.ctrl = ctrl;
|
||||||
|
find_up_store_certs_parm.want_fpr = 1;
|
||||||
|
find_up_store_certs_parm.got_fpr = 0;
|
||||||
|
find_up_store_certs_parm.count = 0;
|
||||||
|
|
||||||
|
/* Find suitable URLs; if there is a http scheme we prefer that. */
|
||||||
|
url = ldapurl = NULL;
|
||||||
|
for (idx=0;
|
||||||
|
!url && !(err = ksba_cert_get_authority_info_access (cert, idx,
|
||||||
|
&oid, &name));
|
||||||
|
idx++)
|
||||||
|
{
|
||||||
|
if (!strcmp (oid, oidstr_caIssuers))
|
||||||
|
{
|
||||||
|
for (i=0; !url && ksba_name_enum (name, i); i++)
|
||||||
|
{
|
||||||
|
char *p = ksba_name_get_uri (name, i);
|
||||||
|
if (p)
|
||||||
|
{
|
||||||
|
if (!strncmp (p, "http:", 5) || !strncmp (p, "https:", 6))
|
||||||
|
url = p;
|
||||||
|
else if (ldapurl)
|
||||||
|
xfree (p); /* We already got one. */
|
||||||
|
else if (!strncmp (p, "ldap:",5) || !strncmp (p, "ldaps:",6))
|
||||||
|
ldapurl = p;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
xfree (p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ksba_name_release (name);
|
||||||
|
ksba_free (oid);
|
||||||
|
}
|
||||||
|
if (err && gpg_err_code (err) != GPG_ERR_EOF)
|
||||||
|
{
|
||||||
|
log_error (_("can't get authorityInfoAccess: %s\n"), gpg_strerror (err));
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
if (!url && ldapurl)
|
||||||
|
{
|
||||||
|
/* No HTTP scheme; fallback to LDAP if available. */
|
||||||
|
url = ldapurl;
|
||||||
|
ldapurl = NULL;
|
||||||
|
}
|
||||||
|
xfree (ldapurl);
|
||||||
|
if (!url)
|
||||||
|
return gpg_error (GPG_ERR_NOT_FOUND);
|
||||||
|
|
||||||
|
if (opt.verbose)
|
||||||
|
log_info ("looking up issuer via authorityInfoAccess.caIssuers\n");
|
||||||
|
|
||||||
|
err = gpgsm_dirmngr_lookup (ctrl, NULL, url, 0, find_up_store_certs_cb,
|
||||||
|
&find_up_store_certs_parm);
|
||||||
|
|
||||||
|
/* Although we might receive several certificates we use only the
|
||||||
|
* first one. Or more exacty the first one for which we retrieved
|
||||||
|
* the fingerprint. */
|
||||||
|
if (opt.verbose)
|
||||||
|
log_info ("number of caIssuers found: %d\n",
|
||||||
|
find_up_store_certs_parm.count);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
log_error ("external URL lookup failed: %s\n", gpg_strerror (err));
|
||||||
|
err = gpg_error (GPG_ERR_NOT_FOUND);
|
||||||
|
}
|
||||||
|
else if (!find_up_store_certs_parm.got_fpr)
|
||||||
|
err = gpg_error (GPG_ERR_NOT_FOUND);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int old;
|
||||||
|
/* The retrieved certificates are currently stored in the
|
||||||
|
* ephemeral key DB, so we temporary switch to ephemeral
|
||||||
|
* mode. */
|
||||||
|
old = keydb_set_ephemeral (kh, 1);
|
||||||
|
keydb_search_reset (kh);
|
||||||
|
err = keydb_search_fpr (ctrl, kh, find_up_store_certs_parm.fpr);
|
||||||
|
keydb_set_ephemeral (kh, old);
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Helper for find_up(). Ask the dirmngr for the certificate for
|
/* Helper for find_up(). Ask the dirmngr for the certificate for
|
||||||
ISSUER with optional SERIALNO. KH is the keydb context we are
|
ISSUER with optional SERIALNO. KH is the keydb context we are
|
||||||
currently using. With SUBJECT_MODE set, ISSUER is searched as the
|
currently using. With SUBJECT_MODE set, ISSUER is searched as the
|
||||||
@ -693,7 +808,7 @@ find_up_dirmngr (ctrl_t ctrl, KEYDB_HANDLE kh,
|
|||||||
add_to_strlist (&names, pattern);
|
add_to_strlist (&names, pattern);
|
||||||
xfree (pattern);
|
xfree (pattern);
|
||||||
|
|
||||||
rc = gpgsm_dirmngr_lookup (ctrl, names, 1, find_up_store_certs_cb,
|
rc = gpgsm_dirmngr_lookup (ctrl, names, NULL, 1, find_up_store_certs_cb,
|
||||||
&find_up_store_certs_parm);
|
&find_up_store_certs_parm);
|
||||||
free_strlist (names);
|
free_strlist (names);
|
||||||
|
|
||||||
@ -815,9 +930,18 @@ find_up (ctrl_t ctrl, KEYDB_HANDLE kh,
|
|||||||
/* 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 && opt.auto_issuer_key_retrieve && !find_next)
|
if (rc == -1 && opt.auto_issuer_key_retrieve && !find_next)
|
||||||
{
|
{
|
||||||
rc = find_up_external (ctrl, kh, issuer, keyid);
|
if (!find_up_via_auth_info_access (ctrl, kh, cert))
|
||||||
if (!rc && DBG_X509)
|
{
|
||||||
log_debug (" found via authid and external lookup\n");
|
if (DBG_X509)
|
||||||
|
log_debug (" found via authorityInfoAccess.caIssuers\n");
|
||||||
|
rc = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rc = find_up_external (ctrl, kh, issuer, keyid);
|
||||||
|
if (!rc && DBG_X509)
|
||||||
|
log_debug (" found via authid and external lookup\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -878,9 +1002,18 @@ 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 && opt.auto_issuer_key_retrieve && !find_next)
|
if (rc == -1 && opt.auto_issuer_key_retrieve && !find_next)
|
||||||
{
|
{
|
||||||
rc = find_up_external (ctrl, kh, issuer, NULL);
|
if (!find_up_via_auth_info_access (ctrl, kh, cert))
|
||||||
if (!rc && DBG_X509)
|
{
|
||||||
log_debug (" found via issuer and external lookup\n");
|
if (DBG_X509)
|
||||||
|
log_debug (" found via authorityInfoAccess.caIssuers\n");
|
||||||
|
rc = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rc = find_up_external (ctrl, kh, issuer, NULL);
|
||||||
|
if (!rc && DBG_X509)
|
||||||
|
log_debug (" found via issuer and external lookup\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -424,7 +424,8 @@ gpg_error_t gpgsm_agent_export_key (ctrl_t ctrl, const char *keygrip,
|
|||||||
int gpgsm_dirmngr_isvalid (ctrl_t ctrl,
|
int gpgsm_dirmngr_isvalid (ctrl_t ctrl,
|
||||||
ksba_cert_t cert, ksba_cert_t issuer_cert,
|
ksba_cert_t cert, ksba_cert_t issuer_cert,
|
||||||
int use_ocsp);
|
int use_ocsp);
|
||||||
int gpgsm_dirmngr_lookup (ctrl_t ctrl, strlist_t names, int cache_only,
|
int gpgsm_dirmngr_lookup (ctrl_t ctrl, strlist_t names, const char *uri,
|
||||||
|
int cache_only,
|
||||||
void (*cb)(void*, ksba_cert_t), void *cb_value);
|
void (*cb)(void*, ksba_cert_t), void *cb_value);
|
||||||
int gpgsm_dirmngr_run_command (ctrl_t ctrl, const char *command,
|
int gpgsm_dirmngr_run_command (ctrl_t ctrl, const char *command,
|
||||||
int argc, char **argv);
|
int argc, char **argv);
|
||||||
|
@ -1607,7 +1607,7 @@ list_external_keys (ctrl_t ctrl, strlist_t names, estream_t fp, int raw_mode)
|
|||||||
parm.with_chain = ctrl->with_chain;
|
parm.with_chain = ctrl->with_chain;
|
||||||
parm.raw_mode = raw_mode;
|
parm.raw_mode = raw_mode;
|
||||||
|
|
||||||
rc = gpgsm_dirmngr_lookup (ctrl, names, 0, list_external_cb, &parm);
|
rc = gpgsm_dirmngr_lookup (ctrl, names, NULL, 0, list_external_cb, &parm);
|
||||||
if (gpg_err_code (rc) == GPG_ERR_EOF || rc == -1
|
if (gpg_err_code (rc) == GPG_ERR_EOF || rc == -1
|
||||||
|| gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
|
|| gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
|
||||||
rc = 0; /* "Not found" is not an error here. */
|
rc = 0; /* "Not found" is not an error here. */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user