Closed frioux closed 9 years ago
Client certificates work this way too. If you look with wireshark or at the traffic or use openssl s_server ...
you will see, that it sends not only the leaf certificate but also the chain certificates, the same way as the server does send its certificate and chain.
But there seem to be some strange things going on with doing the verification of the client certificate containing a chain, which I can see with openssl s_server
too.
I think you misunderstand me; I'm not saying you shouldn't need a chain at all. The problem is that for client certs, the library must figure out the chain by looking at the client cert and the certificate store. I want to give it a signle file with all the certificates concatenated, like you can with a server.
If you give IO::Socket::SSL a single file with SSL_cert_file
and this file contains multiple certificates, then it will use the first one as the leaf certificate and the rest as chain certificates. That means all of these certificates will be transferred to the peer within the SSL handshake. This works not only for server side certificates but also for client side certificates.
If you still think I misunderstood you then I would suggest that you create some example code to show which behavior you see and which behavior you expect. Please make sure to make clear which version of IO::Socket::SSL, Net::SSLeay and OpenSSL you used with your example code.
Huh! Ok I did not find that to be the case, I'll be make a demo. Thanks
sent from a rotary phone, pardon my brevity On Jan 16, 2015 12:52 AM, "Steffen Ullrich" notifications@github.com wrote:
If you give IO::Socket::SSL a single file with SSL_ca_file and this file contains multiple certificates, then it will use the first one as the leaf certificate and the rest as chain certificates. That means all of these certificates will be transferred to the peer within the SSL handshake. This works not only for server side certificates but also for client side certificates.
If you still think I misunderstood you then I would suggest that you create some example code to show which behavior you see and which behavior you expect. Please make sure to make clear which version of IO::Socket::SSL, Net::SSLeay and OpenSSL you used with your example code.
— Reply to this email directly or view it on GitHub https://github.com/noxxi/p5-io-socket-ssl/issues/24#issuecomment-70215227 .
But there seem to be some strange things going on with doing the verification of the client certificate containing a chain, which I can see with openssl s_server too.
These problems vanish and verification succeeds once the client certificate has the valid purpose to be used as a client certificate, that is NetscapeCertType must be client.
Ugh, I can't seem to get my example to work because I can't get my server to require a client cert! Shouldn't SSL_verify_mode => SSL_VERIFY_PEER
be all that's required, on the server side, to force the client to send a cert?
Yes, that's all what is needed and it works for me.
Yeah I believe it. Something else weird is going on over here. Don't worry too much about this; I suspect my environment is messed up since the way you say it should work is what I want anyway. I'll get something that shows... something at some point :)
You might have a look at https://github.com/noxxi/p5-io-socket-ssl/tree/issue-24/stuff to get sample code and certificates.
Ok, this is a step in the right direction I guess. I took your example and made a couple small changes to it. Check out the client-validation
branch from https://github.com/frioux/TLS-eg. If you run make it will generate all the certs for you. If you run miniserver.pl
and then just do curl -k https://localhost:8443
you'll note that you do indeed get a response, despite the fact that peer validation is enabled. I have the latest IO::Socket::SSL installed; my OpenSSL is 1.0.1f. Can you reproduce this?
With the option SSL_VERIFY_PEER
which you used in your example the server only asks the client for a certifcate and it will fail if a client sent a certificate which could not be verified. But the client might still omit the certificate and the connection will succeed. Only with SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT
it will also fail if the client did not send a certificate at all.
Ohhh, sorry that I missed that. Thanks for your help so far!
ok well, I now have code that works well and works the way I want. I suspect the whole time I was just missing the SSL_VERIFY_FAIL_IF_NO_PEER_CERT
. Thanks again and sorry for the noise!
Server certificate files can (and arguably should!) be a single file with the chain of certificates concatenated all the way down to the root certificate. This is efficient and simple.
Unfortunately, client certificates do not work this way, and will only read the first certificate in a file and will only build the cert to the root cert, requiring the user to have all of the certificates that the client cert is based on (ie all the certs in the chain) in the CA store of the client.
For simplicity's sake I'd rather only store my root CA in my CA store, and have the client and server both just have chainfiles instead of single pem files. I suspect that the reason this works this way is that it's how OpenSSL works by default, as
s_client
from openssl acts the same way. But curl, which uses openssl on my system, allows the user to set client cert file which is a chainfile, so I suspect it's doable, just a bit of work.I can try my hand at figuring this out, but I am mostly a pure-perl dev and don't know much about the guts of OpenSSL, XS, and other weird stuff like that. If I were to do this I'd see how curl is doing it.