Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ERL-83: Certificate request exceeds TLS record length for long CA lists #3462

Closed
OTP-Maintainer opened this issue Jan 28, 2016 · 2 comments
Closed
Assignees
Labels
bug Issue is reported as a bug priority:medium team:PS Assigned to OTP team PS
Milestone

Comments

@OTP-Maintainer
Copy link

Original reporter: legoscia
Affected version: OTP-18.2.1
Fixed in version: OTP-18.3
Component: ssl
Migrated from: https://bugs.erlang.org/browse/ERL-83


When using the Erlang/OTP ssl application, a server that requires the client to present a certificate and has a very long list of trusted CAs sends a Certificate Request that exceeds the allowed length for a TLS record.

To reproduce this:

# Create a private key and a self-signed certificate for the server.
# Download a long list of CA certificates from http://curl.haxx.se/ca/cacert.pem.
# Compile the following module:
{code:erlang}
-module(long_ca_list).

-export([listen/0]).

listen() ->
    {ok, _} = application:ensure_all_started(ssl),
    Options = [{verify, verify_peer},
               {fail_if_no_peer_cert, true},
               {keyfile, "self-signed.key"},
               {certfile, "self-signed.crt"},
               {cacertfile, "cacert.pem"}],
    {ok, ListenSocket} = ssl:listen(1234, Options),
    {ok, NewSocket} = ssl:transport_accept(ListenSocket, infinity),
    ok = ssl:ssl_accept(NewSocket, 10000),
    ssl:send(NewSocket, "hello"),
    ssl:close(NewSocket).
{code}
# In an Erlang shell, run {{long_ca_list:listen()}}.
# From a terminal, connect to the server with:
{code:sh}
openssl s_client -connect localhost:1234 -debug
{code}

In the Erlang shell, observe the following output:
{noformat}
=ERROR REPORT==== 28-Jan-2016::16:54:44 ===
SSL: certify: ssl_alert.erl:93:Fatal error: record overflow
** exception error: no match of right hand side value 
                    {error,{tls_alert,"record overflow"}}
     in function  long_ca_list:listen/0 (long_ca_list.erl, line 14)
{noformat}

OpenSSL prints lots of things, but we're interested in this line:
{noformat}
140200477390496:error:1408F092:SSL routines:SSL3_GET_RECORD:data length too long:s3_pkt.c:510:
{noformat}

If you're capturing the traffic with Wireshark, you'll see the following packet:
{noformat}
Frame 12: 17082 bytes on wire (136656 bits), 17082 bytes captured (136656 bits) on interface 0
Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00)
Internet Protocol Version 4, Src: 127.0.0.1, Dst: 127.0.0.1
Transmission Control Protocol, Src Port: 1234 (1234), Dst Port: 44772 (44772), Seq: 1993, Ack: 296, Len: 17016
Secure Sockets Layer
    TLSv1.2 Record Layer: Handshake Protocol: Certificate Request
        Content Type: Handshake (22)
        Version: TLS 1.2 (0x0303)
        Length: 17011
        Handshake Protocol: Certificate Request
            Handshake Type: Certificate Request (13)
            Length: 17007
            Certificate types count: 3
            Certificate types (3 types)
            Signature Hash Algorithms Length: 24
            Signature Hash Algorithms (12 algorithms)
            Distinguished Names Length: 16975
            Distinguished Names (16975 bytes)
{noformat}
(see attached pcap file)


The length field is 17011, but according to [RFC 5246 section 6.2.1|https://tools.ietf.org/html/rfc5246#section-6.2.1], it must not exceed 16384:
{noformat}
   length
      The length (in bytes) of the following TLSPlaintext.fragment.  The
      length MUST NOT exceed 2^14.
{noformat}

I'm not sure what the correct solution is. For now, I've commented out the part of {{ssl_handshake:certificate_request}} that inserts the CA list, as in my application the client only has one certificate and thus doesn't need any hints as to which certificate to choose.
@OTP-Maintainer
Copy link
Author

ingela said:

This is a bug. I looked at the code and handshake packages are not fragmented on the record layer as they should be and as data packages are. I suppose the "normal" handshake packages are small enough so it has been unnoticed until now.  It will be fixed. 

@OTP-Maintainer
Copy link
Author

ingela said:

Solves the problem

--- a/lib/ssl/src/ssl_record.erl
+++ b/lib/ssl/src/ssl_record.erl
@@ -311,9 +311,19 @@ set_pending_cipher_state(#connection_states{pending_read = Read,
 %%
 %% Description: Encodes a handshake message to send on the ssl-socket.
 %%--------------------------------------------------------------------
-encode_handshake(Frag, Version, ConnectionStates) ->
-    encode_plain_text(?HANDSHAKE, Version, Frag, ConnectionStates).
-
+encode_handshake(Frag, Version, 
+		 #connection_states{current_write = 
+					#connection_state{
+					   security_parameters =
+					       #security_parameters{bulk_cipher_algorithm = BCA}}
} = 
+		     ConnectionStates) ->
+    case iolist_size(Frag) of
+	N  when N > ?MAX_PLAIN_TEXT_LENGTH ->
+	    Data = split_bin(iolist_to_binary(Frag), ?MAX_PLAIN_TEXT_LENGTH, Version, BCA),
+	    encode_iolist(?HANDSHAKE, Data, Version, ConnectionStates);
+	_  ->
+	    encode_plain_text(?HANDSHAKE, Version, Frag, ConnectionStates)
+    end.
 %%--------------------------------------------------------------------
 -spec encode_alert_record(#alert{}, ssl_version(), #connection_states{}) ->
 				 {iolist(), #connection_states{}}.

@OTP-Maintainer OTP-Maintainer added bug Issue is reported as a bug team:PS Assigned to OTP team PS priority:medium labels Feb 10, 2021
@OTP-Maintainer OTP-Maintainer added this to the OTP-18.3 milestone Feb 10, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Issue is reported as a bug priority:medium team:PS Assigned to OTP team PS
Projects
None yet
Development

No branches or pull requests

2 participants