Issue with SSL client certificate

I have a unusual case where, as a server, I need the client to provide a
SSL cert, however, I am not interested in verifying it. In order to
convince the client to provide a cert, the SSL_VERIFY_PEER param is
passed to the context using SSL_CTX_set_verify function. This happens
in the function ngx_ssl_client_certificate in “ngx_event_openssl.c”
(configured by setting ssl_verify_client to ‘ask’)


ngx_int_t
ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t
*cert,
ngx_int_t depth)
{
STACK_OF(X509_NAME) *list;

SSL_CTX_set_verify(ssl->ctx, SSL_VERIFY_PEER, 

ngx_http_ssl_verify_callback);

SSL_CTX_set_verify_depth(ssl->ctx, depth);

if (cert->len == 0) {
    return NGX_OK;
}

However, in order to get into that code, I have to first call
ngx_http_ssl_merge_srv_conf in “ngx_http_ssl_module.c”:


if (conf->verify) {

    if (conf->client_certificate.len == 0) {
        ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
                      "no ssl_client_certificate for 

ssl_client_verify");
return NGX_CONF_ERROR;
}

    if (ngx_ssl_client_certificate(cf, &conf->ssl,
                                   &conf->client_certificate,
                                   conf->verify_depth)
        != NGX_OK)
    {
        return NGX_CONF_ERROR;
    }
}

The problem is that if (conf->verify) is non-zero, but the
(conf->client_certificate.len == 0), the function is aborted. This will
happen when verify is turned on, but the ca_cert is not supplied in the
configuration. I can get around this by commenting out that check, and
the code works fine.


if (conf->verify) {

/* if (conf->client_certificate.len == 0) {
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
“no ssl_client_certificate for
ssl_client_verify”);
return NGX_CONF_ERROR;
}
*/
if (ngx_ssl_client_certificate(cf, &conf->ssl,
&conf->client_certificate,
conf->verify_depth)
!= NGX_OK)
{
return NGX_CONF_ERROR;
}
}

My question is, does nginx need to return a NGX_CONF_ERROR if the
ssl_client_certificate (ie. ca_cert) is not provided? It already
correct checks for an empty ca_cert in “ngx_ssl_client_certificate” and
returns NGX_OK in that case.

Posted at Nginx Forum:

On Wed, Oct 21, 2009 at 12:10:17PM -0400, scunningham wrote:

if (conf->verify) {
        != NGX_OK)

    {
        return NGX_CONF_ERROR;
    }
}

My question is, does nginx need to return a NGX_CONF_ERROR if the ssl_client_certificate (ie. ca_cert) is not provided? It already correct checks for an empty ca_cert in “ngx_ssl_client_certificate” and returns NGX_OK in that case.

When HTTPS server requests a client to send certificate, it must send
one or more Distinguished Names in the request. Otherwise the client
does
not know what it should send (the client may have many certificate for
different servers). OpenSSL gets these Name from the provided CA
certificate.

Thank you for responding so quickly.

<<
When HTTPS server requests a client to send certificate, it must send
one or more Distinguished Names in the request. Otherwise the client
does
not know what it should send (the client may have many certificate for
different servers). OpenSSL gets these Name from the provided CA
certificate.

snipped from Section 7.4.4, Certificate Request, of RFC 5246, TLS
Version 1.2 as follows:

certificate_authorities
A list of the distinguished names of acceptable
certificate_authorities, represented in DER-encoded format. These
distinguished names may specify a desired distinguished name for a
root CA or for a subordinate CA; thus, this message can be used to
describe known roots as well as a desired authorization space. 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.

My interpretation of this clause is that the “certficate_authorities”
list is optional, so it is legal to have a zero sized list of
distinguished names. OpenSSL seems to handle the zero case fine,
generating a CertificateRequest packet that looks like this (example
from Wireshark):


Handshake Protocol: Certificate Request
Handshake Type: Certificate Request (13)
Length: 9
Certificate types count: 6
Certificate types (6 types)
Certificate type: RSA Fixed DH (3)
Certificate type: DSS Fixed DH (4)
Certificate type: Unknown (5)
Certificate type: Unknown (6)
Certificate type: RSA Sign (1)
Certificate type: DSS Sign (2)
Distinguished Names Length: 0

The client then responds with whatever cert it deems appropriate, which
the server may validate or chose to ignore.

Thanks for your time.

Posted at Nginx Forum: