[erlang-questions] bad certificate if trying to verify StartSsl certificate
Ben Murphy
benmmurphy@REDACTED
Sun Sep 13 23:22:25 CEST 2015
Just a note that this verify function is broken and accepts all self
signed certificates. :(
On Thu, Sep 10, 2015 at 11:44 AM, Ben Murphy <benmmurphy@REDACTED> wrote:
> I have a verify function that hacks around this problem. It adds the
> certs to a list during the 'verification' then it resorts and passes
> it off to the path validation. However, this function only supports
> validation from a single root cert because we are using it in
> production to connect to a server that has a chain signed by a
> non-public CA. You use it like: {verify_fun,
> fixed_root_lenient_verifier:create_verify_function(DerCaCert, 10)}
>
> Use this module at your own risk it may effectively disable your SSL
> security. I really think this resorting should be done in OTP or OTP
> should supply a cleaner hook for resorting. A hook that gives you the
> chain and the cacerts and lets you send back a new chain would be
> perfect :)
>
> -module(fixed_root_lenient_verifier).
>
> -record(state, {certs = [], root_cert, max_path_length}).
>
> -export([verify/3]).
> -export([create_verify_function/2]).
>
> create_verify_function(DerCertificate, MaxPathLength) ->
> DecodedCert = public_key:pkix_decode_cert(DerCertificate, otp),
> {fun fixed_root_lenient_verifier:verify/3, #state{root_cert =
> DecodedCert, max_path_length = MaxPathLength}}.
>
> append_cert(State, Cert) ->
> State#state{certs = [Cert | State#state.certs]}.
>
> default_verify(_Cert, Event, State) ->
> case Event of
> {bad_cert, Reason} -> {fail, Reason};
> {extension, _} -> {unknown, State};
> valid -> {valid, State};
> valid_peer -> {valid, State}
> end.
>
>
> verify(Cert, Event, State) ->
> case Event of
> {bad_cert, _Reason} ->
> {valid, append_cert(State, Cert)};
> {extension, _} -> {unknown, State};
> valid -> {valid, append_cert(State, Cert)};
> valid_peer ->
> case final_verification(State#state.certs, Cert,
> State#state.max_path_length, State#state.root_cert) of
> {ok, _} -> {valid, State};
> {error, Reason} -> {fail, Reason}
> end
> end.
>
> final_verification(Certs, PeerCert, MaxPathLength, RootCertificate) ->
> Chain = fix_path(PeerCert, Certs),
> public_key:pkix_path_validation(RootCertificate, Chain,
> [{max_path_length, MaxPathLength}, {verify_fun, {fun default_verify/3,
> none}}]).
>
>
> fix_path(Peer, RestOfChain) ->
> make_chain(Peer, RestOfChain, []).
>
> make_chain(OtpCert, CertChain, ResultChain) ->
> case public_key:pkix_is_self_signed(OtpCert) of
> true ->
> [OtpCert | ResultChain ];
> false ->
> case find_issuer(OtpCert, CertChain) of
> {ok, NewCert, NewCertChain} ->
> % we remove the cert that was found from the chain
> % to prevent infinite loops where a chain becomes
> % a loop
> make_chain(NewCert, NewCertChain, [OtpCert | ResultChain]);
> {error, issuer_not_found} ->
> % assume it is the 'trusted' certificate
> [OtpCert | ResultChain]
> end
> end.
>
> find_issuer(OtpCert, CertChain) ->
> {Not, Maybe} = lists:splitwith(fun(Candidate) ->
> not public_key:pkix_is_issuer(OtpCert, Candidate)
> end, CertChain),
>
> case Maybe of
> [Issuer | Rest] ->
> {ok, Issuer, Not ++ Rest};
> [] ->
> {error, issuer_not_found}
> end.
>
> On Thu, Sep 10, 2015 at 10:02 AM, Benoit Chesneau <bchesneau@REDACTED> wrote:
>> I
>> On Tue, Aug 11, 2015 at 9:54 AM Ingela Andin <ingela.andin@REDACTED> wrote:
>>>
>>> Hi!
>>>
>>> 2015-07-16 11:16 GMT+02:00 Alex Hudich <alttagil@REDACTED>:
>>>>
>>>> Hi!
>>>>
>>>>
>>>>
>>>> wget http://curl.haxx.se/ca/cacert.pem
>>>>
>>>> and then
>>>>
>>>> ssl:connect( "www.nicemine.ru", 443,
>>>> [{verify,verify_peer},{server_name_indication,"www.nicemine.ru"},{depth,2},{cacertfile,"cacert.pem"}]
>>>> ).
>>>>
>>>> gives me {error,{tls_alert,"bad certificate"}}
>>>>
>>>>
>>>>
>>>
>>> This site is not sending a correct certificate chain, I get all the
>>> certificates that shall be in the chain but scrambled around and not in the
>>> correct order, this is breaking the
>>> SSL/TLS-protocol. OpenSSL will also get the error above when trying to
>>> verify that chain, but later versions of OpenSSL and also other
>>> implementations obviously tries to work around this by attempting to sort
>>> them and run the validation again.
>>>
>>> You could do that too using the verify_fun if you really want to. We would
>>> rather not make that a default feature as breaking security protocols is
>>> usually a bad idea that could lead to vulnerabilities.
>>>
>>>
>>> Regards Ingela Erlang/OTP Team - Ericsson AB
>>>
>>
>>
>> I have the same issue on another host: rest-api.pay.nl:
>>
>> 15> ssl:connect( "rest-api.pay.nl", 443,
>> [{verify,verify_peer},{server_name_indication,"rest-api.pay.nl"},{depth,2},{cacertfile,
>> "priv/ca-bundle.crt"}] ).
>>
>> =ERROR REPORT==== 10-Sep-2015::11:01:31 ===
>> SSL: certify: ssl_handshake.erl:1476:Fatal error: bad certificate
>> {error,{tls_alert,"bad certificate"}}
>>
>>
>> the chain looks correct for me and curl handle it without issue. What do you
>> mean by sorting certificates ? Any example?
>>
>> - benoit
>>
>>
>>
>>>
>>>
>>>>
>>>> Why? Site can be opened ok in the browser.
>>>>
>>>> Erlang/OTP 17 [erts-6.3]
>>>>
>>>>
>>>> _______________________________________________
>>>> 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
>>
>>
>> _______________________________________________
>> erlang-questions mailing list
>> erlang-questions@REDACTED
>> http://erlang.org/mailman/listinfo/erlang-questions
>>
More information about the erlang-questions
mailing list