Trouble with ssl_verify_client option

Hello mailinglist,

Somehow I can’t get the ssl_verify_client option to work properly for
me. As it more and more looks like this might be a bug, I thought I’d
report. I’m using 0.8.53, but upgraded from 0.7.67 because of this
problem.

The problem is with setting ssl_verify_client in any server {} block.
Setting it globally (in the http{} block) works as expected, but I
can’t get ssl_verify_client enabled for one specific server {} and not
for all the others. Setting it to ‘optional’ in a server config
doesn’t change much (maybe something does change, but nothing
noticeable happens), though setting it to ‘on’ does deny connections
without a client certificate. Sadly this, like ‘optional’, still does
mean it won’t ask for a client certificate so will deny access to
every request.

Am I expecting the wrong things here, or is server-specific
ssl_verify_client setting broken here?

Regards,
Luit van Drongelen [email protected]

On Fri, Nov 5, 2010 at 1:14 AM, Luit van Drongelen [email protected]
wrote:

Am I expecting the wrong things here, or is server-specific
ssl_verify_client setting broken here?

My case further simplified:
http { server { listen: 443; ssl on; ssl_verify_client optional;
certificate and key stuffs; }} # DOESN’T WORK
vs.
http { ssl_verify_client: optional; certificate and key stuffs;
server{listen: 443; ssl: on; }} # WORKS FINE

This is the same for ssl_verify_client: on, where the “doesn’t work”
means it’ll just stop any request.
So are my expectations of ssl_verify_client wrong, or would this be a
bug?

Regards,
Luit van Drongelen [email protected]

Hello!

On Fri, Nov 05, 2010 at 11:28:33PM +0100, Luit van Drongelen wrote:

This is the same for ssl_verify_client: on, where the “doesn’t work”
means it’ll just stop any request.
So are my expectations of ssl_verify_client wrong, or would this be a bug?

Directive ssl_verify_client works correctly only on
per-ssl-connection basis (as well as ssl_certificate) as it
requires client certificate request during ssl handshake.

This means that (unless you have SNI[1] enabled) if you have multiple
ssl server{}'s listening on the same ip:port pair - you have to
specify ssl_verify_client identical (or at least somewhat synced)
for all servers on the ip:port pair in question.

[1] Server Name Indication - Wikipedia

Your simplified cases should both work ok (and they works ok here,
and I doubt you actually tested them). Though this one will cause
troubles without SNI:

http {
server {
listen 443;
server_name test1.example.com;
ssl on;

}

server {
listen 443;
server_name test2.example.com;
ssl on;
ssl_verify_client on;

}
}

Default server for port 443 is first one, test1.example.com, and
all ssl connections will be established without certificate
request (and with server certificate specified in this server -
though this is probably obvious). As soon as request to
test2.example.com comes in - nginx will select second server, try
to check client’s certificate and return 400 as there is no client
certificate.

Obvious solutions are:

  1. Use separate ip’s for separate servers.

  2. Keep ssl_verify_client at least “optional” in the default
    server for ip:port pair if you want client certificates to be
    available for servers on the ip:port pair in question. Note that
    this may cause unnecessary “select certificate to submit” dialogs
    in browser.

  3. Use SNI. As long as you care about IE users under Windows XP -
    this probably isn’t an option.

Maxim D.

On Sat, Nov 6, 2010 at 3:06 AM, Maxim D. [email protected] wrote:

Your simplified cases should both work ok (and they works ok here,
and I doubt you actually tested them). Though this one will cause
troubles without SNI:

They do work for changing certificates, but the ssl_verify_client
option won’t be properly used. Furthermore the server will expect a
client certificate when this is set to “on”, though will not send any
accepted accepted DNs (only when it’s globally set it will work).
Should this mean that I have SNI disabled, how do I enable this? I use
a recent version of OpenSSL, I have compiled nginx with SNI support,
according to nginx -V, so what am I missing here?

Regards,
Luit van Drongelen [email protected]

Hello!

On Sat, Nov 06, 2010 at 01:18:11PM +0100, Luit van Drongelen wrote:

Should this mean that I have SNI disabled, how do I enable this? I use
a recent version of OpenSSL, I have compiled nginx with SNI support,
according to nginx -V, so what am I missing here?

ENOPARSE. Do you mean you already using SNI to distinguish
between different virtual hosts (with different certificates) on
the same ip:port, and it works for certificates, but not for
ssl_verify_client, right?

This make sense: it looks like OpenSSL only changes certificate on
SSL_set_SSL_CTX(). Seems to be OpenSSL problem - it should apply
all settings from new context, at least ones which weren’t
explicitly modified for the connection in question.

Attached patch implements workaround for the problem.

Maxim D.

2010/11/7 Maxim D. [email protected]:

This make sense: it looks like OpenSSL only changes certificate on
SSL_set_SSL_CTX(). Seems to be OpenSSL problem - it should apply
all settings from new context, at least ones which weren’t
explicitly modified for the connection in question.

Should have made it a little more clear in the first mail that
certificates switched fine but that setting didn’t in my situation.
This patch seems to fix all issues I have, thanks!

Regards,
Luit van Drongelen [email protected]