aboutsummaryrefslogtreecommitdiffstats
path: root/sm
diff options
context:
space:
mode:
Diffstat (limited to 'sm')
-rw-r--r--sm/Makefile.am4
-rw-r--r--sm/call-dirmngr.c55
-rw-r--r--sm/certchain.c54
-rw-r--r--sm/gpgsm.c4
-rw-r--r--sm/gpgsm.h12
-rw-r--r--sm/keydb.c2
-rw-r--r--sm/keylist.c18
-rw-r--r--sm/verify.c17
8 files changed, 140 insertions, 26 deletions
diff --git a/sm/Makefile.am b/sm/Makefile.am
index c676adac9..cfcc36c63 100644
--- a/sm/Makefile.am
+++ b/sm/Makefile.am
@@ -70,8 +70,8 @@ common_libs = ../kbx/libkeybox509.a $(libcommonpth)
gpgsm_LDADD = $(common_libs) ../common/libgpgrl.a \
$(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(LIBASSUAN_LIBS) \
$(NPTH_LIBS) $(GPG_ERROR_LIBS) $(LIBREADLINE) $(LIBINTL) \
- $(LIBICONV) $(resource_objs) $(extra_sys_libs) $(NETLIBS)
-gpgsm_LDFLAGS = $(extra_bin_ldflags)
+ $(LIBICONV) $(resource_objs) $(NETLIBS)
+gpgsm_LDFLAGS =
module_tests =
diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c
index 5dd8a3938..cc958ccf8 100644
--- a/sm/call-dirmngr.c
+++ b/sm/call-dirmngr.c
@@ -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))
{
}
@@ -510,12 +525,17 @@ isvalid_status_cb (void *opaque, const char *line)
Values for USE_OCSP:
0 = Do CRL check.
- 1 = Do an OCSP check but fallback to CRL unless CRLS are disabled.
- 2 = Do only an OCSP check using only the default responder.
+ 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.
*/
-int
+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. */
@@ -563,9 +590,8 @@ gpgsm_dirmngr_isvalid (ctrl_t ctrl,
NULL, NULL, NULL, NULL, NULL, NULL);
did_options = 1;
}
- snprintf (line, DIM(line), "ISVALID%s%s %s%s%s",
- use_ocsp == 2 || opt.no_crl_check ? " --only-ocsp":"",
- use_ocsp == 2? " --force-default-responder":"",
+ snprintf (line, DIM(line), "ISVALID%s %s%s%s",
+ (use_ocsp == 2 || opt.no_crl_check) ? " --only-ocsp":"",
certid,
use_ocsp? " ":"",
use_ocsp? certfpr:"");
@@ -578,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. */
@@ -635,7 +674,9 @@ gpgsm_dirmngr_isvalid (ctrl_t ctrl,
ksba_cert_release (rspcert);
}
}
+
release_dirmngr (ctrl);
+ xfree (stparm.revocation_reason);
return rc;
}
diff --git a/sm/certchain.c b/sm/certchain.c
index 4050680e8..cbb6e1127 100644
--- a/sm/certchain.c
+++ b/sm/certchain.c
@@ -350,7 +350,7 @@ check_cert_policy (ksba_cert_t cert, int listmode, estream_t fplist)
/* With no critical policies this is only a warning */
if (!any_critical)
{
- if (!opt.quiet)
+ if (opt.verbose)
do_list (0, listmode, fplist,
_("Note: non-critical certificate policy not allowed"));
return 0;
@@ -380,7 +380,8 @@ check_cert_policy (ksba_cert_t cert, int listmode, estream_t fplist)
/* With no critical policies this is only a warning */
if (!any_critical)
{
- do_list (0, listmode, fplist,
+ if (opt.verbose)
+ do_list (0, listmode, fplist,
_("Note: non-critical certificate policy not allowed"));
return 0;
}
@@ -1187,11 +1188,13 @@ gpgsm_is_root_cert (ksba_cert_t cert)
/* This is a helper for gpgsm_validate_chain. */
static gpg_error_t
-is_cert_still_valid (ctrl_t ctrl, int force_ocsp, int lm, estream_t fp,
+is_cert_still_valid (ctrl_t ctrl, int chain_model, int lm, estream_t fp,
ksba_cert_t subject_cert, ksba_cert_t issuer_cert,
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))
{
@@ -1201,7 +1204,7 @@ is_cert_still_valid (ctrl_t ctrl, int force_ocsp, int lm, estream_t fp,
}
- if (!(force_ocsp || ctrl->use_ocsp)
+ if (!(chain_model || ctrl->use_ocsp)
&& !opt.enable_issuer_based_crl_check)
{
err = ksba_cert_get_crl_dist_point (subject_cert, 0, NULL, NULL, NULL);
@@ -1220,7 +1223,20 @@ is_cert_still_valid (ctrl_t ctrl, int force_ocsp, int lm, estream_t fp,
err = gpgsm_dirmngr_isvalid (ctrl,
subject_cert, issuer_cert,
- force_ocsp? 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)
@@ -1230,7 +1246,22 @@ is_cert_still_valid (ctrl_t ctrl, int force_ocsp, int lm, estream_t fp,
switch (gpg_err_code (err))
{
case GPG_ERR_CERT_REVOKED:
- do_list (1, lm, fp, _("certificate has been revoked"));
+ if (!check_isotime (ctrl->revoked_at))
+ {
+ char *tmpstr;
+ const unsigned char *t = ctrl->revoked_at;
+
+ tmpstr = xtryasprintf ("%.4s-%.2s-%.2s %.2s:%.2s:%s (%s)",
+ t, t+4, t+6, t+9, t+11, t+13,
+ ctrl->revocation_reason?
+ ctrl->revocation_reason : "");
+
+ do_list (1, lm, fp, "%s: %s",
+ _("certificate has been revoked"), tmpstr);
+ xfree (tmpstr);
+ }
+ else
+ do_list (1, lm, fp, _("certificate has been revoked"));
*any_revoked = 1;
/* Store that in the keybox so that key listings are able to
return the revoked flag. We don't care about error,
@@ -2158,11 +2189,14 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t checktime,
{
*retflags |= VALIDATE_FLAG_STEED;
}
- else if (gpg_err_code (rc) == GPG_ERR_CERT_EXPIRED
- && !(flags & VALIDATE_FLAG_CHAIN_MODEL)
- && (rootca_flags.valid && rootca_flags.chain_model))
+ else if (!(flags & VALIDATE_FLAG_CHAIN_MODEL)
+ && (rootca_flags.valid && rootca_flags.chain_model))
{
- do_list (0, listmode, listfp, _("switching to chain model"));
+ /* The root CA indicated that the chain model is to be used but
+ * we have not yet used it. Thus do the validation again using
+ * the chain model. */
+ if (opt.verbose)
+ do_list (0, listmode, listfp, _("switching to chain model"));
rc = do_validate_chain (ctrl, cert, checktime,
r_exptime, listmode, listfp,
(flags |= VALIDATE_FLAG_CHAIN_MODEL),
diff --git a/sm/gpgsm.c b/sm/gpgsm.c
index 3247a0f2e..f8b3856c2 100644
--- a/sm/gpgsm.c
+++ b/sm/gpgsm.c
@@ -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;
}
diff --git a/sm/gpgsm.h b/sm/gpgsm.h
index 9fbb53a29..ced2d679f 100644
--- a/sm/gpgsm.h
+++ b/sm/gpgsm.h
@@ -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;
};
@@ -494,9 +498,11 @@ gpg_error_t gpgsm_agent_export_key (ctrl_t ctrl, const char *keygrip,
size_t *r_resultlen);
/*-- call-dirmngr.c --*/
-int gpgsm_dirmngr_isvalid (ctrl_t ctrl,
- ksba_cert_t cert, ksba_cert_t issuer_cert,
- int use_ocsp);
+gpg_error_t gpgsm_dirmngr_isvalid (ctrl_t ctrl,
+ ksba_cert_t cert, ksba_cert_t issuer_cert,
+ 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);
diff --git a/sm/keydb.c b/sm/keydb.c
index 5b28df7ab..fbe28f2b9 100644
--- a/sm/keydb.c
+++ b/sm/keydb.c
@@ -2027,7 +2027,7 @@ keydb_set_cert_flags (ctrl_t ctrl, ksba_cert_t cert, int ephemeral,
err = keydb_search_fpr (ctrl, kh, fpr);
if (err)
{
- if (gpg_err_code (err) != gpg_error (GPG_ERR_NOT_FOUND))
+ if (gpg_err_code (err) != GPG_ERR_NOT_FOUND)
log_error (_("problem re-searching certificate: %s\n"),
gpg_strerror (err));
keydb_release (kh);
diff --git a/sm/keylist.c b/sm/keylist.c
index fb2c3bad5..fabd82224 100644
--- a/sm/keylist.c
+++ b/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)
diff --git a/sm/verify.c b/sm/verify.c
index 2e40c021f..9f1216f83 100644
--- a/sm/verify.c
+++ b/sm/verify.c
@@ -299,6 +299,7 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, estream_t out_fp)
unsigned int nbits;
int pkalgo;
char *pkalgostr = NULL;
+ char *pkcurve = NULL;
char *pkfpr = NULL;
unsigned int pkalgoflags, verifyflags;
@@ -457,7 +458,7 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, estream_t out_fp)
pkfpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
pkalgostr = gpgsm_pubkey_algo_string (cert, NULL);
- pkalgo = gpgsm_get_key_algo_info (cert, &nbits);
+ pkalgo = gpgsm_get_key_algo_info2 (cert, &nbits, &pkcurve);
/* Remap the ECC algo to the algo we use. Note that EdDSA has
* already been mapped. */
if (pkalgo == GCRY_PK_ECC)
@@ -513,9 +514,19 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, estream_t out_fp)
goto next_signer;
}
+ /* Print compliance warning for the key. */
+ if (!opt.quiet
+ && !gnupg_pk_is_compliant (opt.compliance, pkalgo, pkalgoflags,
+ NULL, nbits, pkcurve))
+ {
+ log_info (_("WARNING: This key is not suitable for signing"
+ " in %s mode\n"),
+ gnupg_compliance_option_string (opt.compliance));
+ }
+
/* Check compliance with CO_DE_VS. */
if (gnupg_pk_is_compliant (CO_DE_VS, pkalgo, pkalgoflags,
- NULL, nbits, NULL)
+ NULL, nbits, pkcurve)
&& gnupg_gcrypt_is_compliant (CO_DE_VS)
&& gnupg_digest_is_compliant (CO_DE_VS, sigval_hash_algo))
gpgsm_status (ctrl, STATUS_VERIFICATION_COMPLIANCE_MODE,
@@ -528,7 +539,6 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, estream_t out_fp)
gpgsm_errors_seen = 1;
}
-
/* Now we can check the signature. */
if (msgdigest)
{ /* Signed attributes are available. */
@@ -715,6 +725,7 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, estream_t out_fp)
gcry_sexp_release (sigval);
xfree (msgdigest);
xfree (pkalgostr);
+ xfree (pkcurve);
xfree (pkfpr);
ksba_cert_release (cert);
cert = NULL;