*) applies to 0.9.6a/0.9.6b/0.9.6c and 0.9.7
+) applies to 0.9.7 only
+ +) Test for certificates which contain unsupported critical extensions.
+ If such a certificate is found during a verify operation it is
+ rejected by default: this behaviour can be overridden by either
+ handling the new error X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION or
+ by setting the verify flag X509_V_FLAG_IGNORE_CRITICAL. A new function
+ X509_supported_extension() has also been added which returns 1 if a
+ particular extension is supported.
+ [Steve Henson]
+
+) New functions/macros
SSL_CTX_set_msg_callback(ctx, cb)
}
else if (strcmp(*argv,"-help") == 0)
goto end;
+ else if (strcmp(*argv,"-ignore_critical") == 0)
+ vflags |= X509_V_FLAG_IGNORE_CRITICAL;
else if (strcmp(*argv,"-issuer_checks") == 0)
vflags |= X509_V_FLAG_CB_ISSUER_CHECK;
else if (strcmp(*argv,"-crl_check") == 0)
if (ctx->error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) ok=1;
if (ctx->error == X509_V_ERR_CRL_HAS_EXPIRED) ok=1;
if (ctx->error == X509_V_ERR_CRL_NOT_YET_VALID) ok=1;
+ if (ctx->error == X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION) ok=1;
}
if (!v_verbose)
ERR_clear_error();
case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER:
return("unable to get CRL issuer certificate");
+ case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION:
+ return("unhandled critical extension");
+
default:
sprintf(buf,"error number %ld",n);
return(buf);
for (i = 0; i < ctx->last_untrusted; i++)
{
x = sk_X509_value(ctx->chain, i);
+ if (!(ctx->flags & X509_V_FLAG_IGNORE_CRITICAL)
+ && (x->ex_flags & EXFLAG_CRITICAL))
+ {
+ ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION;
+ ctx->error_depth = i;
+ ctx->current_cert = x;
+ ok=cb(0,ctx);
+ if (!ok) goto end;
+ }
if (!X509_check_purpose(x, ctx->purpose, i))
{
if (i)
if (!ok) goto end;
}
- /* CRL CHECK */
-
/* The last error (if any) is still in the error value */
ctx->current_cert=xs;
ok=(*cb)(1,ctx);
#define X509_V_ERR_KEYUSAGE_NO_CERTSIGN 32
#define X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER 33
+#define X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION 34
/* The application is not happy */
#define X509_V_ERR_APPLICATION_VERIFICATION 50
#define X509_V_FLAG_USE_CHECK_TIME 0x2 /* Use check time instead of current time */
#define X509_V_FLAG_CRL_CHECK 0x4 /* Lookup CRLs */
#define X509_V_FLAG_CRL_CHECK_ALL 0x8 /* Lookup CRLs for whole chain */
+#define X509_V_FLAG_IGNORE_CRITICAL 0x10 /* Ignore unhandled critical extensions */
int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, int type,
X509_NAME *name);
/* v3_purp.c */
/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
- * project 1999.
+ * project 2001.
*/
/* ====================================================================
- * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1999-2001 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
return xp->trust;
}
+static int nid_cmp(int *a, int *b)
+ {
+ return *a - *b;
+ }
+
+int X509_supported_extension(X509_EXTENSION *ex)
+ {
+ /* This table is a list of the NIDs of supported extensions:
+ * that is those which are used by the verify process. If
+ * an extension is critical and doesn't appear in this list
+ * then the verify process will normally reject the certificate.
+ * The list must be kept in numerical order because it will be
+ * searched using bsearch.
+ */
+
+ static int supported_nids[] = {
+ NID_netscape_cert_type, /* 71 */
+ NID_key_usage, /* 83 */
+ NID_subject_alt_name, /* 85 */
+ NID_basic_constraints, /* 87 */
+ NID_ext_key_usage /* 126 */
+ };
+
+ int ex_nid;
+
+ ex_nid = OBJ_obj2nid(X509_EXTENSION_get_object(ex));
+
+ if (ex_nid == NID_undef)
+ return 0;
+
+ if (OBJ_bsearch((char *)&ex_nid, (char *)supported_nids,
+ sizeof(supported_nids)/sizeof(int), sizeof(int),
+ (int (*)(const void *, const void *))nid_cmp))
+ return 1;
+ return 0;
+ }
+
+
static void x509v3_cache_extensions(X509 *x)
{
BASIC_CONSTRAINTS *bs;
ASN1_BIT_STRING *usage;
ASN1_BIT_STRING *ns;
EXTENDED_KEY_USAGE *extusage;
+ X509_EXTENSION *ex;
int i;
if(x->ex_flags & EXFLAG_SET) return;
}
x->skid =X509_get_ext_d2i(x, NID_subject_key_identifier, NULL, NULL);
x->akid =X509_get_ext_d2i(x, NID_authority_key_identifier, NULL, NULL);
+ for (i = 0; i < X509_get_ext_count(x); i++)
+ {
+ ex = X509_get_ext(x, i);
+ if (!X509_EXTENSION_get_critical(ex))
+ continue;
+ if (!X509_supported_extension(ex))
+ {
+ x->ex_flags |= EXFLAG_CRITICAL;
+ break;
+ }
+ }
x->ex_flags |= EXFLAG_SET;
}
#define EXFLAG_V1 0x40
#define EXFLAG_INVALID 0x80
#define EXFLAG_SET 0x100
+#define EXFLAG_CRITICAL 0x200
#define KU_DIGITAL_SIGNATURE 0x0080
#define KU_NON_REPUDIATION 0x0040
int X509V3_extensions_print(BIO *out, char *title, STACK_OF(X509_EXTENSION) *exts, unsigned long flag, int indent);
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);
int X509_check_issued(X509 *issuer, X509 *subject);
int X509_PURPOSE_get_count(void);