Thread

Posted on Tue Jun 12 17:16:43 2007 by christopherodenbach
Checking of hostname missing

Hi,

I recently discovered, that IO::Socket::SSL does not verify the hostname in the certificate to the one it connects to.

I found out about this when fiddeling with Net::LDAP. Even with 'verify=require' the hostname was not checked (the certificate was of course).

Now it is of course possible to make Net::LDAP check the hostname itself (after having IO::Socket::SSL check the certificate), but that is quite a long and difficult task: there are certificates with wildcards, with IP addresses, with subjectAltNames and so on. I have nearly done it now for Net::LDAP, but there are plenty of other perl modules which use IO::Socket::SSL which all would need the hostname checking implemented.

Wouldn't it make more sense to put the neccessary code into IO::Socket::SSL itself?

Cheers,

Christopher

Direct Responses: 5422 | Write a response
Posted on Tue Jun 12 19:00:14 2007 by noxxi in response to 5413
Re: Checking of hostname missing

IO::Socket::SSL just checks if the certificate is valid at the SSL layer, e.g. that the certificate has a valid signature from a known CA. Interpretation and constrains on the CN of the certificate are specified at the application layer and depend on the protocol used. That's why it is specified in rfc4513 how the CN in the certificate should be checked for LDAP, in rfc2818 for HTTPS etc.

For instance rfc2818 states in 3.1 "If the client has external information as to the expected identity of the server, the hostname check MAY be omitted.".

So this is not an issue which IO::Socket::SSL, it's an issue with Net::LDAPS which should conform to RFC4513. It might do it using the verify_callback of IO::Socket::SSL

Direct Responses: 5431 | Write a response
Posted on Wed Jun 13 12:27:53 2007 by christopherodenbach in response to 5422
Re: Checking of hostname missing

Hi,

I tried to use the verify_callback, but the callback seems to be called for every part of the complete certificate chain, not only for the server certificate. It also gets too few parameters.

Even if every application has to implement its own hostname checks, wouldn't it be good to have common checks like hostname with or without wildcards, IP addresses etc. in a central place? Should that be IO::Socket::SSL or Net::SSLeay? It does not make much sense to me that every application should implement all the messy certificate handling again and again.

Christopher

Direct Responses: 5432 | Write a response
Posted on Wed Jun 13 12:52:27 2007 by noxxi in response to 5431
Re: Checking of hostname missing

The problem is, that there is no standard for checking the hostname in the certificate. RFC4513 (LDAP) specifies, that the hostname should be checked against subjectAltName and that wildcards can be only left-most. But RFC2818 (https) allows checking against the CN (with subjectAltName preferred) while allowing also wildcars like f*.com (which is insane in my opinion, but see rfc2818, section 3.1).

So if there would be a common rule it would definitly make sense to implement it on the transport layer (either IO::Socket::SSL or Net::SSLeay), but unfortunatly there is no common rule.

That doesn't mean that it wouldn't be useful to have kind of 'best-practices' by implementing the system desribed in rfc4513 for LDAP and rfc2595 for imap,pop,... . Both systems seems to mean the same thing, even if the description is different

As for the verify_callback: It is is called on every part of the chain to give you the opportunity to either stop the verification of the whole chain even if openssl thinks it is valid or to accept this part and continue with the verification even if openssl considered the part invalid.
What kind of parameters you need within the callback which don't get provided?

Direct Responses: 5433 | Write a response
Posted on Wed Jun 13 14:16:47 2007 by christopherodenbach in response to 5432
Re: Checking of hostname missing

Hi,

alright, there is no common rule, but a few quite common rules (call it best practice). It would really be good to have them somewhere in a common library.

For the callback: How can I find out for which part of the certificate chain the callback is called? If I only want to verify the actual server certificate? How do I work with this c-style certificate store? Maybe it is enough, but maybe not.

Christopher

Direct Responses: 5441 | Write a response
Posted on Thu Jun 14 09:10:47 2007 by noxxi in response to 5433
Re: Checking of hostname missing

Yes I think it would be good to have something like this either in IO::Socket::SSL or Net::SSLeay.

But currently I see only one module (Crypt::X509) which gives you access to the subjAltName extension of the certificate. And unfortunatly this module needs to get the certificate from a file, a design which doesn't really fit into the design of IO::Socket::SSL, e.g. it would be necessary to use a tempfile which is not an option I like, given that openssl provides all the necessary function, only that they are not available through Net::SSLeay.

I think the best way would be to add functionality to Net::SSLeay so that subjAltName could be extracted and the checked within IO::Socket::SSL. Checking the CN only is not enough, for instance signin.ebay.DE send a certificate for signin.ebay.COM and signin.ebay.DE is only mentioned within the subjAltName.

As for the callback: I don't think it's easy to get info which part of the chain is currently checked. So if you just want to check the top most certificate it could be easier to don't use the verify_callback but check against the infos you get from $socket->peer_certificate after the builtin verification succeeded (e.g. the SSL connection is set up).

Write a response