aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sm/ChangeLog16
-rw-r--r--sm/call-dirmngr.c111
-rw-r--r--sm/certchain.c32
-rw-r--r--sm/certlist.c5
-rw-r--r--sm/gpgsm.h6
-rw-r--r--sm/keylist.c4
-rw-r--r--sm/sign.c2
-rw-r--r--sm/verify.c5
8 files changed, 159 insertions, 22 deletions
diff --git a/sm/ChangeLog b/sm/ChangeLog
index ecf1125c4..c1ca076dd 100644
--- a/sm/ChangeLog
+++ b/sm/ChangeLog
@@ -1,3 +1,19 @@
+2004-04-05 Werner Koch <[email protected]>
+
+ * verify.c (gpgsm_verify): Print STATUS_NEWSIG for each signature.
+
+ * certchain.c (gpgsm_validate_chain) <gpgsm_cert_use_cer_p>: Do
+ not just warn if a cert is not suitable; bail out immediately.
+
+2004-04-01 Werner Koch <[email protected]>
+
+ * call-dirmngr.c (isvalid_status_cb): New.
+ (unhexify_fpr): New. Taken from ../g10/call-agent.c
+ (gpgsm_dirmngr_isvalid): Add new arg CTRL, changed caller to pass
+ it thru. Detect need to check the respondert cert and do that.
+ * certchain.c (gpgsm_validate_chain): Add new arg FLAGS. Changed
+ all callers.
+
2004-03-24 Werner Koch <[email protected]>
* sign.c (gpgsm_sign): Include a short list of capabilities.
diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c
index 4f07fec24..0e8f67f28 100644
--- a/sm/call-dirmngr.c
+++ b/sm/call-dirmngr.c
@@ -33,6 +33,8 @@
#include <assuan.h>
#include "i18n.h"
+#include "keydb.h"
+
struct membuf {
size_t len;
@@ -52,6 +54,12 @@ struct inq_certificate_parm_s {
ksba_cert_t issuer_cert;
};
+struct isvalid_status_parm_s {
+ int seen;
+ unsigned char fpr[20];
+};
+
+
struct lookup_parm_s {
CTRL ctrl;
ASSUAN_CONTEXT ctx;
@@ -300,6 +308,42 @@ inq_certificate (void *opaque, const char *line)
}
+/* Take a 20 byte hexencoded string and put it into the the provided
+ 20 byte buffer FPR in binary format. */
+static int
+unhexify_fpr (const char *hexstr, unsigned char *fpr)
+{
+ const char *s;
+ int n;
+
+ for (s=hexstr, n=0; hexdigitp (s); s++, n++)
+ ;
+ if (*s || (n != 40))
+ return 0; /* no fingerprint (invalid or wrong length). */
+ n /= 2;
+ for (s=hexstr, n=0; *s; s += 2, n++)
+ fpr[n] = xtoi_2 (s);
+ return 1; /* okay */
+}
+
+
+static assuan_error_t
+isvalid_status_cb (void *opaque, const char *line)
+{
+ struct isvalid_status_parm_s *parm = opaque;
+
+ if (!strncmp (line, "ONLY_VALID_IF_CERT_VALID", 24)
+ && (line[24]==' ' || !line[24]))
+ {
+ parm->seen++;
+ if (!line[24] || !unhexify_fpr (line+25, parm->fpr))
+ parm->seen++; /* Bumb it to indicate an error. */
+ }
+ return 0;
+}
+
+
+
/* Call the directory manager to check whether the certificate is valid
Returns 0 for valid or usually one of the errors:
@@ -312,12 +356,14 @@ inq_certificate (void *opaque, const char *line)
request first.
*/
int
-gpgsm_dirmngr_isvalid (ksba_cert_t cert, ksba_cert_t issuer_cert, int use_ocsp)
+gpgsm_dirmngr_isvalid (ctrl_t ctrl,
+ ksba_cert_t cert, ksba_cert_t issuer_cert, int use_ocsp)
{
int rc;
char *certid;
char line[ASSUAN_LINELENGTH];
struct inq_certificate_parm_s parm;
+ struct isvalid_status_parm_s stparm;
rc = start_dirmngr ();
if (rc)
@@ -349,6 +395,9 @@ gpgsm_dirmngr_isvalid (ksba_cert_t cert, ksba_cert_t issuer_cert, int use_ocsp)
parm.cert = cert;
parm.issuer_cert = issuer_cert;
+ stparm.seen = 0;
+ memset (stparm.fpr, 0, 20);
+
/* FIXME: If --disable-crl-checks has been set, we should pass an
option to dirmngr, so that no fallback CRL check is done after an
ocsp check. */
@@ -358,10 +407,66 @@ gpgsm_dirmngr_isvalid (ksba_cert_t cert, ksba_cert_t issuer_cert, int use_ocsp)
xfree (certid);
rc = assuan_transact (dirmngr_ctx, line, NULL, NULL,
- inq_certificate, &parm, NULL, NULL);
+ inq_certificate, &parm,
+ isvalid_status_cb, &stparm);
if (opt.verbose > 1)
log_info ("response of dirmngr: %s\n", rc? assuan_strerror (rc): "okay");
- return map_assuan_err (rc);
+ rc = map_assuan_err (rc);
+
+ if (!rc && stparm.seen)
+ {
+ /* Need to also check the certificate validity. */
+ if (stparm.seen != 1)
+ {
+ log_error ("communication problem with dirmngr detected\n");
+ rc = gpg_error (GPG_ERR_INV_CRL);
+ }
+ else
+ {
+ KEYDB_HANDLE kh;
+ ksba_cert_t rspcert = NULL;
+
+ /* Fixme: First try to get the certificate from the
+ dirmngr's cache - it should be there. */
+ kh = keydb_new (0);
+ if (!kh)
+ rc = gpg_error (GPG_ERR_ENOMEM);
+ if (!rc)
+ rc = keydb_search_fpr (kh, stparm.fpr);
+ if (!rc)
+ rc = keydb_get_cert (kh, &rspcert);
+ if (rc)
+ {
+ log_error ("unable to find the certificate used "
+ "by the dirmngr: %s\n", gpg_strerror (rc));
+ rc = gpg_error (GPG_ERR_INV_CRL);
+ }
+ keydb_release (kh);
+
+ if (!rc)
+ {
+ /* fixme: We should refine the check to check for
+ certificates allowed for CRL/OCPS. */
+ rc = gpgsm_cert_use_verify_p (rspcert);
+ if (rc)
+ rc = gpg_error (GPG_ERR_INV_CRL);
+ else
+ {
+ /* Note, the flag = 1: This avoids checking this
+ certificate over and over again. */
+ rc = gpgsm_validate_chain (ctrl, rspcert, NULL, 0, NULL, 1);
+ if (rc)
+ {
+ log_error ("invalid certificate used for CRL/OCSP: %s\n",
+ gpg_strerror (rc));
+ rc = gpg_error (GPG_ERR_INV_CRL);
+ }
+ }
+ }
+ ksba_cert_release (rspcert);
+ }
+ }
+ return rc;
}
diff --git a/sm/certchain.c b/sm/certchain.c
index 5056139df..3bdba2a9d 100644
--- a/sm/certchain.c
+++ b/sm/certchain.c
@@ -480,7 +480,8 @@ is_cert_still_valid (ctrl_t ctrl, int lm, FILE *fp,
{
gpg_error_t err;
- err = gpgsm_dirmngr_isvalid (subject_cert, issuer_cert, ctrl->use_ocsp);
+ err = gpgsm_dirmngr_isvalid (ctrl,
+ subject_cert, issuer_cert, ctrl->use_ocsp);
if (err)
{
/* Fixme: We should change the wording because we may
@@ -522,10 +523,13 @@ is_cert_still_valid (ctrl_t ctrl, int lm, FILE *fp,
/* Validate a chain and optionally return the nearest expiration time
in R_EXPTIME. With LISTMODE set to 1 a special listmode is
activated where only information about the certificate is printed
- to FP and no outputis send to the usual log stream. */
+ to FP and no output is send to the usual log stream.
+
+ Defined flag bits: 0 - do not do any dirmngr isvalid checks.
+*/
int
gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime,
- int listmode, FILE *fp)
+ int listmode, FILE *fp, unsigned int flags)
{
int rc = 0, depth = 0, maxdepth;
char *issuer = NULL;
@@ -698,10 +702,13 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime,
}
/* Check for revocations etc. */
- rc = is_cert_still_valid (ctrl, lm, fp,
- subject_cert, subject_cert,
- &any_revoked, &any_no_crl,
- &any_crl_too_old);
+ if ((flags & 1))
+ rc = 0;
+ else
+ rc = is_cert_still_valid (ctrl, lm, fp,
+ subject_cert, subject_cert,
+ &any_revoked, &any_no_crl,
+ &any_crl_too_old);
if (rc)
goto leave;
@@ -818,14 +825,17 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime,
sprintf (numbuf, "%d", rc);
gpgsm_status2 (ctrl, STATUS_ERROR, "certcert.issuer.keyusage",
numbuf, NULL);
- rc = 0;
+ goto leave;
}
}
/* Check for revocations etc. */
- rc = is_cert_still_valid (ctrl, lm, fp,
- subject_cert, issuer_cert,
- &any_revoked, &any_no_crl, &any_crl_too_old);
+ if ((flags & 1))
+ rc = 0;
+ else
+ rc = is_cert_still_valid (ctrl, lm, fp,
+ subject_cert, issuer_cert,
+ &any_revoked, &any_no_crl, &any_crl_too_old);
if (rc)
goto leave;
diff --git a/sm/certlist.c b/sm/certlist.c
index 6e694b781..0394a584f 100644
--- a/sm/certlist.c
+++ b/sm/certlist.c
@@ -130,7 +130,8 @@ cert_usage_p (ksba_cert_t cert, int mode)
{
if ((use & (KSBA_KEYUSAGE_KEY_CERT_SIGN)))
return 0;
- log_info ( _("certificate should have not been used certification\n"));
+ log_info (_("certificate should have not "
+ "been used for certification\n"));
return gpg_error (GPG_ERR_WRONG_KEY_USAGE);
}
@@ -347,7 +348,7 @@ gpgsm_add_to_certlist (CTRL ctrl, const char *name, int secret,
}
}
if (!rc)
- rc = gpgsm_validate_chain (ctrl, cert, NULL, 0, NULL);
+ rc = gpgsm_validate_chain (ctrl, cert, NULL, 0, NULL, 0);
if (!rc)
{
CERTLIST cl = xtrycalloc (1, sizeof *cl);
diff --git a/sm/gpgsm.h b/sm/gpgsm.h
index 62bc05354..93487f002 100644
--- a/sm/gpgsm.h
+++ b/sm/gpgsm.h
@@ -222,7 +222,8 @@ int gpgsm_walk_cert_chain (ksba_cert_t start, ksba_cert_t *r_next);
int gpgsm_is_root_cert (ksba_cert_t cert);
int gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert,
ksba_isotime_t r_exptime,
- int listmode, FILE *listfp);
+ int listmode, FILE *listfp,
+ unsigned int flags);
int gpgsm_basic_cert_check (ksba_cert_t cert);
/*-- certlist.c --*/
@@ -288,7 +289,8 @@ int gpgsm_agent_learn (void);
int gpgsm_agent_passwd (const char *hexkeygrip, const char *desc);
/*-- call-dirmngr.c --*/
-int gpgsm_dirmngr_isvalid (ksba_cert_t cert, ksba_cert_t issuer_cert,
+int gpgsm_dirmngr_isvalid (ctrl_t ctrl,
+ ksba_cert_t cert, ksba_cert_t issuer_cert,
int use_ocsp);
int gpgsm_dirmngr_lookup (ctrl_t ctrl, STRLIST names,
void (*cb)(void*, ksba_cert_t), void *cb_value);
diff --git a/sm/keylist.c b/sm/keylist.c
index 80cc675db..4e6f28db8 100644
--- a/sm/keylist.c
+++ b/sm/keylist.c
@@ -182,7 +182,7 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity,
gpg_error_t valerr;
if (ctrl->with_validation)
- valerr = gpgsm_validate_chain (ctrl, cert, NULL, 1, NULL);
+ valerr = gpgsm_validate_chain (ctrl, cert, NULL, 1, NULL, 0);
else
valerr = 0;
@@ -483,7 +483,7 @@ list_cert_std (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int have_secret,
if (with_validation)
{
- err = gpgsm_validate_chain (ctrl, cert, NULL, 1, fp);
+ err = gpgsm_validate_chain (ctrl, cert, NULL, 1, fp, 0);
if (!err)
fprintf (fp, " [certificate is good]\n");
else
diff --git a/sm/sign.c b/sm/sign.c
index 3cc1444b7..473cf93a2 100644
--- a/sm/sign.c
+++ b/sm/sign.c
@@ -378,7 +378,7 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist,
valid. */
rc = gpgsm_cert_use_sign_p (cert);
if (!rc)
- rc = gpgsm_validate_chain (ctrl, cert, NULL, 0, NULL);
+ rc = gpgsm_validate_chain (ctrl, cert, NULL, 0, NULL, 0);
if (rc)
goto leave;
diff --git a/sm/verify.c b/sm/verify.c
index bd334908e..4b43ed064 100644
--- a/sm/verify.c
+++ b/sm/verify.c
@@ -263,6 +263,9 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp)
err = 0;
break;
}
+
+ gpgsm_status (ctrl, STATUS_NEWSIG, NULL);
+
if (DBG_X509)
{
log_debug ("signer %d - issuer: `%s'\n",
@@ -458,7 +461,7 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp)
if (DBG_X509)
log_debug ("signature okay - checking certs\n");
- rc = gpgsm_validate_chain (ctrl, cert, keyexptime, 0, NULL);
+ rc = gpgsm_validate_chain (ctrl, cert, keyexptime, 0, NULL, 0);
if (gpg_err_code (rc) == GPG_ERR_CERT_EXPIRED)
{
gpgsm_status (ctrl, STATUS_EXPKEYSIG, NULL);