NID_key_usage, /* 83 */
NID_subject_alt_name, /* 85 */
NID_basic_constraints, /* 87 */
- NID_ext_key_usage /* 126 */
+ NID_ext_key_usage, /* 126 */
+ NID_proxyCertInfo /* 661 */
};
int ex_nid;
static void x509v3_cache_extensions(X509 *x)
{
BASIC_CONSTRAINTS *bs;
+ PROXY_CERT_INFO_EXTENSION *pci;
ASN1_BIT_STRING *usage;
ASN1_BIT_STRING *ns;
EXTENDED_KEY_USAGE *extusage;
BASIC_CONSTRAINTS_free(bs);
x->ex_flags |= EXFLAG_BCONS;
}
+ /* Handle proxy certificates */
+ if((pci=X509_get_ext_d2i(x, NID_proxyCertInfo, NULL, NULL))) {
+ if (x->ex_flags & EXFLAG_CA
+ || X509_get_ext_by_NID(x, NID_subject_alt_name, 0) >= 0
+ || X509_get_ext_by_NID(x, NID_issuer_alt_name, 0) >= 0) {
+ x->ex_flags |= EXFLAG_INVALID;
+ }
+ if (pci->pcPathLengthConstraint) {
+ x->ex_pcpathlen =
+ ASN1_INTEGER_get(pci->pcPathLengthConstraint);
+ } else x->ex_pcpathlen = -1;
+ PROXY_CERT_INFO_EXTENSION_free(pci);
+ x->ex_flags |= EXFLAG_PROXY;
+ }
/* Handle key usage */
if((usage=X509_get_ext_d2i(x, NID_key_usage, NULL, NULL))) {
if(usage->length > 0) {
#define ns_reject(x, usage) \
(((x)->ex_flags & EXFLAG_NSCERT) && !((x)->ex_nscert & (usage)))
-int X509_check_ca(X509 *x)
+static int check_ca(const 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) {
/* 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;
}
}
+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);
+ }
+
+ return check_ca(x);
+}
+
/* Check SSL CA: common checks for SSL client and server */
static int check_ssl_ca(const X509 *x)
{
int ca_ret;
- ca_ret = X509_check_ca(x);
+ ca_ret = check_ca(x);
if(!ca_ret) return 0;
/* check nsCertType if present */
if(ca_ret != 5 || x->ex_nscert & NS_SSL_CA) return ca_ret;
if(xku_reject(x,XKU_SMIME)) return 0;
if(ca) {
int ca_ret;
- ca_ret = X509_check_ca(x);
+ ca_ret = check_ca(x);
if(!ca_ret) return 0;
/* check nsCertType if present */
if(ca_ret != 5 || x->ex_nscert & NS_SMIME_CA) return ca_ret;
{
if(ca) {
int ca_ret;
- if((ca_ret = X509_check_ca(x)) != 2) return ca_ret;
+ if((ca_ret = check_ca(x)) != 2) return ca_ret;
else return 0;
}
if(ku_reject(x, KU_CRL_SIGN)) 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);
+ if(ca) return check_ca(x);
/* leaf certificate is checked in OCSP_verify() */
return 1;
}
return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH;
}
}
- if(ku_reject(issuer, KU_KEY_CERT_SIGN)) return X509_V_ERR_KEYUSAGE_NO_CERTSIGN;
+ if(subject->ex_flags & EXFLAG_PROXY)
+ {
+ if(ku_reject(issuer, KU_DIGITAL_SIGNATURE))
+ return X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE;
+ }
+ else if(ku_reject(issuer, KU_KEY_CERT_SIGN))
+ return X509_V_ERR_KEYUSAGE_NO_CERTSIGN;
return X509_V_OK;
}