[erlang-questions] Erlang SSL and Invalid Certificate Chains

Dmitry Kolesnikov dmkolesnikov@REDACTED
Mon Aug 11 16:22:18 CEST 2014


Hello,

Have you tried to bypass an issue with custom verify_fun ?

- Dmitry


On 11 Aug 2014, at 17:16, Ben Murphy <benmmurphy@REDACTED> wrote:

> (I originally sent this to erlang-bugs but it doesn't look like it
> made it there)
> 
> We have a problem where an SSL server sends back a certificate chain
> that is invalid according to the TLS 1.2 specification and erlang
> rejects this chain with an unknown ca error. However, openssl and
> browsers will accept this chain because they are less strict about
> validation.
> 
> The chain looks something like:
> 
> 0. Server Cert issued by Intermediate Cert
> 1. Intermediate Cert issued by Root Cert
> 2. Root Cert issued by Root Cert
> 3. Unrelated certificate
> 4. Unrelated certificate
> 
> Which is invalid according to: http://www.ietf.org/rfc/rfc5246.txt
> 
>   certificate_list
>      This is a sequence (chain) of certificates.  The sender's
>      certificate MUST come first in the list.  Each following
>      certificate MUST directly certify the one preceding it.  Because
>      certificate validation requires that root keys be distributed
>      independently, the self-signed certificate that specifies the root
>      certificate authority MAY be omitted from the chain, under the
>      assumption that the remote end must already possess it in order to
>      validate it in any case
> 
> Looking at the openssl code they start at the beginning of the chain
> then recursively find the issuer in order to build up a chain. While
> the erlang ssl code assumes the last certificate in the chain is the
> root CA (ssl_certificate:trusted_cert_and_path).
> 
> Maybe this is more of a feature request than a bug. But I was
> wondering if it would be possible for erlang to either accept these
> dodgy chains, provide an option when connecting to accept these dodgy
> chains or allow users to supply a function to modify the certificate
> chain before validation takes place.
> 
> I have some code that I've been mucking around with to fix up chains
> but I haven't done thorough testing of it.
> 
> fix_path(CertChain) ->
>  DecodedCerts = [ {public_key:pkix_decode_cert(Cert, otp), Cert} ||
> Cert <- CertChain ],
>  [Peer | RestOfChain] = DecodedCerts,
>  lists:reverse(make_chain(Peer, RestOfChain, [])).
> 
> make_chain({OtpCert, Cert}, CertChain, ResultChain) ->
>  case public_key:pkix_is_self_signed(OtpCert) of
>    true ->
>      [Cert | 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, [Cert | ResultChain]);
>          {error, issuer_not_found} ->
>            % assume it is the 'trusted' certificate
>            [Cert | 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.
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://erlang.org/mailman/listinfo/erlang-questions




More information about the erlang-questions mailing list