summaryrefslogtreecommitdiff
path: root/crypto/x509v3
diff options
context:
space:
mode:
authorRichard Levitte <levitte@openssl.org>2004-11-29 11:28:08 +0000
committerRichard Levitte <levitte@openssl.org>2004-11-29 11:28:08 +0000
commit30b415b0765b465e71262d051b7b16b604a855be (patch)
treeea4d4e61013d94f9bcd05ee521efc71e67eda6b3 /crypto/x509v3
parent914c2a28c05797dc44fb3f498e6e12e5bc0db2b3 (diff)
downloadopenssl-new-30b415b0765b465e71262d051b7b16b604a855be.tar.gz
Make an explicit check during certificate validation to see that the
CA setting in each certificate on the chain is correct. As a side- effect always do the following basic checks on extensions, not just when there's an associated purpose to the check: - if there is an unhandled critical extension (unless the user has chosen to ignore this fault) - if the path length has been exceeded (if one is set at all) - that certain extensions fit the associated purpose (if one has been given)
Diffstat (limited to 'crypto/x509v3')
-rw-r--r--crypto/x509v3/v3_purp.c50
-rw-r--r--crypto/x509v3/x509v3.h1
2 files changed, 24 insertions, 27 deletions
diff --git a/crypto/x509v3/v3_purp.c b/crypto/x509v3/v3_purp.c
index 67596862ab..d37e79481a 100644
--- a/crypto/x509v3/v3_purp.c
+++ b/crypto/x509v3/v3_purp.c
@@ -63,7 +63,6 @@
static void x509v3_cache_extensions(X509 *x);
-static int ca_check(const X509 *x);
static int check_ssl_ca(const X509 *x);
static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, int ca);
static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x, int ca);
@@ -426,8 +425,14 @@ static void x509v3_cache_extensions(X509 *x)
#define ns_reject(x, usage) \
(((x)->ex_flags & EXFLAG_NSCERT) && !((x)->ex_nscert & (usage)))
-static int ca_check(const X509 *x)
+int X509_check_ca(X509 *x)
{
+ if(!(x->ex_flags & EXFLAG_SET)) {
+ CRYPTO_w_lock(CRYPTO_LOCK_X509);
+ x509v3_cache_extensions(x);
+ CRYPTO_w_unlock(CRYPTO_LOCK_X509);
+ }
+
/* keyUsage if present should allow cert signing */
if(ku_reject(x, KU_KEY_CERT_SIGN)) return 0;
if(x->ex_flags & EXFLAG_BCONS) {
@@ -435,10 +440,17 @@ static int ca_check(const X509 *x)
/* If basicConstraints says not a CA then say so */
else return 0;
} else {
+ /* we support V1 roots for... uh, I don't really know why. */
if((x->ex_flags & V1_ROOT) == V1_ROOT) return 3;
/* If key usage present it must have certSign so tolerate it */
else if (x->ex_flags & EXFLAG_KUSAGE) return 4;
- else return 2;
+ /* Older certificates could have Netscape-specific CA types */
+ else if (x->ex_flags & EXFLAG_NSCERT
+ && x->ex_nscert & NS_ANY_CA) return 5;
+ /* 2 means "I don't know...", which is legal for V1 and V2 */
+ else if (x->ex_flags & EXFLAG_V1) return 2;
+ /* can this still be regarded a CA certificate? I doubt it */
+ return 0;
}
}
@@ -446,14 +458,10 @@ static int ca_check(const X509 *x)
static int check_ssl_ca(const X509 *x)
{
int ca_ret;
- ca_ret = ca_check(x);
+ ca_ret = X509_check_ca(x);
if(!ca_ret) return 0;
/* check nsCertType if present */
- if(x->ex_flags & EXFLAG_NSCERT) {
- if(x->ex_nscert & NS_SSL_CA) return ca_ret;
- return 0;
- }
- if(ca_ret != 2) return ca_ret;
+ if(ca_ret != 5 || x->ex_nscert & NS_SSL_CA) return ca_ret;
else return 0;
}
@@ -498,14 +506,10 @@ static int purpose_smime(const X509 *x, int ca)
if(xku_reject(x,XKU_SMIME)) return 0;
if(ca) {
int ca_ret;
- ca_ret = ca_check(x);
+ ca_ret = X509_check_ca(x);
if(!ca_ret) return 0;
/* check nsCertType if present */
- if(x->ex_flags & EXFLAG_NSCERT) {
- if(x->ex_nscert & NS_SMIME_CA) return ca_ret;
- return 0;
- }
- if(ca_ret != 2) return ca_ret;
+ if(ca_ret != 5 || x->ex_nscert & NS_SMIME_CA) return ca_ret;
else return 0;
}
if(x->ex_flags & EXFLAG_NSCERT) {
@@ -539,7 +543,7 @@ static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, int ca)
{
if(ca) {
int ca_ret;
- if((ca_ret = ca_check(x)) != 2) return ca_ret;
+ if((ca_ret = X509_check_ca(x)) != 2) return ca_ret;
else return 0;
}
if(ku_reject(x, KU_CRL_SIGN)) return 0;
@@ -552,17 +556,9 @@ static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, int ca)
static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca)
{
- /* Must be a valid CA */
- if(ca) {
- int ca_ret;
- ca_ret = ca_check(x);
- if(ca_ret != 2) return ca_ret;
- if(x->ex_flags & EXFLAG_NSCERT) {
- if(x->ex_nscert & NS_ANY_CA) return ca_ret;
- return 0;
- }
- return 0;
- }
+ /* Must be a valid CA. Should we really support the "I don't know"
+ value (2)? */
+ if(ca) return X509_check_ca(x);
/* leaf certificate is checked in OCSP_verify() */
return 1;
}
diff --git a/crypto/x509v3/x509v3.h b/crypto/x509v3/x509v3.h
index 677a930f77..a6436289c0 100644
--- a/crypto/x509v3/x509v3.h
+++ b/crypto/x509v3/x509v3.h
@@ -578,6 +578,7 @@ int X509V3_EXT_print_fp(FILE *out, X509_EXTENSION *ext, int flag, int indent);
int X509V3_extensions_print(BIO *out, char *title, STACK_OF(X509_EXTENSION) *exts, unsigned long flag, int indent);
+int X509_check_ca(X509 *x);
int X509_check_purpose(X509 *x, int id, int ca);
int X509_supported_extension(X509_EXTENSION *ex);
int X509_PURPOSE_set(int *p, int purpose);