[erlang-questions] ssl certificate verification in httpc
Camille Troillard
lists@REDACTED
Thu Jul 17 13:20:02 CEST 2014
Hello Ivan,
I have the same issue, here is what I came up to. This may not be correct and I would be very happy to discuss the issues anyone may find. My goal is to check the server certificate is valid using verify_peer, and also implement a check on the server hostname I connect to.
Here are the SSL options I use:
% I know the certificate used by the server requires a depth of 2, you may not need this option in your code.
{ssl, [
{cacertfile, cacert_path()},
{depth, 2},
{verify_fun, ssl_verify_fun(?SERVER_HOSTNAME)},
{verify, verify_peer}
]}
And the verify fun:
ssl_verify_fun(Hostname) ->
{
fun (_, {bad_cert, _} = Reason, _) ->
{fail, Reason};
(_, {extension, _}, UserState) ->
{unknown, UserState};
(_, valid, UserState) ->
{valid, UserState};
(Cert, valid_peer, UserState) ->
TBSCert = Cert#'OTPCertificate'.tbsCertificate,
Extensions = TBSCert#'OTPTBSCertificate'.extensions,
case lists:keysearch(?'id-ce-subjectAltName', #'Extension'.extnID, Extensions) of
{value, #'Extension'{extnValue = [{dNSName, Hostname}]}} ->
{valid, UserState};
false ->
{fail, invalid_certificate_hostname}
end
end,
[]
}.
As you can see, I verify the host name matches the one I am connecting to.
Best,
Camille
On 17 Jul 2014, at 11:30, Ivan Uemlianin <ivan@REDACTED> wrote:
> Dear Roger
>
> Thank you for your comments.
>
> Your comments take us back to my initial question:
>
> > In short, what am I missing to be able to verify this certificate?
>
> Just providing the CA certificate doesn't seem to be enough:
>
> > ...
>> SSLOpts = [{verify, verify_peer},
>> {cacertfile,"certificates.crt"}],
>> httpc:request(get, {Url, []}, [{ssl,SSLOpts}], []).
>>
>> But this returns an unknown ca error:
>>
>> {error,{failed_connect,[{to_address,{"bla.org", 443}},
>> {inet,[inet],{tls_alert,"unknown ca"}}]}}
>> 11:06:04.942 [error] SSL: certify: ssl_handshake.erl:1344:
> > Fatal error: unknown ca
>
> None of the other ssl options in the erlang ssl documentation look likely, and I have found no examples of verifying an ssl certification from erlang on the web.
>
> - are any of the other ssl options relevant here? Are there other undocumented ssl options?
>
> - failing that, it looks like I need to write a verify_fun and access parts of the OTPCertificate and Extension records. Is that correct, or is more required?
>
> - I have scoured the usual sources on the web but found nothing. If anyone knows of relevant work in this area please let me know.
>
> Thanks
>
> Ivan
>
>
> On 17/07/2014 08:08, Roger Lipscombe wrote:
>> SSL encryption is done by the client creating a session key, and using
>> the server's public key (from the server's certificate) to securely
>> send it to the server. If you don't verify the server certificate, you
>> have no way of knowing whether you're subject to a man-in-the-middle
>> attack, where the attacker can give you a fake certificate, extract
>> the session key, read/manipulate all your traffic, and then
>> (optionally) send it to the real server.
>>
>> Encryption is only half of the story. SSL also aims to guarantee safe
>> key exchange, but to do that, you need to verify the server
>> certificate. This means verifying that the names match, that it's
>> trusted (or issued by a trusted CA), and that it hasn't expired, been
>> revoked, etc.
>>
>> And there's more than one way (also including DNS spoofing) to
>> intercept the traffic: transparent proxies, pwned WiFi router, etc..
>>
>> On 15 July 2014 15:41, Camille Troillard <lists@REDACTED> wrote:
>>> Hi Robert,
>>>
>>>> SSL essentially does two things at once: encrypts the data and checks if client and/or server are who they say they are. The latter is where certificate verification comes into play, the encryption part is always done and usually automatically negotiated between client and server.
>>>>
>>>> So, if all you are aiming for is encrypting the data travelling between client and server, then you don't need the ssl option. Just point your httpc:request at an "https://..." URL and the encryption is handled for you without you having to do anything more.
>>>
>>> I think this works only if you trust your DNS, otherwise you have to check that the certificate matches the host.
>>> Please correct me if I’m wrong.
>>>
>>> Cam
>>>
>>>
>>> _______________________________________________
>>> erlang-questions mailing list
>>> erlang-questions@REDACTED
>>> http://erlang.org/mailman/listinfo/erlang-questions
>> _______________________________________________
>> erlang-questions mailing list
>> erlang-questions@REDACTED
>> http://erlang.org/mailman/listinfo/erlang-questions
>>
>
> --
> ============================================================
> Ivan A. Uemlianin PhD
> Llaisdy
> Speech Technology Research and Development
>
> ivan@REDACTED
> www.llaisdy.com
> llaisdy.wordpress.com
> github.com/llaisdy
> www.linkedin.com/in/ivanuemlianin
>
> festina lente
> ============================================================
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://erlang.org/mailman/listinfo/erlang-questions
More information about the erlang-questions
mailing list