X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fsrc%2Fdane-openssl.c;h=6c2b1dbdedafff179c7a3f8a4719d5e8fc6b0c51;hb=e3555426308395ef260b0dae4548593ac114aed5;hp=50a2e8aa5ebef706f016a3475f5b90fdd7f669ea;hpb=f92c55222fcc678d28110ec58df998c16e98c84a;p=user%2Fhenk%2Fcode%2Fexim.git diff --git a/src/src/dane-openssl.c b/src/src/dane-openssl.c index 50a2e8aa5..6c2b1dbde 100644 --- a/src/src/dane-openssl.c +++ b/src/src/dane-openssl.c @@ -1,6 +1,8 @@ /* * Author: Viktor Dukhovni * License: THIS CODE IS IN THE PUBLIC DOMAIN. + * + * Copyright (c) The Exim Maintainers 2014 - 2016 */ #include #include @@ -20,10 +22,26 @@ # error "OpenSSL 1.0.0 or higher required" #else /* remainder of file */ -#if OPENSSL_VERSION_NUMBER < 0x10100000L -#define X509_up_ref(x) CRYPTO_add(&((x)->references), 1, CRYPTO_LOCK_X509) +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) +# define X509_up_ref(x) CRYPTO_add(&((x)->references), 1, CRYPTO_LOCK_X509) +#endif +#if OPENSSL_VERSION_NUMBER >= 0x10100000L +# define EXIM_HAVE_ASN1_MACROS +# define EXIM_OPAQUE_X509 +#else +# define X509_STORE_CTX_get_verify(ctx) (ctx)->verify +# define X509_STORE_CTX_get_verify_cb(ctx) (ctx)->verify_cb +# define X509_STORE_CTX_get0_cert(ctx) (ctx)->cert +# define X509_STORE_CTX_get0_chain(ctx) (ctx)->chain +# define X509_STORE_CTX_get0_untrusted(ctx) (ctx)->untrusted + +# define X509_STORE_CTX_set_verify(ctx, verify_chain) (ctx)->verify = (verify_chain) +# define X509_STORE_CTX_set0_verified_chain(ctx, sk) (ctx)->chain = (sk) +# define X509_STORE_CTX_set_error_depth(ctx, val) (ctx)->error_depth = (val) +# define X509_STORE_CTX_set_current_cert(ctx, cert) (ctx)->current_cert = (cert) #endif + #include "danessl.h" #define DANESSL_F_ADD_SKID 100 @@ -190,6 +208,8 @@ typedef struct ssl_dane # define X509_V_ERR_HOSTNAME_MISMATCH X509_V_ERR_APPLICATION_VERIFICATION #endif + + static int match(dane_selector_list slist, X509 *cert, int depth) { @@ -335,7 +355,11 @@ if (id && ASN1_STRING_length(id) == 1 && *ASN1_STRING_data(id) == c) if ( (akid = AUTHORITY_KEYID_new()) != 0 && (akid->keyid = ASN1_OCTET_STRING_new()) != 0 +#ifdef EXIM_HAVE_ASN1_MACROS + && ASN1_OCTET_STRING_set(akid->keyid, (void *) &c, 1) +#else && M_ASN1_OCTET_STRING_set(akid->keyid, (void *) &c, 1) +#endif && X509_add1_ext_i2d(cert, nid, akid, 0, X509V3_ADD_APPEND)) ret = 1; if (akid) @@ -410,7 +434,11 @@ if (cert) { if (trusted && !X509_add1_trust_object(cert, serverAuth)) return 0; +#ifdef EXIM_OPAQUE_X509 + X509_up_ref(cert); +#else CRYPTO_add(&cert->references, 1, CRYPTO_LOCK_X509); +#endif if (!sk_X509_push(*xs, cert)) { X509_free(cert); @@ -575,7 +603,7 @@ int i; int depth = 0; EVP_PKEY *takey; X509 *ca; -STACK_OF(X509) *in = ctx->untrusted; /* XXX: Accessor? */ +STACK_OF(X509) *in = X509_STORE_CTX_get0_untrusted(ctx); if (!grow_chain(dane, UNTRUSTED, 0)) return -1; @@ -686,11 +714,14 @@ if (matched > 0) dane->mdpth = 0; dane->match = cert; X509_up_ref(cert); - if(!ctx->chain) + if(!X509_STORE_CTX_get0_chain(ctx)) { - if ( (ctx->chain = sk_X509_new_null()) != 0 - && sk_X509_push(ctx->chain, cert)) + STACK_OF(X509) * sk = sk_X509_new_null(); + if (sk && sk_X509_push(sk, cert)) + { + X509_STORE_CTX_set0_verified_chain(ctx, sk); X509_up_ref(cert); + } else { DANEerr(DANESSL_F_CHECK_END_ENTITY, ERR_R_MALLOC_FAILURE); @@ -840,6 +871,7 @@ if (gens) continue; if (!(dane->mhost = OPENSSL_strdup(certid))) matched = -1; + DEBUG(D_tls) debug_printf("Dane name_check: matched SAN %s\n", certid); break; } } @@ -850,14 +882,16 @@ if (gens) * XXX: Should the subjectName be skipped when *any* altnames are present, * or only when DNS altnames are present? */ -if (got_altname == 0) +if (!got_altname) { char *certid = parse_subject_name(cert); - if (certid != 0 && *certid - && (matched = match_name(certid, dane)) != 0) + if (certid != 0 && *certid && (matched = match_name(certid, dane)) != 0) + { + DEBUG(D_tls) debug_printf("Dane name_check: matched SN %s\n", certid); dane->mhost = OPENSSL_strdup(certid); - if (certid) - OPENSSL_free(certid); + } + if (certid) + OPENSSL_free(certid); } return matched; } @@ -865,21 +899,19 @@ return matched; static int verify_chain(X509_STORE_CTX *ctx) { -dane_selector_list issuer_rrs; -dane_selector_list leaf_rrs; -int (*cb)(int, X509_STORE_CTX *) = ctx->verify_cb; +int (*cb)(int, X509_STORE_CTX *) = X509_STORE_CTX_get_verify_cb(ctx); +X509 *cert = X509_STORE_CTX_get0_cert(ctx); +int chain_length = sk_X509_num(X509_STORE_CTX_get0_chain(ctx)); int ssl_idx = SSL_get_ex_data_X509_STORE_CTX_idx(); SSL *ssl = X509_STORE_CTX_get_ex_data(ctx, ssl_idx); ssl_dane *dane = SSL_get_ex_data(ssl, dane_idx); -X509 *cert = ctx->cert; /* XXX: accessor? */ +dane_selector_list issuer_rrs = dane->selectors[DANESSL_USAGE_PKIX_TA]; +dane_selector_list leaf_rrs = dane->selectors[DANESSL_USAGE_PKIX_EE]; int matched = 0; -int chain_length = sk_X509_num(ctx->chain); -DEBUG(D_tls) debug_printf("Dane verify-chain\n"); +DEBUG(D_tls) debug_printf("Dane verify_chain\n"); -issuer_rrs = dane->selectors[DANESSL_USAGE_PKIX_TA]; -leaf_rrs = dane->selectors[DANESSL_USAGE_PKIX_EE]; -ctx->verify = dane->verify; +X509_STORE_CTX_set_verify(ctx, dane->verify); if ((matched = name_check(dane, cert)) < 0) { @@ -889,41 +921,41 @@ if ((matched = name_check(dane, cert)) < 0) if (!matched) { - ctx->error_depth = 0; - ctx->current_cert = cert; + X509_STORE_CTX_set_error_depth(ctx, 0); + X509_STORE_CTX_set_current_cert(ctx, cert); X509_STORE_CTX_set_error(ctx, X509_V_ERR_HOSTNAME_MISMATCH); if (!cb(0, ctx)) return 0; } matched = 0; - /* - * Satisfy at least one usage 0 or 1 constraint, unless we've already - * matched a usage 2 trust anchor. - * - * XXX: internal_verify() doesn't callback with top certs that are not - * self-issued. This should be fixed in a future OpenSSL. - */ - if (dane->roots && sk_X509_num(dane->roots)) - { - X509 *top = sk_X509_value(ctx->chain, dane->depth); +/* + * Satisfy at least one usage 0 or 1 constraint, unless we've already + * matched a usage 2 trust anchor. + * + * XXX: internal_verify() doesn't callback with top certs that are not + * self-issued. This should be fixed in a future OpenSSL. + */ +if (dane->roots && sk_X509_num(dane->roots)) + { + X509 *top = sk_X509_value(X509_STORE_CTX_get0_chain(ctx), dane->depth); - dane->mdpth = dane->depth; - dane->match = top; - X509_up_ref(top); + dane->mdpth = dane->depth; + dane->match = top; + X509_up_ref(top); #ifndef NO_CALLBACK_WORKAROUND - if (X509_check_issued(top, top) != X509_V_OK) - { - ctx->error_depth = dane->depth; - ctx->current_cert = top; - if (!cb(1, ctx)) - return 0; - } + if (X509_check_issued(top, top) != X509_V_OK) + { + X509_STORE_CTX_set_error_depth(ctx, dane->depth); + X509_STORE_CTX_set_current_cert(ctx, top); + if (!cb(1, ctx)) + return 0; + } #endif /* Pop synthetic trust-anchor ancestors off the chain! */ while (--chain_length > dane->depth) - X509_free(sk_X509_pop(ctx->chain)); + X509_free(sk_X509_pop(X509_STORE_CTX_get0_chain(ctx))); } else { @@ -936,19 +968,22 @@ else */ if (leaf_rrs) matched = match(leaf_rrs, xn, 0); + if (matched) DEBUG(D_tls) debug_printf("Dane verify_chain: matched EE\n"); if (!matched && issuer_rrs) for (n = chain_length-1; !matched && n >= 0; --n) { - xn = sk_X509_value(ctx->chain, n); + xn = sk_X509_value(X509_STORE_CTX_get0_chain(ctx), n); if (n > 0 || X509_check_issued(xn, xn) == X509_V_OK) matched = match(issuer_rrs, xn, n); } + if (matched) DEBUG(D_tls) debug_printf("Dane verify_chain: matched %s\n", + n>0 ? "CA" : "selfisssued EE"); if (!matched) { - ctx->current_cert = cert; - ctx->error_depth = 0; + X509_STORE_CTX_set_error_depth(ctx, 0); + X509_STORE_CTX_set_current_cert(ctx, cert); X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_UNTRUSTED); if (!cb(0, ctx)) return 0; @@ -961,7 +996,7 @@ else } } -return ctx->verify(ctx); +return (X509_STORE_CTX_get_verify(ctx))(ctx); } static void @@ -997,11 +1032,11 @@ verify_cert(X509_STORE_CTX *ctx, void *unused_ctx) static int ssl_idx = -1; SSL *ssl; ssl_dane *dane; -int (*cb)(int, X509_STORE_CTX *) = ctx->verify_cb; +int (*cb)(int, X509_STORE_CTX *) = X509_STORE_CTX_get_verify_cb(ctx); +X509 *cert = X509_STORE_CTX_get0_cert(ctx); int matched; -X509 *cert = ctx->cert; /* XXX: accessor? */ -DEBUG(D_tls) debug_printf("Dane verify-cert\n"); +DEBUG(D_tls) debug_printf("Dane verify_cert\n"); if (ssl_idx < 0) ssl_idx = SSL_get_ex_data_X509_STORE_CTX_idx(); @@ -1015,15 +1050,15 @@ ssl = X509_STORE_CTX_get_ex_data(ctx, ssl_idx); if (!(dane = SSL_get_ex_data(ssl, dane_idx)) || !cert) return X509_verify_cert(ctx); - /* Reset for verification of a new chain, perhaps a renegotiation. */ +/* Reset for verification of a new chain, perhaps a renegotiation. */ dane_reset(dane); if (dane->selectors[DANESSL_USAGE_DANE_EE]) { if ((matched = check_end_entity(ctx, dane, cert)) > 0) { - ctx->error_depth = 0; - ctx->current_cert = cert; + X509_STORE_CTX_set_error_depth(ctx, 0); + X509_STORE_CTX_set_current_cert(ctx, cert); return cb(1, ctx); } if (matched < 0) @@ -1048,7 +1083,7 @@ if (dane->selectors[DANESSL_USAGE_DANE_EE]) */ X509_STORE_CTX_trusted_stack(ctx, dane->roots); X509_STORE_CTX_set_chain(ctx, dane->chain); - OPENSSL_assert(ctx->untrusted == dane->chain); + OPENSSL_assert(X509_STORE_CTX_get0_untrusted(ctx) == dane->chain); } } @@ -1057,8 +1092,8 @@ if (dane->selectors[DANESSL_USAGE_DANE_EE]) * X509_verify_cert() builds the full chain and calls our verify_chain() * wrapper. */ - dane->verify = ctx->verify; - ctx->verify = verify_chain; + dane->verify = X509_STORE_CTX_get_verify(ctx); + X509_STORE_CTX_set_verify(ctx, verify_chain); if (X509_verify_cert(ctx)) return 1;