[PATCH] SSL: consistent certificate verification depth
Maxim Dounin
mdounin at mdounin.ru
Wed Jul 20 18:04:52 UTC 2022
Hello!
On Wed, Jul 20, 2022 at 05:58:26PM +0400, Sergey Kandaurov wrote:
> # HG changeset patch
> # User Sergey Kandaurov <pluknet at nginx.com>
> # Date 1658325446 -14400
> # Wed Jul 20 17:57:26 2022 +0400
> # Node ID 5a9cc2a846c9ea4c0af03109ab186af1ac28e222
> # Parent 069a4813e8d6d7ec662d282a10f5f7062ebd817f
> SSL: consistent certificate verification depth.
>
> Originally, certificate verification depth was used to limit the number
> of signatures to validate, that is, to limit chains with intermediate
> certificates one less. The semantics was changed in OpenSSL 1.1.0, and
> instead it limits now the number of intermediate certificates allowed.
> This makes it not possible to limit certificate checking to self-signed
> certificates with verify depth 0 in OpenSSL 1.1.0+, and is inconsistent
> compared with former behaviour in BoringSSL and older OpenSSL versions.
>
> This change restores former verification logic when using OpenSSL 1.1.0+.
> The verify callback is adjusted to emit the "certificate chain too long"
> error when the certificate chain exceeds the verification depth. It has
> no effect to other SSL libraries, where this is limited by other means.
> Also, this fixes verification checks when using LibreSSL 3.4.0+, where
> a chain depth is not limited except by X509_VERIFY_MAX_CHAIN_CERTS (32).
This (highly questionable) OpenSSL behaviour seems to be status
quo for a while, also recorded in tests (see ssl_verify_depth.t).
Any specific reasons for the nginx-side workaround?
>
> diff -r 069a4813e8d6 -r 5a9cc2a846c9 src/event/ngx_event_openssl.c
> --- a/src/event/ngx_event_openssl.c Tue Jul 19 17:05:27 2022 +0300
> +++ b/src/event/ngx_event_openssl.c Wed Jul 20 17:57:26 2022 +0400
> @@ -997,16 +997,26 @@ ngx_ssl_crl(ngx_conf_t *cf, ngx_ssl_t *s
> static int
> ngx_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store)
> {
> + int depth, verify_depth;
> + ngx_ssl_conn_t *ssl_conn;
> +
> + ssl_conn = X509_STORE_CTX_get_ex_data(x509_store,
> + SSL_get_ex_data_X509_STORE_CTX_idx());
> +
> + depth = X509_STORE_CTX_get_error_depth(x509_store);
> + verify_depth = SSL_CTX_get_verify_depth(SSL_get_SSL_CTX(ssl_conn));
s/verify_depth/limit/?
Also, using SSL_get_verify_depth() instead of going through SSL
context might be easier.
> +
> + if (depth > verify_depth) {
> + X509_STORE_CTX_set_error(x509_store, X509_V_ERR_CERT_CHAIN_TOO_LONG);
This is going to overwrite earlier errors, if any. Does not look like a good
idea.
> + }
> +
> #if (NGX_DEBUG)
> +
> + int err;
This is not going to work, variables have to be defined at the
start of a block unless you assume C99. At least MSVC 2010 won't
be able to compile this.
> char *subject, *issuer;
> - int err, depth;
> X509 *cert;
> X509_NAME *sname, *iname;
> ngx_connection_t *c;
> - ngx_ssl_conn_t *ssl_conn;
> -
> - ssl_conn = X509_STORE_CTX_get_ex_data(x509_store,
> - SSL_get_ex_data_X509_STORE_CTX_idx());
>
> c = ngx_ssl_get_connection(ssl_conn);
>
> @@ -1016,7 +1026,6 @@ ngx_ssl_verify_callback(int ok, X509_STO
>
> cert = X509_STORE_CTX_get_current_cert(x509_store);
> err = X509_STORE_CTX_get_error(x509_store);
> - depth = X509_STORE_CTX_get_error_depth(x509_store);
>
> sname = X509_get_subject_name(cert);
>
> @@ -1058,6 +1067,7 @@ ngx_ssl_verify_callback(int ok, X509_STO
> if (issuer) {
> OPENSSL_free(issuer);
> }
> +
> #endif
>
> return 1;
>
--
Maxim Dounin
http://mdounin.ru/
More information about the nginx-devel
mailing list