-/* $OpenBSD: x509_internal.h,v 1.20 2022/11/11 12:02:34 beck Exp $ */
+/* $OpenBSD: x509_internal.h,v 1.21 2022/11/13 18:37:32 beck Exp $ */
/*
* Copyright (c) 2020 Bob Beck <beck@openbsd.org>
*
struct x509_constraints_names *excluded, int *error);
int x509_constraints_chain(STACK_OF(X509) *chain, int *error,
int *depth);
+int x509_check_trust_no_compat(X509 *x, int id, int flags);
void x509_verify_cert_info_populate(X509 *cert);
int x509_vfy_check_security_level(X509_STORE_CTX *ctx);
-/* $OpenBSD: x509_trs.c,v 1.26 2022/11/10 16:52:19 beck Exp $ */
+/* $OpenBSD: x509_trs.c,v 1.27 2022/11/13 18:37:32 beck Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 1999.
*/
return oldtrust;
}
-int
-X509_check_trust(X509 *x, int id, int flags)
+static int
+X509_check_trust_internal(X509 *x, int id, int flags, int compat)
{
X509_TRUST *pt;
int idx;
rv = obj_trust(NID_anyExtendedKeyUsage, x, 0);
if (rv != X509_TRUST_UNTRUSTED)
return rv;
- return trust_compat(NULL, x, 0);
+ return compat && trust_compat(NULL, x, 0);
}
idx = X509_TRUST_get_by_id(id);
if (idx == -1)
return pt->check_trust(pt, x, flags);
}
+int
+X509_check_trust(X509 *x, int id, int flags)
+{
+ return X509_check_trust_internal(x, id, flags, /*compat =*/1);
+}
+
+int
+x509_check_trust_no_compat(X509 *x, int id, int flags)
+{
+ return X509_check_trust_internal(x, id, flags, /*compat =*/0);
+}
+
int
X509_TRUST_get_count(void)
{
-/* $OpenBSD: x509_vfy.c,v 1.103 2022/08/31 07:15:31 tb Exp $ */
+/* $OpenBSD: x509_vfy.c,v 1.104 2022/11/13 18:37:32 beck Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
return 0;
}
+/*
+ * X509_check_purpose is special.
+ * 0 is bad, 1 is good, values > 1 are maybe good for web pki necromancy
+ * and certificates that were checked into software unit tests years ago
+ * that nobody knows how to change. (Netscape Server Gated Crypto Forever!)
+ */
+#define PURPOSE_GOOD(x) (x == 1)
+#define PURPOSE_BAD(x) (x == 0)
+static int
+check_purpose(X509_STORE_CTX *ctx, X509 *x, int purpose, int depth,
+ int must_be_ca)
+{
+ int purpose_check, trust;
+
+ purpose_check = X509_check_purpose(x, purpose, must_be_ca > 0);
+ trust = X509_TRUST_UNTRUSTED;
+
+ /*
+ * For trusted certificates we want to see whether any auxiliary trust
+ * settings for the desired purpose override the purpose constraints
+ * from the certificate EKU.
+ */
+ if (depth >= ctx->num_untrusted && purpose == ctx->param->purpose)
+ trust = x509_check_trust_no_compat(x, ctx->param->trust, 0);
+
+ /* XXX STRICT should really be the default */
+ if (trust != X509_TRUST_REJECTED && !PURPOSE_BAD(purpose_check)) {
+ return PURPOSE_GOOD(purpose_check) ||
+ (ctx->param->flags & X509_V_FLAG_X509_STRICT) == 0;
+ }
+
+ ctx->error = X509_V_ERR_INVALID_PURPOSE;
+ ctx->error_depth = depth;
+ ctx->current_cert = x;
+ return ctx->verify_cb(0, ctx);
+}
+
/* Check a certificate chains extensions for consistency
* with the supplied purpose
*/
int proxy_path_length = 0;
int purpose;
int allow_proxy_certs;
+ size_t chain_len;
cb = ctx->verify_cb;
purpose = ctx->param->purpose;
}
- /* Check all untrusted certificates */
- for (i = 0; i < ctx->num_untrusted; i++) {
+ chain_len = sk_X509_num(ctx->chain);
+ for (i = 0; i < chain_len; i++) {
int ret;
x = sk_X509_value(ctx->chain, i);
if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL) &&
if (!ok)
goto end;
}
+ if (purpose > 0) {
+ ok = check_purpose(ctx, x, purpose, i, must_be_ca);
+ if (!ok)
+ goto end;
+ }
if (ctx->param->purpose > 0) {
ret = X509_check_purpose(x, purpose, must_be_ca > 0);
if ((ret == 0) ||