[erlang-bugs] new_ssl [{verify,verify_peer}, {fail_if_no_peer_cert, true}] bug

Dan Gudmundsson dgud@REDACTED
Thu Aug 20 10:23:40 CEST 2009


That sounds correct to me.

I will fix that R13B02.

Thanks.

/Dan

Essien Essien wrote:
> Hi all,
> 
> I'm either missing something very major or there is a bug in the way
> the new_ssl implementation in R13B-2 handles a Client's
> CertificateMessages after it has indeed issued a CertificateRequest to
> the connecting client or rather the _absence_ of the
> CerfificateMessage
> 
> The rfc requires compliant clients to compulsorily return a
> CertificateMessage even if its a zero length on, once the server
> issues a CertificateRequest, but the rfc also says that it is up to
> the server to decide what to do if the client refuses to send its
> cert.
> 
> I believe then that the fail_if_no_peer_cert option is designed to
> control the server's behaviour when there is no client cert, but on
> closer inspection and testing, the erlang stack seems to ONLY properly
> fail if the clients sends it a CertificateMessage  of zero length.
> Normally this would not be a problem, but Mono 2.4-2 infact does just
> this. If Mono does not find a certificate to send back to the server
> in response to a CertificateRequest during the handshake, it simply
> does not send any CertificateMessage request at all, not even one with
> a zero length, hence clearly breaking the rfc.
> 
> This behaviour currently throws the erlang new_ssl implementation for
> a loop and the gen_fsm used by new_ssl just silently moves to the
> 'cipher' state, where it expects and processes a ClientKeyExchange
> message, effectively allowing the erring client to make it through.
> 
> 
> In summary, the only valid change from 'certify' to 'cipher' for a
> server should be:
> 
> 1. role = server, current_state = certify, verify = verify_peer,
> fail_if_no_peer_cert = false, message = client_key_exchange:
>           next_state = cipher
> 
> 2. role = server, current_state = certify, verify = verify_peer,
> fail_if_no_peer_cert = false, message = certificate
>           next_state = cipher
> 
> 
> 3. role = server, current_state = certify, verify = verify_peer,
> fail_if_no_peer_cert = true, message = certificate{length > 0}
>           next_state = cipher
> 
> while the following states should produce an error:
> 
> 4. role = server, current_state = certify, verify = verify_peer,
> fail_if_no_peer_cert = true, message = client_key_exchange:
>           next_state = ERROR
> 
> 5. role = server, current_state = certify, verify = verify_peer,
> fail_if_no_peer_cert = true, message = certificate{length = 0}
>           next_state = ERROR
> 
> 
> Of all the rules above, only rule 4 is not handled by new_ssl in
> R13B-2 and the following patch (which is just a quick and dirty proof
> of concept) properly kills the connection if the client in the event
> that rule 4 occurs.
> 
> <patch>
> 
> --- /usr/lib/erlang/lib/ssl-3.10.1/src/ssl_connection.erl	2009-04-27
> 07:05:47.000000000 +0100
> +++ ssl-3.10.1/src/ssl_connection.erl	2009-08-07 13:09:02.142360183 +0100
> @@ -477,6 +477,11 @@
>  	    {stop, normal, State0}
>      end;
> 
> +certify(#client_key_exchange{}, State =
> +        #state{role = server, ssl_options = #ssl_options{verify = verify_peer,
> +                fail_if_no_peer_cert = true}}) ->
> +    {stop, normal, State};
> +
>  certify(#client_key_exchange{exchange_keys
>  			     = #encrypted_premaster_secret{premaster_secret
>  							   = EncPMS}},
> 
> 
> </patch>
> 
> ________________________________________________________________
> erlang-bugs mailing list. See http://www.erlang.org/faq.html
> erlang-bugs (at) erlang.org
> 


More information about the erlang-bugs mailing list