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:
parent
1146232890
commit
4f39f92eff
@ -77,6 +77,10 @@ enum {
|
||||
GNUPG_Line_Too_Long = 48,
|
||||
GNUPG_Not_Trusted = 49,
|
||||
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 */
|
||||
|
@ -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>
|
||||
|
||||
* gpgsm.c: Add option --enable-crl-checks.
|
||||
|
121
sm/certchain.c
121
sm/certchain.c
@ -34,14 +34,64 @@
|
||||
#include "keydb.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
|
||||
gpgsm_validate_path (KsbaCert cert)
|
||||
{
|
||||
int rc = 0, depth = 0;
|
||||
int rc = 0, depth = 0, maxdepth;
|
||||
char *issuer = NULL;
|
||||
char *subject = NULL;
|
||||
KEYDB_HANDLE kh = keydb_new (0);
|
||||
KsbaCert subject_cert = NULL, issuer_cert = NULL;
|
||||
time_t current_time = time (NULL);
|
||||
|
||||
if (!kh)
|
||||
{
|
||||
@ -54,8 +104,7 @@ gpgsm_validate_path (KsbaCert cert)
|
||||
gpgsm_dump_cert ("subject", cert);
|
||||
|
||||
subject_cert = cert;
|
||||
|
||||
/* FIXME: We need to check that none of the certs didexpire */
|
||||
maxdepth = 50;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
@ -66,12 +115,45 @@ gpgsm_validate_path (KsbaCert cert)
|
||||
|
||||
if (!issuer)
|
||||
{
|
||||
if (DBG_X509)
|
||||
log_debug ("ERROR: issuer missing\n");
|
||||
log_error ("no issuer found in certificate\n");
|
||||
rc = GNUPG_Bad_Certificate;
|
||||
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)
|
||||
{
|
||||
rc = gpgsm_dirmngr_isvalid (subject_cert);
|
||||
@ -107,6 +189,10 @@ gpgsm_validate_path (KsbaCert cert)
|
||||
rc = depth? GNUPG_Bad_Certificate_Path : GNUPG_Bad_Certificate;
|
||||
goto leave;
|
||||
}
|
||||
rc = allowed_ca (subject_cert, NULL);
|
||||
if (rc)
|
||||
goto leave;
|
||||
|
||||
rc = gpgsm_agent_istrusted (subject_cert);
|
||||
if (!rc)
|
||||
;
|
||||
@ -118,7 +204,7 @@ gpgsm_validate_path (KsbaCert cert)
|
||||
log_info (_("fingerprint=%s\n"), fpr? fpr : "?");
|
||||
xfree (fpr);
|
||||
/* 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 */
|
||||
gpgsm_dump_cert ("issuer", subject_cert);
|
||||
log_info ("after checking the fingerprint, you may want "
|
||||
@ -134,7 +220,12 @@ gpgsm_validate_path (KsbaCert cert)
|
||||
}
|
||||
|
||||
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 */
|
||||
keydb_search_reset (kh);
|
||||
@ -167,7 +258,21 @@ gpgsm_validate_path (KsbaCert cert)
|
||||
rc = GNUPG_Bad_Certificate_Path;
|
||||
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");
|
||||
|
||||
keydb_search_reset (kh);
|
||||
|
121
sm/certpath.c
121
sm/certpath.c
@ -34,14 +34,64 @@
|
||||
#include "keydb.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
|
||||
gpgsm_validate_path (KsbaCert cert)
|
||||
{
|
||||
int rc = 0, depth = 0;
|
||||
int rc = 0, depth = 0, maxdepth;
|
||||
char *issuer = NULL;
|
||||
char *subject = NULL;
|
||||
KEYDB_HANDLE kh = keydb_new (0);
|
||||
KsbaCert subject_cert = NULL, issuer_cert = NULL;
|
||||
time_t current_time = time (NULL);
|
||||
|
||||
if (!kh)
|
||||
{
|
||||
@ -54,8 +104,7 @@ gpgsm_validate_path (KsbaCert cert)
|
||||
gpgsm_dump_cert ("subject", cert);
|
||||
|
||||
subject_cert = cert;
|
||||
|
||||
/* FIXME: We need to check that none of the certs didexpire */
|
||||
maxdepth = 50;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
@ -66,12 +115,45 @@ gpgsm_validate_path (KsbaCert cert)
|
||||
|
||||
if (!issuer)
|
||||
{
|
||||
if (DBG_X509)
|
||||
log_debug ("ERROR: issuer missing\n");
|
||||
log_error ("no issuer found in certificate\n");
|
||||
rc = GNUPG_Bad_Certificate;
|
||||
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)
|
||||
{
|
||||
rc = gpgsm_dirmngr_isvalid (subject_cert);
|
||||
@ -107,6 +189,10 @@ gpgsm_validate_path (KsbaCert cert)
|
||||
rc = depth? GNUPG_Bad_Certificate_Path : GNUPG_Bad_Certificate;
|
||||
goto leave;
|
||||
}
|
||||
rc = allowed_ca (subject_cert, NULL);
|
||||
if (rc)
|
||||
goto leave;
|
||||
|
||||
rc = gpgsm_agent_istrusted (subject_cert);
|
||||
if (!rc)
|
||||
;
|
||||
@ -118,7 +204,7 @@ gpgsm_validate_path (KsbaCert cert)
|
||||
log_info (_("fingerprint=%s\n"), fpr? fpr : "?");
|
||||
xfree (fpr);
|
||||
/* 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 */
|
||||
gpgsm_dump_cert ("issuer", subject_cert);
|
||||
log_info ("after checking the fingerprint, you may want "
|
||||
@ -134,7 +220,12 @@ gpgsm_validate_path (KsbaCert cert)
|
||||
}
|
||||
|
||||
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 */
|
||||
keydb_search_reset (kh);
|
||||
@ -167,7 +258,21 @@ gpgsm_validate_path (KsbaCert cert)
|
||||
rc = GNUPG_Bad_Certificate_Path;
|
||||
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");
|
||||
|
||||
keydb_search_reset (kh);
|
||||
|
Loading…
x
Reference in New Issue
Block a user