1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-10-29 19:48:43 +01:00

gpgsm: Use a cache for ISTRUSTED queries.

* sm/call-agent.c (struct istrusted_cache_s): New.
(istrusted_cache, istrusted_cache_valid): New.
(istrusted_cache_disabled): New.
(flush_istrusted_cache): New.
(struct istrusted_status_parm_s): New.
(istrusted_status_cb): Fill the cache.
(gpgsm_agent_istrusted): Implement a cache.
--

Not a really measurable performance improvements on Linux but maybe
somewhat on Windows (not yet tested).  However, it does not clutter
the log files with IPC calls returning NOT_TRUSTED.

GnuPG-bug-id: 7308
(cherry picked from commit ef2be95258)
This commit is contained in:
Werner Koch 2024-10-02 14:20:03 +02:00
parent 4fa82eec43
commit 09d4b8f496
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B

View File

@ -82,7 +82,45 @@ struct default_inq_parm_s
assuan_context_t ctx; assuan_context_t ctx;
}; };
/* An object and variable to cache ISTRUSTED calls. The cache is
* global and reset with each mark trusted. We also have a disabled
* flag here in case the gpg-agent did not allow us to query all
* trusted keys at once. */
struct istrusted_cache_s
{
struct istrusted_cache_s *next;
struct rootca_flags_s flags; /* The flags of this fingerprint. */
char fpr[1]; /* The fingerprint of the trusted key in hex format. */
};
typedef struct istrusted_cache_s *istrusted_cache_t;
static istrusted_cache_t istrusted_cache;
static int istrusted_cache_valid;
static int istrusted_cache_disabled;
static void
flush_istrusted_cache (void)
{
istrusted_cache_t mycache;
/* First unlink the cache to be npth safe. Note that we don't clear
* the the disabled flag - this is considered a permantent error. */
mycache = istrusted_cache;
istrusted_cache = NULL;
istrusted_cache_valid = 0;
while (mycache)
{
istrusted_cache_t next = mycache->next;
xfree (mycache);
mycache = next;
}
}
/* Print a warning if the server's version number is less than our /* Print a warning if the server's version number is less than our
version number. Returns an error code on a connection problem. */ version number. Returns an error code on a connection problem. */
static gpg_error_t static gpg_error_t
@ -861,29 +899,51 @@ gpgsm_agent_scd_keypairinfo (ctrl_t ctrl, strlist_t *r_list)
struct istrusted_status_parm_s
{
struct rootca_flags_s flags;
istrusted_cache_t cache;
};
static gpg_error_t static gpg_error_t
istrusted_status_cb (void *opaque, const char *line) istrusted_status_cb (void *opaque, const char *line)
{ {
struct rootca_flags_s *flags = opaque; struct istrusted_status_parm_s *parm = opaque;
const char *s; const char *s;
if ((s = has_leading_keyword (line, "TRUSTLISTFLAG"))) if ((s = has_leading_keyword (line, "TRUSTLISTFLAG")))
{ {
line = s; line = s;
if (has_leading_keyword (line, "relax")) if (has_leading_keyword (line, "relax"))
flags->relax = 1; parm->flags.relax = 1;
else if (has_leading_keyword (line, "cm")) else if (has_leading_keyword (line, "cm"))
flags->chain_model = 1; parm->flags.chain_model = 1;
else if (has_leading_keyword (line, "qual")) else if (has_leading_keyword (line, "qual"))
flags->qualified = 1; parm->flags.qualified = 1;
else if (has_leading_keyword (line, "de-vs")) else if (has_leading_keyword (line, "de-vs"))
flags->de_vs = 1; parm->flags.de_vs = 1;
/* Copy the current flags to the current list item. */
if (parm->cache)
parm->cache->flags = parm->flags;
}
else if ((s = has_leading_keyword (line, "TRUSTLISTFPR")) && *s)
{
istrusted_cache_t ci;
ci = xtrymalloc (sizeof *ci + strlen (s));
if (!ci)
return gpg_error_from_syserror ();
strcpy (ci->fpr, s);
memset (&ci->flags, 0, sizeof ci->flags);
ci->next = parm->cache;
parm->cache = ci;
} }
return 0; return 0;
} }
/* Ask the agent whether the certificate is in the list of trusted /* Ask the agent whether the certificate is in the list of trusted
keys. The certificate is either specified by the CERT object or by keys. The certificate is either specified by the CERT object or by
the fingerprint HEXFPR. ROOTCA_FLAGS is guaranteed to be cleared the fingerprint HEXFPR. ROOTCA_FLAGS is guaranteed to be cleared
@ -894,8 +954,12 @@ gpgsm_agent_istrusted (ctrl_t ctrl, ksba_cert_t cert, const char *hexfpr,
{ {
int rc; int rc;
char line[ASSUAN_LINELENGTH]; char line[ASSUAN_LINELENGTH];
char *fpr_buffer = NULL;
struct istrusted_status_parm_s parm;
istrusted_cache_t ci;
memset (rootca_flags, 0, sizeof *rootca_flags); memset (rootca_flags, 0, sizeof *rootca_flags);
memset (&parm, 0, sizeof parm);
if (cert && hexfpr) if (cert && hexfpr)
return gpg_error (GPG_ERR_INV_ARG); return gpg_error (GPG_ERR_INV_ARG);
@ -904,29 +968,64 @@ gpgsm_agent_istrusted (ctrl_t ctrl, ksba_cert_t cert, const char *hexfpr,
if (rc) if (rc)
return rc; return rc;
if (hexfpr) if (!hexfpr)
{ {
snprintf (line, DIM(line), "ISTRUSTED %s", hexfpr); fpr_buffer = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
} if (!fpr_buffer)
else
{
char *fpr;
fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
if (!fpr)
{ {
log_error ("error getting the fingerprint\n"); log_error ("error getting the fingerprint\n");
return gpg_error (GPG_ERR_GENERAL); rc = gpg_error (GPG_ERR_GENERAL);
goto leave;
} }
hexfpr = fpr_buffer;
snprintf (line, DIM(line), "ISTRUSTED %s", fpr);
xfree (fpr);
} }
/* First try to get the info from the cache. */
if (!istrusted_cache_disabled && !istrusted_cache_valid)
{
/* Cache is empty - fill it. */
rc = assuan_transact (agent_ctx, "LISTTRUSTED --status",
NULL, NULL, NULL, NULL,
istrusted_status_cb, &parm);
if (rc)
{
if (gpg_err_code (rc) != GPG_ERR_FORBIDDEN)
log_error ("filling istrusted cache failed: %s\n",
gpg_strerror (rc));
istrusted_cache_disabled = 1;
rc = 0; /* Fallback to single requests. */
}
else
istrusted_cache_valid = 1;
}
if (istrusted_cache_valid)
{
for (ci = istrusted_cache; ci; ci = ci->next)
if (!strcmp (ci->fpr, hexfpr))
break; /* Found. */
if (ci)
{
*rootca_flags = ci->flags;
rootca_flags->valid = 1;
rc = 0;
}
else
rc = gpg_error (GPG_ERR_NOT_TRUSTED);
goto leave;
}
snprintf (line, DIM(line), "ISTRUSTED %s", hexfpr);
rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL,
istrusted_status_cb, rootca_flags); istrusted_status_cb, &parm);
if (!rc) if (!rc)
rootca_flags->valid = 1; {
*rootca_flags = parm.flags;
rootca_flags->valid = 1;
}
leave:
xfree (fpr_buffer);
return rc; return rc;
} }
@ -968,6 +1067,10 @@ gpgsm_agent_marktrusted (ctrl_t ctrl, ksba_cert_t cert)
rc = assuan_transact (agent_ctx, line, NULL, NULL, rc = assuan_transact (agent_ctx, line, NULL, NULL,
default_inq_cb, &inq_parm, NULL, NULL); default_inq_cb, &inq_parm, NULL, NULL);
/* Marktrusted changes the trustlist and thus we need to flush the
* cache. */
if (!rc)
flush_istrusted_cache ();
return rc; return rc;
} }