[nginx] CONF: Make ssl_client_certificate directive optional with TLSv1.3

Praveen Chaudhary pclicoder at gmail.com
Wed Aug 21 16:36:07 UTC 2024


@a.bavshin at nginx.com <a.bavshin at nginx.com>

Gentle Reminder for review. This feature to make ssl_client_certificate
optional may help us here at Nvidia.
Thanks in advance. Kindly let me know if any more modification is needed in
fix.

Note: AFAIK, mTLS was not supported with SSLv2. I kept the NGX_SSL_SSLv2
flag in fix, if Nginx today supports SSLv2.

On Mon, Aug 19, 2024 at 4:22 PM Praveen Chaudhary <pclicoder at gmail.com>
wrote:

> Thanks Aleksei for the review.
>
> Agree, It makes sense to have explicit error message to require either
> ssl_client_certificate or ssl_trusted_certificate. Because:
> Nginx prints error number from SSL to identify SSL error\routine,
> but for a client or admin, it may be still hard to find why "SSL
> certificate error"
> is seen.
>
> V2 Patch.
> [Keeping same Subject]
>
> # HG changeset patch
> # User Praveen Chaudhary <praveen5582 at gmail.com>
> # Date 1723406727 25200
> #      Sun Aug 11 13:05:27 2024 -0700
> # Node ID a5525b8eac0e1f10da42b7367cd5296fb29f4787
> # Parent  8796dfbe7177cb0be2a53bcdb4d25cc64a58d2a7
> Make ssl_client_certificate directive optional with TLSv1.1+.
>
> - With TLS 1.1+, Certificate Authorities(CAs) are optional
>   in the Certificate Request packet. This makes directive
>   ssl_client_certificate also optional for mutual TLS
>   configurations.
>
> - For TLS 1.1, check either ssl_client_certificate or
>   ssl_trusted_certificate is non empty.
>
> diff -r 8796dfbe7177 -r a5525b8eac0e src/http/modules/ngx_http_ssl_module.c
> --- a/src/http/modules/ngx_http_ssl_module.c Mon Aug 12 18:21:01 2024 +0400
> +++ b/src/http/modules/ngx_http_ssl_module.c Sun Aug 11 13:05:27 2024 -0700
> @@ -788,9 +788,20 @@
>      if (conf->verify) {
>
>          if (conf->client_certificate.len == 0 && conf->verify != 3) {
> -            ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
> -                          "no ssl_client_certificate for
> ssl_verify_client");
> -            return NGX_CONF_ERROR;
> +
> +            if (conf->protocols &
> +                (NGX_SSL_SSLv2|NGX_SSL_SSLv3|NGX_SSL_TLSv1)) {
> +                ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
> +                            "no ssl_client_certificate for
> ssl_verify_client");
> +                return NGX_CONF_ERROR;
> +            }
> +            /* For TLS 1.1+. */
> +            if (conf->trusted_certificate.len == 0) {
> +                ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
> +                            "no ssl_client_certificate or "
> +                            "ssl_trusted_certificate for
> ssl_verify_client");
> +                return NGX_CONF_ERROR;
> +            }
>          }
>
>          if (ngx_ssl_client_certificate(cf, &conf->ssl,
> diff -r 8796dfbe7177 -r a5525b8eac0e src/mail/ngx_mail_ssl_module.c
> --- a/src/mail/ngx_mail_ssl_module.c Mon Aug 12 18:21:01 2024 +0400
> +++ b/src/mail/ngx_mail_ssl_module.c Sun Aug 11 13:05:27 2024 -0700
> @@ -451,9 +451,20 @@
>      if (conf->verify) {
>
>          if (conf->client_certificate.len == 0 && conf->verify != 3) {
> -            ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
> -                          "no ssl_client_certificate for
> ssl_verify_client");
> -            return NGX_CONF_ERROR;
> +
> +            if (conf->protocols &
> +                (NGX_SSL_SSLv2|NGX_SSL_SSLv3|NGX_SSL_TLSv1)) {
> +                ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
> +                            "no ssl_client_certificate for
> ssl_verify_client");
> +                return NGX_CONF_ERROR;
> +            }
> +            /* For TLS 1.1+. */
> +            if (conf->trusted_certificate.len == 0) {
> +                ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
> +                            "no ssl_client_certificate or "
> +                            "ssl_trusted_certificate for
> ssl_verify_client");
> +                return NGX_CONF_ERROR;
> +            }
>          }
>
>          if (ngx_ssl_client_certificate(cf, &conf->ssl,
> diff -r 8796dfbe7177 -r a5525b8eac0e src/stream/ngx_stream_ssl_module.c
> --- a/src/stream/ngx_stream_ssl_module.c Mon Aug 12 18:21:01 2024 +0400
> +++ b/src/stream/ngx_stream_ssl_module.c Sun Aug 11 13:05:27 2024 -0700
> @@ -933,9 +933,20 @@
>      if (conf->verify) {
>
>          if (conf->client_certificate.len == 0 && conf->verify != 3) {
> -            ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
> -                          "no ssl_client_certificate for
> ssl_verify_client");
> -            return NGX_CONF_ERROR;
> +
> +            if (conf->protocols &
> +                (NGX_SSL_SSLv2|NGX_SSL_SSLv3|NGX_SSL_TLSv1)) {
> +                ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
> +                            "no ssl_client_certificate for
> ssl_verify_client");
> +                return NGX_CONF_ERROR;
> +            }
> +            /* For TLS 1.1+. */
> +            if (conf->trusted_certificate.len == 0) {
> +                ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
> +                            "no ssl_client_certificate or "
> +                            "ssl_trusted_certificate for
> ssl_verify_client");
> +                return NGX_CONF_ERROR;
> +            }
>          }
>
>          if (ngx_ssl_client_certificate(cf, &conf->ssl,
>
> On Mon, Aug 19, 2024 at 11:41 AM Aleksei Bavshin <a.bavshin at nginx.com>
> wrote:
>
>> On 8/16/2024 8:02 AM, Praveen Chaudhary wrote:
>> > Hi Nginx Devs
>> >
>> > Bumping patch to the top for review.
>> >
>> > CC: @Sergey Kandaurov
>> > Thanks for contributing client certificate validation with OSCP.  It is
>> > a long awaited feature.
>> > In this patch, I am trying to fix another lingering concern. It will be
>> > great, if you can have a look.
>>
>> Hello,
>>
>> Sending an empty list of CAs is explicitly mentioned starting from TLS
>> 1.1; RFC 4346 Section 7.4.4:
>>
>>      If the certificate_authorities list is empty then the client MAY
>>      send any certificate of the appropriate ClientCertificateType,
>>      unless there is some external arrangement to the contrary.
>>
>> TLS 1.0 (RFC 2246 Section 7.4.4) does not specify any behavior. While
>> it's known that some 1.0 or SSL 3.0 clients can accept an empty list, it
>> could be safer to limit the ability to the TLS 1.1+ configurations.
>>
>> As for the means of doing so, simply skipping the
>> conf->client_certificate check is not correct. For any ssl_client_verify
>> mode other than 'optional_no_ca' nginx must have a list of known trusted
>> CAs, and the configuration without any is not valid.
>> A better approach is to require either 'ssl_client_certificate' or
>> 'ssl_trusted_certificate' to be set when the client cert verification is
>> enabled.
>>
>> >
>> > # HG changeset patch
>> > # User Praveen Chaudhary <praveen5582 at gmail.com
>> > <mailto:praveen5582 at gmail.com>>
>> > # Date 1723406727 25200
>> > #      Sun Aug 11 13:05:27 2024 -0700
>> > # Node ID 199a35c74b60437da9d22a70d257507b4afb1878
>> > # Parent  b5550a7f16c795f394f9d1ac87132dd2b7ef0e41
>> > Make ssl_client_certificate directive optional with TLSv1.3.
>> >
>> > - As per RFC 8446 Section 4.2.4, server MAY (not SHOULD or MUST)
>> >    send Certificate Authorities (CAs) in the Certificate Request
>> >    packet. This makes ssl_client_certificate directive optional
>> >    when only TLS 1.3 is used for mutual TLS configurations.
>>  > > - Today, Nginx requires ssl_client_certificate directive to
>> >    be set to CA Certificates file, if ssl_verify_client is
>> >    enabled, even when using only TLS 1.3. Else Nginx does not
>> >    reload or restart.
>> >
>> > diff -r b5550a7f16c7 -r 199a35c74b60
>> src/http/modules/ngx_http_ssl_module.c
>> > --- a/src/http/modules/ngx_http_ssl_module.c Fri Aug 09 19:12:26 2024
>> +0400
>> > +++ b/src/http/modules/ngx_http_ssl_module.c Sun Aug 11 13:05:27 2024
>> -0700
>> > @@ -787,10 +787,16 @@
>> >
>> >       if (conf->verify) {
>> >
>> > -        if (conf->client_certificate.len == 0 && conf->verify != 3) {
>> > -            ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
>> > -                          "no ssl_client_certificate for
>> > ssl_verify_client");
>> > -            return NGX_CONF_ERROR;
>> > +        if (conf->protocols & (NGX_SSL_TLSv1|NGX_SSL_TLSv1_1|
>> > NGX_SSL_TLSv1_2)) {
>> > +            /*
>> > +            For TLS 1.3, It is optional to send Certificate
>> Authorities in
>> > +            Certificate Request Packet. RFC 8446#section-4.2.4
>> > +            */
>> > +            if (conf->client_certificate.len == 0 && conf->verify !=
>> 3) {
>> > +                ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
>> > +                            "no ssl_client_certificate for
>> > ssl_verify_client");
>> > +                return NGX_CONF_ERROR;
>> > +            }
>> >           }
>> >
>> >           if (ngx_ssl_client_certificate(cf, &conf->ssl,
>> > diff -r b5550a7f16c7 -r 199a35c74b60 src/mail/ngx_mail_ssl_module.c
>> > --- a/src/mail/ngx_mail_ssl_module.c Fri Aug 09 19:12:26 2024 +0400
>> > +++ b/src/mail/ngx_mail_ssl_module.c Sun Aug 11 13:05:27 2024 -0700
>> > @@ -450,12 +450,19 @@
>> >
>> >       if (conf->verify) {
>> >
>> > -        if (conf->client_certificate.len == 0 && conf->verify != 3) {
>> > -            ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
>> > -                          "no ssl_client_certificate for
>> > ssl_verify_client");
>> > -            return NGX_CONF_ERROR;
>> > +        if (conf->protocols & (NGX_SSL_TLSv1|NGX_SSL_TLSv1_1|
>> > NGX_SSL_TLSv1_2)) {
>> > +            /*
>> > +            For TLS 1.3, It is optional to send Certificate
>> Authorities in
>> > +            Certificate Request Packet. RFC 8446#section-4.2.4
>> > +            */
>> > +            if (conf->client_certificate.len == 0 && conf->verify !=
>> 3) {
>> > +                ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
>> > +                            "no ssl_client_certificate for
>> > ssl_verify_client");
>> > +                return NGX_CONF_ERROR;
>> > +            }
>> >           }
>> >
>> > +
>> >           if (ngx_ssl_client_certificate(cf, &conf->ssl,
>> >                                          &conf->client_certificate,
>> >                                          conf->verify_depth)
>> > diff -r b5550a7f16c7 -r 199a35c74b60 src/stream/ngx_stream_ssl_module.c
>> > --- a/src/stream/ngx_stream_ssl_module.c Fri Aug 09 19:12:26 2024 +0400
>> > +++ b/src/stream/ngx_stream_ssl_module.c Sun Aug 11 13:05:27 2024 -0700
>> > @@ -932,10 +932,16 @@
>> >
>> >       if (conf->verify) {
>> >
>> > -        if (conf->client_certificate.len == 0 && conf->verify != 3) {
>> > -            ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
>> > -                          "no ssl_client_certificate for
>> > ssl_verify_client");
>> > -            return NGX_CONF_ERROR;
>> > +        if (conf->protocols & (NGX_SSL_TLSv1|NGX_SSL_TLSv1_1|
>> > NGX_SSL_TLSv1_2)) {
>> > +            /*
>> > +            For TLS 1.3, It is optional to send Certificate
>> Authorities in
>> > +            Certificate Request Packet. RFC 8446#section-4.2.4
>> > +            */
>> > +            if (conf->client_certificate.len == 0 && conf->verify !=
>> 3) {
>> > +                ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
>> > +                            "no ssl_client_certificate for
>> > ssl_verify_client");
>> > +                return NGX_CONF_ERROR;
>> > +            }
>> >           }
>> >
>> >           if (ngx_ssl_client_certificate(cf, &conf->ssl,
>> >
>> > _______________________________________________
>> > nginx-devel mailing list
>> > nginx-devel at nginx.org
>> > https://mailman.nginx.org/mailman/listinfo/nginx-devel
>> _______________________________________________
>> nginx-devel mailing list
>> nginx-devel at nginx.org
>> https://mailman.nginx.org/mailman/listinfo/nginx-devel
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.nginx.org/pipermail/nginx-devel/attachments/20240821/b7c42317/attachment-0001.htm>


More information about the nginx-devel mailing list