gpgsm: Try avoiding too many open calls for pubring.kbx.

* sm/gpgsm.h (struct server_control_s): Add fields cached_kh and
cached_kh_for_set_cert_flags.
* sm/certchain.c (do_validate_chain): Cache the keydb handle.
* sm/keydb.c (keydb_set_cert_flags): Ditto
(keydb_release): Invalidate the caches.
--

In particular under Windows opening a file may be a expensive
operation if malware^Dantivirus software gets in the way.

Due to changed locking behaviour this patch has a regression risk.
This commit is contained in:
Werner Koch 2023-05-04 12:01:04 +02:00
parent 0f0ab04435
commit 39f907cb00
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
3 changed files with 42 additions and 13 deletions

View File

@ -1604,7 +1604,14 @@ do_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t checktime_arg,
return 0;
}
kh = keydb_new (ctrl);
if (ctrl->cached_kh)
{
kh = ctrl->cached_kh;
ctrl->cached_kh = NULL;
keydb_search_reset (kh);
}
else
kh = keydb_new (ctrl);
if (!kh)
{
log_error (_("failed to allocate keyDB handle\n"));
@ -2147,7 +2154,12 @@ do_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t checktime_arg,
gnupg_copy_time (r_exptime, exptime);
xfree (issuer);
xfree (subject);
keydb_release (kh);
if (!ctrl->cached_kh)
ctrl->cached_kh = kh;
else
keydb_release (kh);
while (chain)
{
chain_item_t ci_next = chain->next;

View File

@ -270,6 +270,10 @@ struct server_control_s
/* The revocation info. Used as a helper inc ertchain.c */
gnupg_isotime_t revoked_at;
char *revocation_reason;
/* We cache the key data base handle. */
void *cached_kh;
void *cached_kh_for_set_cert_flags;
};

View File

@ -701,6 +701,11 @@ keydb_release (KEYDB_HANDLE hd)
}
}
if (hd->ctrl->cached_kh == hd)
hd->ctrl->cached_kh = NULL;
if (hd->ctrl->cached_kh_for_set_cert_flags == hd)
hd->ctrl->cached_kh_for_set_cert_flags = NULL;
xfree (hd);
if (DBG_CLOCK)
log_clock ("%s: leave\n", __func__);
@ -2023,7 +2028,14 @@ keydb_set_cert_flags (ctrl_t ctrl, ksba_cert_t cert, int ephemeral,
return gpg_error (GPG_ERR_GENERAL);
}
kh = keydb_new (ctrl);
if (ctrl->cached_kh_for_set_cert_flags)
{
kh = ctrl->cached_kh_for_set_cert_flags;
ctrl->cached_kh_for_set_cert_flags = NULL;
keydb_search_reset (kh);
}
else
kh = keydb_new (ctrl);
if (!kh)
{
log_error (_("failed to allocate keyDB handle\n"));
@ -2039,8 +2051,7 @@ keydb_set_cert_flags (ctrl_t ctrl, ksba_cert_t cert, int ephemeral,
if (err)
{
log_error (_("error locking keybox: %s\n"), gpg_strerror (err));
keydb_release (kh);
return err;
goto leave;
}
}
@ -2050,16 +2061,14 @@ keydb_set_cert_flags (ctrl_t ctrl, ksba_cert_t cert, int ephemeral,
if (gpg_err_code (err) != GPG_ERR_NOT_FOUND)
log_error (_("problem re-searching certificate: %s\n"),
gpg_strerror (err));
keydb_release (kh);
return err;
goto leave;
}
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;
goto leave;
}
value = ((old_value & ~mask) | (value & mask));
@ -2070,13 +2079,17 @@ keydb_set_cert_flags (ctrl_t ctrl, ksba_cert_t cert, int ephemeral,
if (err)
{
log_error (_("error storing flags: %s\n"), gpg_strerror (err));
keydb_release (kh);
return err;
goto leave;
}
}
err = 0;
keydb_release (kh);
return 0;
leave:
if (!err && !ctrl->cached_kh_for_set_cert_flags)
ctrl->cached_kh_for_set_cert_flags = kh;
else
keydb_release (kh);
return err;
}