1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-22 10:19:57 +01:00

* certpath.c (unknown_criticals): New.

(allowed_ca): New.
(gpgsm_validate_path): Check validity, CA attribute, path length
and unknown critical extensions.
This commit is contained in:
Werner Koch 2002-01-22 13:32:48 +00:00
parent 1146232890
commit 4f39f92eff
4 changed files with 239 additions and 18 deletions

View File

@ -77,6 +77,10 @@ enum {
GNUPG_Line_Too_Long = 48, GNUPG_Line_Too_Long = 48,
GNUPG_Not_Trusted = 49, GNUPG_Not_Trusted = 49,
GNUPG_Canceled = 50, GNUPG_Canceled = 50,
GNUPG_Bad_CA_Certificate = 51,
GNUPG_Certificate_Expired = 52,
GNUPG_Certificate_Too_Young = 53,
GNUPG_Unsupported_Certificate = 54,
}; };
/* Status codes - fixme: should go into another file */ /* Status codes - fixme: should go into another file */

View File

@ -1,3 +1,10 @@
2002-01-22 Werner Koch <wk@gnupg.org>
* certpath.c (unknown_criticals): New.
(allowed_ca): New.
(gpgsm_validate_path): Check validity, CA attribute, path length
and unknown critical extensions.
2002-01-21 Werner Koch <wk@gnupg.org> 2002-01-21 Werner Koch <wk@gnupg.org>
* gpgsm.c: Add option --enable-crl-checks. * gpgsm.c: Add option --enable-crl-checks.

View File

@ -34,14 +34,64 @@
#include "keydb.h" #include "keydb.h"
#include "i18n.h" #include "i18n.h"
static int
unknown_criticals (KsbaCert cert)
{
static const char *known[] = {
"2.5.29.19", /* basic Constraints */
NULL
};
int rc = 0, i, idx, crit;
const char *oid;
KsbaError err;
for (idx=0; !(err=ksba_cert_get_extension (cert, idx,
&oid, &crit, NULL, NULL));idx++)
{
if (!crit)
continue;
for (i=0; known[i] && strcmp (known[i],oid); i++)
;
if (!known[i])
{
log_error (_("critical certificate extension %s is not supported\n"),
oid);
rc = GNUPG_Unsupported_Certificate;
}
}
if (err && err != -1)
rc = map_ksba_err (err);
return rc;
}
static int
allowed_ca (KsbaCert cert, int *pathlen)
{
KsbaError err;
int flag;
err = ksba_cert_is_ca (cert, &flag, pathlen);
if (err)
return map_ksba_err (err);
if (!flag)
{
log_error (_("issuer certificate is not marked as a CA\n"));
return GNUPG_Bad_CA_Certificate;
}
return 0;
}
int int
gpgsm_validate_path (KsbaCert cert) gpgsm_validate_path (KsbaCert cert)
{ {
int rc = 0, depth = 0; int rc = 0, depth = 0, maxdepth;
char *issuer = NULL; char *issuer = NULL;
char *subject = NULL; char *subject = NULL;
KEYDB_HANDLE kh = keydb_new (0); KEYDB_HANDLE kh = keydb_new (0);
KsbaCert subject_cert = NULL, issuer_cert = NULL; KsbaCert subject_cert = NULL, issuer_cert = NULL;
time_t current_time = time (NULL);
if (!kh) if (!kh)
{ {
@ -54,8 +104,7 @@ gpgsm_validate_path (KsbaCert cert)
gpgsm_dump_cert ("subject", cert); gpgsm_dump_cert ("subject", cert);
subject_cert = cert; subject_cert = cert;
maxdepth = 50;
/* FIXME: We need to check that none of the certs didexpire */
for (;;) for (;;)
{ {
@ -66,12 +115,45 @@ gpgsm_validate_path (KsbaCert cert)
if (!issuer) if (!issuer)
{ {
if (DBG_X509) log_error ("no issuer found in certificate\n");
log_debug ("ERROR: issuer missing\n");
rc = GNUPG_Bad_Certificate; rc = GNUPG_Bad_Certificate;
goto leave; goto leave;
} }
{
time_t not_before, not_after;
not_before = ksba_cert_get_validity (subject_cert, 0);
not_after = ksba_cert_get_validity (subject_cert, 1);
if (not_before == (time_t)(-1) || not_after == (time_t)(-1))
{
log_error ("certificate with invalid validity\n");
rc = GNUPG_Bad_Certificate;
goto leave;
}
if (current_time < not_before)
{
log_error ("certificate to young; valid from ");
gpgsm_dump_time (not_before);
log_printf ("\n");
rc = GNUPG_Certificate_Too_Young;
goto leave;
}
if (current_time > not_after)
{
log_error ("certificate has expired at ");
gpgsm_dump_time (not_after);
log_printf ("\n");
rc = GNUPG_Certificate_Expired;
goto leave;
}
}
rc = unknown_criticals (subject_cert);
if (rc)
goto leave;
if (!opt.no_crl_check) if (!opt.no_crl_check)
{ {
rc = gpgsm_dirmngr_isvalid (subject_cert); rc = gpgsm_dirmngr_isvalid (subject_cert);
@ -107,6 +189,10 @@ gpgsm_validate_path (KsbaCert cert)
rc = depth? GNUPG_Bad_Certificate_Path : GNUPG_Bad_Certificate; rc = depth? GNUPG_Bad_Certificate_Path : GNUPG_Bad_Certificate;
goto leave; goto leave;
} }
rc = allowed_ca (subject_cert, NULL);
if (rc)
goto leave;
rc = gpgsm_agent_istrusted (subject_cert); rc = gpgsm_agent_istrusted (subject_cert);
if (!rc) if (!rc)
; ;
@ -118,7 +204,7 @@ gpgsm_validate_path (KsbaCert cert)
log_info (_("fingerprint=%s\n"), fpr? fpr : "?"); log_info (_("fingerprint=%s\n"), fpr? fpr : "?");
xfree (fpr); xfree (fpr);
/* fixme: print a note while we have not yet the code to /* fixme: print a note while we have not yet the code to
ask whether the cert should be netered into the trust ask whether the cert should be entered into the trust
list */ list */
gpgsm_dump_cert ("issuer", subject_cert); gpgsm_dump_cert ("issuer", subject_cert);
log_info ("after checking the fingerprint, you may want " log_info ("after checking the fingerprint, you may want "
@ -134,7 +220,12 @@ gpgsm_validate_path (KsbaCert cert)
} }
depth++; depth++;
/* fixme: check against a maximum path length */ if (depth > maxdepth)
{
log_error (_("certificate path too long\n"));
rc = GNUPG_Bad_Certificate_Path;
goto leave;
}
/* find the next cert up the tree */ /* find the next cert up the tree */
keydb_search_reset (kh); keydb_search_reset (kh);
@ -167,7 +258,21 @@ gpgsm_validate_path (KsbaCert cert)
rc = GNUPG_Bad_Certificate_Path; rc = GNUPG_Bad_Certificate_Path;
goto leave; goto leave;
} }
if (opt.verbose)
{
int pathlen;
rc = allowed_ca (issuer_cert, &pathlen);
if (rc)
goto leave;
if (pathlen >= 0 && (depth - 1) > pathlen)
{
log_error (_("certificate path longer than allowed by CA (%d)\n"),
pathlen);
rc = GNUPG_Bad_Certificate_Path;
goto leave;
}
}
log_info ("certificate is good\n"); log_info ("certificate is good\n");
keydb_search_reset (kh); keydb_search_reset (kh);

View File

@ -34,14 +34,64 @@
#include "keydb.h" #include "keydb.h"
#include "i18n.h" #include "i18n.h"
static int
unknown_criticals (KsbaCert cert)
{
static const char *known[] = {
"2.5.29.19", /* basic Constraints */
NULL
};
int rc = 0, i, idx, crit;
const char *oid;
KsbaError err;
for (idx=0; !(err=ksba_cert_get_extension (cert, idx,
&oid, &crit, NULL, NULL));idx++)
{
if (!crit)
continue;
for (i=0; known[i] && strcmp (known[i],oid); i++)
;
if (!known[i])
{
log_error (_("critical certificate extension %s is not supported\n"),
oid);
rc = GNUPG_Unsupported_Certificate;
}
}
if (err && err != -1)
rc = map_ksba_err (err);
return rc;
}
static int
allowed_ca (KsbaCert cert, int *pathlen)
{
KsbaError err;
int flag;
err = ksba_cert_is_ca (cert, &flag, pathlen);
if (err)
return map_ksba_err (err);
if (!flag)
{
log_error (_("issuer certificate is not marked as a CA\n"));
return GNUPG_Bad_CA_Certificate;
}
return 0;
}
int int
gpgsm_validate_path (KsbaCert cert) gpgsm_validate_path (KsbaCert cert)
{ {
int rc = 0, depth = 0; int rc = 0, depth = 0, maxdepth;
char *issuer = NULL; char *issuer = NULL;
char *subject = NULL; char *subject = NULL;
KEYDB_HANDLE kh = keydb_new (0); KEYDB_HANDLE kh = keydb_new (0);
KsbaCert subject_cert = NULL, issuer_cert = NULL; KsbaCert subject_cert = NULL, issuer_cert = NULL;
time_t current_time = time (NULL);
if (!kh) if (!kh)
{ {
@ -54,8 +104,7 @@ gpgsm_validate_path (KsbaCert cert)
gpgsm_dump_cert ("subject", cert); gpgsm_dump_cert ("subject", cert);
subject_cert = cert; subject_cert = cert;
maxdepth = 50;
/* FIXME: We need to check that none of the certs didexpire */
for (;;) for (;;)
{ {
@ -66,12 +115,45 @@ gpgsm_validate_path (KsbaCert cert)
if (!issuer) if (!issuer)
{ {
if (DBG_X509) log_error ("no issuer found in certificate\n");
log_debug ("ERROR: issuer missing\n");
rc = GNUPG_Bad_Certificate; rc = GNUPG_Bad_Certificate;
goto leave; goto leave;
} }
{
time_t not_before, not_after;
not_before = ksba_cert_get_validity (subject_cert, 0);
not_after = ksba_cert_get_validity (subject_cert, 1);
if (not_before == (time_t)(-1) || not_after == (time_t)(-1))
{
log_error ("certificate with invalid validity\n");
rc = GNUPG_Bad_Certificate;
goto leave;
}
if (current_time < not_before)
{
log_error ("certificate to young; valid from ");
gpgsm_dump_time (not_before);
log_printf ("\n");
rc = GNUPG_Certificate_Too_Young;
goto leave;
}
if (current_time > not_after)
{
log_error ("certificate has expired at ");
gpgsm_dump_time (not_after);
log_printf ("\n");
rc = GNUPG_Certificate_Expired;
goto leave;
}
}
rc = unknown_criticals (subject_cert);
if (rc)
goto leave;
if (!opt.no_crl_check) if (!opt.no_crl_check)
{ {
rc = gpgsm_dirmngr_isvalid (subject_cert); rc = gpgsm_dirmngr_isvalid (subject_cert);
@ -107,6 +189,10 @@ gpgsm_validate_path (KsbaCert cert)
rc = depth? GNUPG_Bad_Certificate_Path : GNUPG_Bad_Certificate; rc = depth? GNUPG_Bad_Certificate_Path : GNUPG_Bad_Certificate;
goto leave; goto leave;
} }
rc = allowed_ca (subject_cert, NULL);
if (rc)
goto leave;
rc = gpgsm_agent_istrusted (subject_cert); rc = gpgsm_agent_istrusted (subject_cert);
if (!rc) if (!rc)
; ;
@ -118,7 +204,7 @@ gpgsm_validate_path (KsbaCert cert)
log_info (_("fingerprint=%s\n"), fpr? fpr : "?"); log_info (_("fingerprint=%s\n"), fpr? fpr : "?");
xfree (fpr); xfree (fpr);
/* fixme: print a note while we have not yet the code to /* fixme: print a note while we have not yet the code to
ask whether the cert should be netered into the trust ask whether the cert should be entered into the trust
list */ list */
gpgsm_dump_cert ("issuer", subject_cert); gpgsm_dump_cert ("issuer", subject_cert);
log_info ("after checking the fingerprint, you may want " log_info ("after checking the fingerprint, you may want "
@ -134,7 +220,12 @@ gpgsm_validate_path (KsbaCert cert)
} }
depth++; depth++;
/* fixme: check against a maximum path length */ if (depth > maxdepth)
{
log_error (_("certificate path too long\n"));
rc = GNUPG_Bad_Certificate_Path;
goto leave;
}
/* find the next cert up the tree */ /* find the next cert up the tree */
keydb_search_reset (kh); keydb_search_reset (kh);
@ -167,7 +258,21 @@ gpgsm_validate_path (KsbaCert cert)
rc = GNUPG_Bad_Certificate_Path; rc = GNUPG_Bad_Certificate_Path;
goto leave; goto leave;
} }
if (opt.verbose)
{
int pathlen;
rc = allowed_ca (issuer_cert, &pathlen);
if (rc)
goto leave;
if (pathlen >= 0 && (depth - 1) > pathlen)
{
log_error (_("certificate path longer than allowed by CA (%d)\n"),
pathlen);
rc = GNUPG_Bad_Certificate_Path;
goto leave;
}
}
log_info ("certificate is good\n"); log_info ("certificate is good\n");
keydb_search_reset (kh); keydb_search_reset (kh);