mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-21 10:09:57 +01:00
gpgsm: Print revocation date and reason in cert listings.
* dirmngr/ocsp.c (ocsp_isvalid): Add args r_revoked_at and r_revocation_reason. * dirmngr/server.c (cmd_isvalid): Emit a new REVOCATIONINFO status. (cmd_checkocsp): Ditto. * sm/call-dirmngr.c (struct isvalid_status_parm_s): Add new fields. (isvalid_status_cb): Parse REVOCATIONINFO. (gpgsm_dirmngr_isvalid): Add args r_revoked_at and r_revocation_reason. * sm/gpgsm.h (struct server_control_s): Add fields revoked_art and revocation_reason. * sm/keylist.c (list_cert_raw): Print revocation date. (list_cert_std): Ditto. -- Note that for now we do this only for OCSP because it is an important piece of information when using the chain model. For a sample key see commit 7fa1d3cc821dca1ea8e1c80a0bdd527177c185ee.
This commit is contained in:
parent
4f1b9e3abb
commit
b6abaed2b5
@ -650,10 +650,13 @@ check_signature (ctrl_t ctrl,
|
||||
/* Check whether the certificate either given by fingerprint CERT_FPR
|
||||
or directly through the CERT object is valid by running an OCSP
|
||||
transaction. With FORCE_DEFAULT_RESPONDER set only the configured
|
||||
default responder is used. */
|
||||
default responder is used. If R_REVOKED_AT or R_REASON are not
|
||||
NULL and the certificat has been revoked the revocation time and
|
||||
the reasons are stored there. */
|
||||
gpg_error_t
|
||||
ocsp_isvalid (ctrl_t ctrl, ksba_cert_t cert, const char *cert_fpr,
|
||||
int force_default_responder)
|
||||
int force_default_responder, ksba_isotime_t r_revoked_at,
|
||||
const char **r_reason)
|
||||
{
|
||||
gpg_error_t err;
|
||||
ksba_ocsp_t ocsp = NULL;
|
||||
@ -672,6 +675,12 @@ ocsp_isvalid (ctrl_t ctrl, ksba_cert_t cert, const char *cert_fpr,
|
||||
char *oid;
|
||||
ksba_name_t name;
|
||||
fingerprint_list_t default_signer = NULL;
|
||||
const char *sreason;
|
||||
|
||||
if (r_revoked_at)
|
||||
*r_revoked_at = 0;
|
||||
if (r_reason)
|
||||
*r_reason = NULL;
|
||||
|
||||
/* Get the certificate. */
|
||||
if (cert)
|
||||
@ -842,8 +851,36 @@ ocsp_isvalid (ctrl_t ctrl, ksba_cert_t cert, const char *cert_fpr,
|
||||
more important message than the failure of our
|
||||
cache. */
|
||||
}
|
||||
}
|
||||
|
||||
switch (reason)
|
||||
{
|
||||
case KSBA_CRLREASON_UNSPECIFIED:
|
||||
sreason = "unspecified"; break;
|
||||
case KSBA_CRLREASON_KEY_COMPROMISE:
|
||||
sreason = "key compromise"; break;
|
||||
case KSBA_CRLREASON_CA_COMPROMISE:
|
||||
sreason = "CA compromise"; break;
|
||||
case KSBA_CRLREASON_AFFILIATION_CHANGED:
|
||||
sreason = "affiliation changed"; break;
|
||||
case KSBA_CRLREASON_SUPERSEDED:
|
||||
sreason = "superseded"; break;
|
||||
case KSBA_CRLREASON_CESSATION_OF_OPERATION:
|
||||
sreason = "cessation of operation"; break;
|
||||
case KSBA_CRLREASON_CERTIFICATE_HOLD:
|
||||
sreason = "certificate on hold"; break;
|
||||
case KSBA_CRLREASON_REMOVE_FROM_CRL:
|
||||
sreason = "removed from CRL"; break;
|
||||
case KSBA_CRLREASON_PRIVILEGE_WITHDRAWN:
|
||||
sreason = "privilege withdrawn"; break;
|
||||
case KSBA_CRLREASON_AA_COMPROMISE:
|
||||
sreason = "AA compromise"; break;
|
||||
case KSBA_CRLREASON_OTHER:
|
||||
sreason = "other"; break;
|
||||
default: sreason = "?"; break;
|
||||
}
|
||||
}
|
||||
else
|
||||
sreason = "";
|
||||
|
||||
if (opt.verbose)
|
||||
{
|
||||
@ -855,29 +892,19 @@ ocsp_isvalid (ctrl_t ctrl, ksba_cert_t cert, const char *cert_fpr,
|
||||
this_update, next_update);
|
||||
if (status == KSBA_STATUS_REVOKED)
|
||||
log_info (_("certificate has been revoked at: %s due to: %s\n"),
|
||||
revocation_time,
|
||||
reason == KSBA_CRLREASON_UNSPECIFIED? "unspecified":
|
||||
reason == KSBA_CRLREASON_KEY_COMPROMISE? "key compromise":
|
||||
reason == KSBA_CRLREASON_CA_COMPROMISE? "CA compromise":
|
||||
reason == KSBA_CRLREASON_AFFILIATION_CHANGED?
|
||||
"affiliation changed":
|
||||
reason == KSBA_CRLREASON_SUPERSEDED? "superseded":
|
||||
reason == KSBA_CRLREASON_CESSATION_OF_OPERATION?
|
||||
"cessation of operation":
|
||||
reason == KSBA_CRLREASON_CERTIFICATE_HOLD?
|
||||
"certificate on hold":
|
||||
reason == KSBA_CRLREASON_REMOVE_FROM_CRL?
|
||||
"removed from CRL":
|
||||
reason == KSBA_CRLREASON_PRIVILEGE_WITHDRAWN?
|
||||
"privilege withdrawn":
|
||||
reason == KSBA_CRLREASON_AA_COMPROMISE? "AA compromise":
|
||||
reason == KSBA_CRLREASON_OTHER? "other":"?");
|
||||
revocation_time, sreason);
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (status == KSBA_STATUS_REVOKED)
|
||||
err = gpg_error (GPG_ERR_CERT_REVOKED);
|
||||
{
|
||||
err = gpg_error (GPG_ERR_CERT_REVOKED);
|
||||
if (r_revoked_at)
|
||||
gnupg_copy_time (r_revoked_at, revocation_time);
|
||||
if (r_reason)
|
||||
*r_reason = sreason;
|
||||
}
|
||||
else if (status == KSBA_STATUS_UNKNOWN)
|
||||
err = gpg_error (GPG_ERR_NO_DATA);
|
||||
else if (status != KSBA_STATUS_GOOD)
|
||||
|
@ -23,7 +23,9 @@
|
||||
#define OCSP_H
|
||||
|
||||
gpg_error_t ocsp_isvalid (ctrl_t ctrl, ksba_cert_t cert, const char *cert_fpr,
|
||||
int force_default_responder);
|
||||
int force_default_responder,
|
||||
gnupg_isotime_t r_revoked_at,
|
||||
const char **r_reason);
|
||||
|
||||
/* Release the list of OCSP certificates hold in the CTRL object. */
|
||||
void release_ctrl_ocsp_certs (ctrl_t ctrl);
|
||||
|
@ -1310,6 +1310,9 @@ cmd_isvalid (assuan_context_t ctx, char *line)
|
||||
again:
|
||||
if (ocsp_mode)
|
||||
{
|
||||
gnupg_isotime_t revoked_at;
|
||||
const char *reason;
|
||||
|
||||
/* Note, that we currently ignore the supplied fingerprint FPR;
|
||||
* instead ocsp_isvalid does an inquire to ask for the cert.
|
||||
* The fingerprint may eventually be used to lookup the
|
||||
@ -1317,7 +1320,12 @@ cmd_isvalid (assuan_context_t ctx, char *line)
|
||||
if (!opt.allow_ocsp)
|
||||
err = gpg_error (GPG_ERR_NOT_SUPPORTED);
|
||||
else
|
||||
err = ocsp_isvalid (ctrl, NULL, NULL, force_default_responder);
|
||||
err = ocsp_isvalid (ctrl, NULL, NULL, force_default_responder,
|
||||
revoked_at, &reason);
|
||||
|
||||
if (gpg_err_code (err) == GPG_ERR_CERT_REVOKED)
|
||||
dirmngr_status_printf (ctrl, "REVOCATIONINFO", "%s %s",
|
||||
revoked_at, reason);
|
||||
|
||||
if (gpg_err_code (err) == GPG_ERR_CONFIGURATION
|
||||
&& gpg_err_source (err) == GPG_ERR_SOURCE_DIRMNGR)
|
||||
@ -1512,6 +1520,8 @@ cmd_checkocsp (assuan_context_t ctx, char *line)
|
||||
unsigned char fprbuffer[20], *fpr;
|
||||
ksba_cert_t cert;
|
||||
int force_default_responder;
|
||||
gnupg_isotime_t revoked_at;
|
||||
const char *reason;
|
||||
|
||||
force_default_responder = has_option (line, "--force-default-responder");
|
||||
line = skip_options (line);
|
||||
@ -1547,12 +1557,18 @@ cmd_checkocsp (assuan_context_t ctx, char *line)
|
||||
goto leave;
|
||||
}
|
||||
|
||||
assert (cert);
|
||||
log_assert (cert);
|
||||
|
||||
if (!opt.allow_ocsp)
|
||||
err = gpg_error (GPG_ERR_NOT_SUPPORTED);
|
||||
else
|
||||
err = ocsp_isvalid (ctrl, cert, NULL, force_default_responder);
|
||||
err = ocsp_isvalid (ctrl, cert, NULL, force_default_responder,
|
||||
revoked_at, &reason);
|
||||
|
||||
if (gpg_err_code (err) == GPG_ERR_CERT_REVOKED)
|
||||
dirmngr_status_printf (ctrl, "REVOCATIONINFO", "%s %s",
|
||||
revoked_at, reason);
|
||||
|
||||
|
||||
leave:
|
||||
ksba_cert_release (cert);
|
||||
|
@ -64,6 +64,8 @@ struct isvalid_status_parm_s {
|
||||
ctrl_t ctrl;
|
||||
int seen;
|
||||
unsigned char fpr[20];
|
||||
gnupg_isotime_t revoked_at;
|
||||
char *revocation_reason; /* malloced or NULL */
|
||||
};
|
||||
|
||||
|
||||
@ -491,6 +493,19 @@ isvalid_status_cb (void *opaque, const char *line)
|
||||
if (!*s || !unhexify_fpr (s, parm->fpr))
|
||||
parm->seen++; /* Bump it to indicate an error. */
|
||||
}
|
||||
else if ((s = has_leading_keyword (line, "REVOCATIONINFO")))
|
||||
{
|
||||
if (*s && strlen (s) >= 15)
|
||||
{
|
||||
memcpy (parm->revoked_at, s, 15);
|
||||
parm->revoked_at[15] = 0;
|
||||
}
|
||||
s += 15;
|
||||
while (*s && spacep (s))
|
||||
s++;
|
||||
xfree (parm->revocation_reason);
|
||||
parm->revocation_reason = *s? xtrystrdup (s) : NULL;
|
||||
}
|
||||
else if (warning_and_note_printer (line))
|
||||
{
|
||||
}
|
||||
@ -512,10 +527,15 @@ isvalid_status_cb (void *opaque, const char *line)
|
||||
0 = Do CRL check.
|
||||
1 = Do an OCSP check but fallback to CRL unless CRLs are disabled.
|
||||
2 = Do only an OCSP check (used for the chain model).
|
||||
|
||||
If R_REVOKED_AT pr R_REASON are not NULL and the certificate has
|
||||
been revoked the revocation time and the reason are copied to there.
|
||||
The caller needs to free R_REASON.
|
||||
*/
|
||||
gpg_error_t
|
||||
gpgsm_dirmngr_isvalid (ctrl_t ctrl,
|
||||
ksba_cert_t cert, ksba_cert_t issuer_cert, int use_ocsp)
|
||||
ksba_cert_t cert, ksba_cert_t issuer_cert, int use_ocsp,
|
||||
gnupg_isotime_t r_revoked_at, char **r_reason)
|
||||
{
|
||||
static int did_options;
|
||||
int rc;
|
||||
@ -524,6 +544,11 @@ gpgsm_dirmngr_isvalid (ctrl_t ctrl,
|
||||
struct inq_certificate_parm_s parm;
|
||||
struct isvalid_status_parm_s stparm;
|
||||
|
||||
if (r_revoked_at)
|
||||
*r_revoked_at = 0;
|
||||
if (r_reason)
|
||||
*r_reason = NULL;
|
||||
|
||||
rc = start_dirmngr (ctrl);
|
||||
if (rc)
|
||||
return rc;
|
||||
@ -553,6 +578,8 @@ gpgsm_dirmngr_isvalid (ctrl_t ctrl,
|
||||
stparm.ctrl = ctrl;
|
||||
stparm.seen = 0;
|
||||
memset (stparm.fpr, 0, 20);
|
||||
stparm.revoked_at[0] = 0;
|
||||
stparm.revocation_reason = NULL;
|
||||
|
||||
/* It is sufficient to send the options only once because we have
|
||||
* one connection per process only. */
|
||||
@ -577,6 +604,19 @@ gpgsm_dirmngr_isvalid (ctrl_t ctrl,
|
||||
if (opt.verbose > 1)
|
||||
log_info ("response of dirmngr: %s\n", rc? gpg_strerror (rc): "okay");
|
||||
|
||||
if (gpg_err_code (rc) == GPG_ERR_CERT_REVOKED
|
||||
&& !check_isotime (stparm.revoked_at))
|
||||
{
|
||||
if (r_revoked_at)
|
||||
gnupg_copy_time (r_revoked_at, stparm.revoked_at);
|
||||
if (r_reason)
|
||||
{
|
||||
*r_reason = stparm.revocation_reason;
|
||||
stparm.revocation_reason = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!rc && stparm.seen)
|
||||
{
|
||||
/* Need to also check the certificate validity. */
|
||||
@ -634,7 +674,9 @@ gpgsm_dirmngr_isvalid (ctrl_t ctrl,
|
||||
ksba_cert_release (rspcert);
|
||||
}
|
||||
}
|
||||
|
||||
release_dirmngr (ctrl);
|
||||
xfree (stparm.revocation_reason);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -1193,6 +1193,8 @@ is_cert_still_valid (ctrl_t ctrl, int chain_model, int lm, estream_t fp,
|
||||
int *any_revoked, int *any_no_crl, int *any_crl_too_old)
|
||||
{
|
||||
gpg_error_t err;
|
||||
gnupg_isotime_t revoked_at;
|
||||
char *reason;
|
||||
|
||||
if (ctrl->offline || (opt.no_crl_check && !ctrl->use_ocsp))
|
||||
{
|
||||
@ -1221,7 +1223,20 @@ is_cert_still_valid (ctrl_t ctrl, int chain_model, int lm, estream_t fp,
|
||||
|
||||
err = gpgsm_dirmngr_isvalid (ctrl,
|
||||
subject_cert, issuer_cert,
|
||||
chain_model? 2 : !!ctrl->use_ocsp);
|
||||
chain_model? 2 : !!ctrl->use_ocsp,
|
||||
revoked_at, &reason);
|
||||
if (gpg_err_code (err) == GPG_ERR_CERT_REVOKED)
|
||||
{
|
||||
gnupg_copy_time (ctrl->revoked_at, revoked_at);
|
||||
xfree (ctrl->revocation_reason);
|
||||
ctrl->revocation_reason = reason;
|
||||
reason = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
xfree (reason);
|
||||
reason = (NULL);
|
||||
}
|
||||
audit_log_ok (ctrl->audit, AUDIT_CRL_CHECK, err);
|
||||
|
||||
if (err)
|
||||
|
@ -2228,6 +2228,8 @@ gpgsm_init_default_ctrl (struct server_control_s *ctrl)
|
||||
ctrl->use_ocsp = opt.enable_ocsp;
|
||||
ctrl->validation_model = default_validation_model;
|
||||
ctrl->offline = opt.disable_dirmngr;
|
||||
ctrl->revoked_at[0] = 0;
|
||||
ctrl->revocation_reason = NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -2237,6 +2239,8 @@ void
|
||||
gpgsm_deinit_default_ctrl (ctrl_t ctrl)
|
||||
{
|
||||
gpgsm_keydb_deinit_session_data (ctrl);
|
||||
xfree (ctrl->revocation_reason);
|
||||
ctrl->revocation_reason = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -264,6 +264,10 @@ struct server_control_s
|
||||
|
||||
/* The current time. Used as a helper in certchain.c. */
|
||||
ksba_isotime_t current_time;
|
||||
|
||||
/* The revocation info. Used as a helper inc ertchain.c */
|
||||
gnupg_isotime_t revoked_at;
|
||||
char *revocation_reason;
|
||||
};
|
||||
|
||||
|
||||
@ -496,7 +500,9 @@ gpg_error_t gpgsm_agent_export_key (ctrl_t ctrl, const char *keygrip,
|
||||
/*-- call-dirmngr.c --*/
|
||||
gpg_error_t gpgsm_dirmngr_isvalid (ctrl_t ctrl,
|
||||
ksba_cert_t cert, ksba_cert_t issuer_cert,
|
||||
int use_ocsp);
|
||||
int use_ocsp,
|
||||
gnupg_isotime_t r_revoked_at,
|
||||
char **r_reason);
|
||||
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);
|
||||
|
18
sm/keylist.c
18
sm/keylist.c
@ -1201,6 +1201,15 @@ list_cert_raw (ctrl_t ctrl, KEYDB_HANDLE hd,
|
||||
{
|
||||
err = gpgsm_validate_chain (ctrl, cert,
|
||||
GNUPG_ISOTIME_NONE, NULL, 1, fp, 0, NULL);
|
||||
if (gpg_err_code (err) == GPG_ERR_CERT_REVOKED
|
||||
&& !check_isotime (ctrl->revoked_at))
|
||||
{
|
||||
es_fputs (" revoked: ", fp);
|
||||
gpgsm_print_time (fp, ctrl->revoked_at);
|
||||
if (ctrl->revocation_reason)
|
||||
es_fprintf (fp, " (%s)", ctrl->revocation_reason);
|
||||
es_putc ('\n', fp);
|
||||
}
|
||||
if (!err)
|
||||
es_fprintf (fp, " [certificate is good]\n");
|
||||
else
|
||||
@ -1451,6 +1460,15 @@ list_cert_std (ctrl_t ctrl, ksba_cert_t cert, estream_t fp, int have_secret,
|
||||
|
||||
err = gpgsm_validate_chain (ctrl, cert,
|
||||
GNUPG_ISOTIME_NONE, NULL, 1, fp, 0, NULL);
|
||||
if (gpg_err_code (err) == GPG_ERR_CERT_REVOKED
|
||||
&& !check_isotime (ctrl->revoked_at))
|
||||
{
|
||||
es_fputs (" revoked: ", fp);
|
||||
gpgsm_print_time (fp, ctrl->revoked_at);
|
||||
if (ctrl->revocation_reason)
|
||||
es_fprintf (fp, " (%s)", ctrl->revocation_reason);
|
||||
es_putc ('\n', fp);
|
||||
}
|
||||
tmperr = ksba_cert_get_user_data (cert, "is_qualified",
|
||||
&buffer, sizeof (buffer), &buflen);
|
||||
if (!tmperr && buflen)
|
||||
|
Loading…
x
Reference in New Issue
Block a user