[erlang-questions] ssl certificate verification in httpc
Ivan Uemlianin
ivan@REDACTED
Thu Jul 17 16:29:23 CEST 2014
Dear Cammille
Thanks for your help. However, I'm still failing at bad_cert (unknown
ca). It seems to be finding the cacertfile ok. ...
I guess there's no alternative but to go in.
If/when I get it working I'll report back.
Best wishes
Ivan
On 17/07/2014 12:20, Camille Troillard wrote:
> 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
>
--
============================================================
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
============================================================
More information about the erlang-questions
mailing list