* 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.

* 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.
This commit is contained in:
Werner Koch 2004-04-05 17:25:21 +00:00
parent d3411b3277
commit da89d93c77
8 changed files with 159 additions and 22 deletions

View File

@ -1,3 +1,19 @@
2004-04-05 Werner Koch <wk@gnupg.org>
* 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 <wk@gnupg.org>
* 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 <wk@gnupg.org> 2004-03-24 Werner Koch <wk@gnupg.org>
* sign.c (gpgsm_sign): Include a short list of capabilities. * sign.c (gpgsm_sign): Include a short list of capabilities.

View File

@ -33,6 +33,8 @@
#include <assuan.h> #include <assuan.h>
#include "i18n.h" #include "i18n.h"
#include "keydb.h"
struct membuf { struct membuf {
size_t len; size_t len;
@ -52,6 +54,12 @@ struct inq_certificate_parm_s {
ksba_cert_t issuer_cert; ksba_cert_t issuer_cert;
}; };
struct isvalid_status_parm_s {
int seen;
unsigned char fpr[20];
};
struct lookup_parm_s { struct lookup_parm_s {
CTRL ctrl; CTRL ctrl;
ASSUAN_CONTEXT ctx; 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 /* Call the directory manager to check whether the certificate is valid
Returns 0 for valid or usually one of the errors: Returns 0 for valid or usually one of the errors:
@ -312,12 +356,14 @@ inq_certificate (void *opaque, const char *line)
request first. request first.
*/ */
int 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; int rc;
char *certid; char *certid;
char line[ASSUAN_LINELENGTH]; char line[ASSUAN_LINELENGTH];
struct inq_certificate_parm_s parm; struct inq_certificate_parm_s parm;
struct isvalid_status_parm_s stparm;
rc = start_dirmngr (); rc = start_dirmngr ();
if (rc) 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.cert = cert;
parm.issuer_cert = issuer_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 /* 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 option to dirmngr, so that no fallback CRL check is done after an
ocsp check. */ ocsp check. */
@ -358,10 +407,66 @@ gpgsm_dirmngr_isvalid (ksba_cert_t cert, ksba_cert_t issuer_cert, int use_ocsp)
xfree (certid); xfree (certid);
rc = assuan_transact (dirmngr_ctx, line, NULL, NULL, rc = assuan_transact (dirmngr_ctx, line, NULL, NULL,
inq_certificate, &parm, NULL, NULL); inq_certificate, &parm,
isvalid_status_cb, &stparm);
if (opt.verbose > 1) if (opt.verbose > 1)
log_info ("response of dirmngr: %s\n", rc? assuan_strerror (rc): "okay"); 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;
} }

View File

@ -480,7 +480,8 @@ is_cert_still_valid (ctrl_t ctrl, int lm, FILE *fp,
{ {
gpg_error_t err; 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) if (err)
{ {
/* Fixme: We should change the wording because we may /* 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 /* Validate a chain and optionally return the nearest expiration time
in R_EXPTIME. With LISTMODE set to 1 a special listmode is in R_EXPTIME. With LISTMODE set to 1 a special listmode is
activated where only information about the certificate is printed 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 int
gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, 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; int rc = 0, depth = 0, maxdepth;
char *issuer = NULL; 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. */ /* Check for revocations etc. */
rc = is_cert_still_valid (ctrl, lm, fp, if ((flags & 1))
subject_cert, subject_cert, rc = 0;
&any_revoked, &any_no_crl, else
&any_crl_too_old); rc = is_cert_still_valid (ctrl, lm, fp,
subject_cert, subject_cert,
&any_revoked, &any_no_crl,
&any_crl_too_old);
if (rc) if (rc)
goto leave; 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); sprintf (numbuf, "%d", rc);
gpgsm_status2 (ctrl, STATUS_ERROR, "certcert.issuer.keyusage", gpgsm_status2 (ctrl, STATUS_ERROR, "certcert.issuer.keyusage",
numbuf, NULL); numbuf, NULL);
rc = 0; goto leave;
} }
} }
/* Check for revocations etc. */ /* Check for revocations etc. */
rc = is_cert_still_valid (ctrl, lm, fp, if ((flags & 1))
subject_cert, issuer_cert, rc = 0;
&any_revoked, &any_no_crl, &any_crl_too_old); else
rc = is_cert_still_valid (ctrl, lm, fp,
subject_cert, issuer_cert,
&any_revoked, &any_no_crl, &any_crl_too_old);
if (rc) if (rc)
goto leave; goto leave;

View File

@ -130,7 +130,8 @@ cert_usage_p (ksba_cert_t cert, int mode)
{ {
if ((use & (KSBA_KEYUSAGE_KEY_CERT_SIGN))) if ((use & (KSBA_KEYUSAGE_KEY_CERT_SIGN)))
return 0; 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); 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) if (!rc)
rc = gpgsm_validate_chain (ctrl, cert, NULL, 0, NULL); rc = gpgsm_validate_chain (ctrl, cert, NULL, 0, NULL, 0);
if (!rc) if (!rc)
{ {
CERTLIST cl = xtrycalloc (1, sizeof *cl); CERTLIST cl = xtrycalloc (1, sizeof *cl);

View File

@ -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_is_root_cert (ksba_cert_t cert);
int gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, int gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert,
ksba_isotime_t r_exptime, 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); int gpgsm_basic_cert_check (ksba_cert_t cert);
/*-- certlist.c --*/ /*-- certlist.c --*/
@ -288,7 +289,8 @@ int gpgsm_agent_learn (void);
int gpgsm_agent_passwd (const char *hexkeygrip, const char *desc); int gpgsm_agent_passwd (const char *hexkeygrip, const char *desc);
/*-- call-dirmngr.c --*/ /*-- 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 use_ocsp);
int gpgsm_dirmngr_lookup (ctrl_t ctrl, STRLIST names, int gpgsm_dirmngr_lookup (ctrl_t ctrl, STRLIST names,
void (*cb)(void*, ksba_cert_t), void *cb_value); void (*cb)(void*, ksba_cert_t), void *cb_value);

View File

@ -182,7 +182,7 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity,
gpg_error_t valerr; gpg_error_t valerr;
if (ctrl->with_validation) if (ctrl->with_validation)
valerr = gpgsm_validate_chain (ctrl, cert, NULL, 1, NULL); valerr = gpgsm_validate_chain (ctrl, cert, NULL, 1, NULL, 0);
else else
valerr = 0; valerr = 0;
@ -483,7 +483,7 @@ list_cert_std (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int have_secret,
if (with_validation) if (with_validation)
{ {
err = gpgsm_validate_chain (ctrl, cert, NULL, 1, fp); err = gpgsm_validate_chain (ctrl, cert, NULL, 1, fp, 0);
if (!err) if (!err)
fprintf (fp, " [certificate is good]\n"); fprintf (fp, " [certificate is good]\n");
else else

View File

@ -378,7 +378,7 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist,
valid. */ valid. */
rc = gpgsm_cert_use_sign_p (cert); rc = gpgsm_cert_use_sign_p (cert);
if (!rc) if (!rc)
rc = gpgsm_validate_chain (ctrl, cert, NULL, 0, NULL); rc = gpgsm_validate_chain (ctrl, cert, NULL, 0, NULL, 0);
if (rc) if (rc)
goto leave; goto leave;

View File

@ -263,6 +263,9 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp)
err = 0; err = 0;
break; break;
} }
gpgsm_status (ctrl, STATUS_NEWSIG, NULL);
if (DBG_X509) if (DBG_X509)
{ {
log_debug ("signer %d - issuer: `%s'\n", 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) if (DBG_X509)
log_debug ("signature okay - checking certs\n"); 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) if (gpg_err_code (rc) == GPG_ERR_CERT_EXPIRED)
{ {
gpgsm_status (ctrl, STATUS_EXPKEYSIG, NULL); gpgsm_status (ctrl, STATUS_EXPKEYSIG, NULL);