More validation checks.

git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@19816 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
Love Hörnquist Åstrand
2007-01-10 21:45:56 +00:00
parent 5b9b07461e
commit 5bf1bd2a7d

View File

@@ -41,6 +41,15 @@ struct hx509_validate_ctx_data {
void *ctx;
};
struct cert_status {
unsigned int selfsigned:1;
unsigned int isca:1;
unsigned int haveIAN:1;
unsigned int haveSKI:1;
unsigned int haveAKI:1;
};
/*
*
*/
@@ -158,7 +167,9 @@ validate_print(hx509_validate_ctx ctx, int flags, const char *fmt, ...)
enum critical_flag { D_C = 0, S_C, S_N_C, M_C, M_N_C };
static int
check_Null(hx509_validate_ctx ctx, enum critical_flag cf, const Extension *e)
check_Null(hx509_validate_ctx ctx,
struct cert_status *status,
enum critical_flag cf, const Extension *e)
{
switch(cf) {
case D_C:
@@ -191,13 +202,53 @@ check_Null(hx509_validate_ctx ctx, enum critical_flag cf, const Extension *e)
static int
check_subjectKeyIdentifier(hx509_validate_ctx ctx,
struct cert_status *status,
enum critical_flag cf,
const Extension *e)
{
check_Null(ctx, cf, e);
SubjectKeyIdentifier si;
size_t size;
int ret;
status->haveSKI = 1;
check_Null(ctx, status, cf, e);
ret = decode_SubjectKeyIdentifier(e->extnValue.data,
e->extnValue.length,
&si, &size);
if (ret) {
validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
"Decoding SubjectKeyIdentifier failed: %d", ret);
return 1;
}
if (size != e->extnValue.length) {
validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
"Decoding SKI ahve extra bits on the end");
return 1;
}
if (si.length == 0)
validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
"SKI is too short (0 bytes)");
if (si.length > 20)
validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
"SKI is too long");
free_SubjectKeyIdentifier(&si);
return 0;
}
static int
check_authorityKeyIdentifier(hx509_validate_ctx ctx,
struct cert_status *status,
enum critical_flag cf,
const Extension *e)
{
status->haveAKI = 1;
check_Null(ctx, status, cf, e);
return 0;
}
static int
check_pkinit_san(hx509_validate_ctx ctx, heim_any *a)
{
@@ -209,12 +260,14 @@ check_pkinit_san(hx509_validate_ctx ctx, heim_any *a)
ret = decode_KRB5PrincipalName(a->data, a->length,
&kn, &size);
if (ret) {
printf("Decoding kerberos name in SAN failed: %d", ret);
validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
"Decoding kerberos name in SAN failed: %d", ret);
return 1;
}
if (size != a->length) {
printf("Decoding kerberos name have extra bits on the end");
validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
"Decoding kerberos name have extra bits on the end");
return 1;
}
@@ -249,6 +302,7 @@ struct {
static int
check_altName(hx509_validate_ctx ctx,
struct cert_status *status,
const char *name,
enum critical_flag cf,
const Extension *e)
@@ -257,7 +311,7 @@ check_altName(hx509_validate_ctx ctx,
size_t size;
int ret, i;
check_Null(ctx, cf, e);
check_Null(ctx, status, cf, e);
if (e->extnValue.length == 0) {
printf("%sAltName empty, not allowed", name);
@@ -343,23 +397,27 @@ check_altName(hx509_validate_ctx ctx,
static int
check_subjectAltName(hx509_validate_ctx ctx,
struct cert_status *status,
enum critical_flag cf,
const Extension *e)
{
return check_altName(ctx, "subject", cf, e);
return check_altName(ctx, status, "subject", cf, e);
}
static int
check_issuerAltName(hx509_validate_ctx ctx,
struct cert_status *status,
enum critical_flag cf,
const Extension *e)
{
return check_altName(ctx, "issuer", cf, e);
status->haveIAN = 1;
return check_altName(ctx, status, "issuer", cf, e);
}
static int
check_basicConstraints(hx509_validate_ctx ctx,
struct cert_status *status,
enum critical_flag cf,
const Extension *e)
{
@@ -367,7 +425,7 @@ check_basicConstraints(hx509_validate_ctx ctx,
size_t size;
int ret;
check_Null(ctx, cf, e);
check_Null(ctx, status, cf, e);
ret = decode_BasicConstraints(e->extnValue.data, e->extnValue.length,
&b, &size);
@@ -384,6 +442,14 @@ check_basicConstraints(hx509_validate_ctx ctx,
validate_print(ctx, HX509_VALIDATE_F_VERBOSE,
"\tpathLenConstraint: %d\n", *b.pathLenConstraint);
if (b.cA) {
if (*b.cA)
status->isca = 1;
else
validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
"cA is FALSE, not allowed to be\n");
}
return 0;
}
@@ -391,6 +457,7 @@ struct {
const char *name;
const heim_oid *(*oid)(void);
int (*func)(hx509_validate_ctx ctx,
struct cert_status *status,
enum critical_flag cf,
const Extension *);
enum critical_flag cf;
@@ -413,7 +480,7 @@ struct {
{ ext(cRLDistributionPoints, Null), S_N_C },
{ ext(certificatePolicies, Null) },
{ ext(policyMappings, Null), M_N_C },
{ ext(authorityKeyIdentifier, Null), M_N_C },
{ ext(authorityKeyIdentifier, authorityKeyIdentifier), M_N_C },
{ ext(policyConstraints, Null), D_C },
{ ext(extKeyUsage, Null), D_C },
{ ext(freshestCRL, Null), M_N_C },
@@ -459,31 +526,42 @@ hx509_validate_cert(hx509_context context,
{
Certificate *c = _hx509_get_cert(cert);
TBSCertificate *t = &c->tbsCertificate;
hx509_name name;
hx509_name issuer, subject;
char *str;
struct cert_status status;
memset(&status, 0, sizeof(status));
if (_hx509_cert_get_version(c) != 3)
validate_print(ctx, HX509_VALIDATE_F_VERBOSE,
"Not version 3 certificate\n");
if (t->version && *t->version < 2 && t->extensions)
if ((t->version || *t->version < 2) && t->extensions)
validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
"Not version 3 certificate with extensions\n");
_hx509_name_from_Name(&t->subject, &name);
hx509_name_to_string(name, &str);
hx509_name_free(&name);
if (_hx509_cert_get_version(c) >= 3 && t->extensions == NULL)
validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
"Version 3 certificate without extensions\n");
_hx509_name_from_Name(&t->subject, &subject);
hx509_name_to_string(subject, &str);
validate_print(ctx, HX509_VALIDATE_F_VERBOSE,
"subject name: %s\n", str);
free(str);
_hx509_name_from_Name(&t->issuer, &name);
hx509_name_to_string(name, &str);
hx509_name_free(&name);
_hx509_name_from_Name(&t->issuer, &issuer);
hx509_name_to_string(issuer, &str);
validate_print(ctx, HX509_VALIDATE_F_VERBOSE,
"issuer name: %s\n", str);
free(str);
if (hx509_name_cmp(subject, issuer) == 0)
status.selfsigned = 1;
hx509_name_free(&subject);
hx509_name_free(&issuer);
validate_print(ctx, HX509_VALIDATE_F_VERBOSE,
"Validity:\n");
@@ -528,11 +606,33 @@ hx509_validate_cert(hx509_context context,
"checking extention: %s\n",
check_extension[j].name);
(*check_extension[j].func)(ctx,
&status,
check_extension[j].cf,
&t->extensions->val[i]);
}
} else
validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "no extentions\n");
if (status.isca) {
if (!status.haveSKI)
validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
"CA certificate have no SubjectKeyIdentifier\n");
if (!status.haveSKI)
validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
"CA certificate have no SubjectKeyIdentifier\n");
} else {
if (!status.haveAKI)
validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
"Is not CA and doesn't have "
"AuthorityKeyIdentifier\n");
}
if (!status.haveSKI)
validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
"Doesn't have SubjectKeyIdentifier\n");
return 0;
}