TLS handshake wrapper


Hi All,

I was looking at the SQL/TDS driver and noticed that it doesn’t support TLS. That got me thinking: I wonder how hard it would be to add TLS…

Definitely harder than I thought…

After looking through the TDS specification, I see that the TLS handshake works differently than in most protocols. The client first has to reach out with a normal TDS “client hello” packet. Then the server responds with a TDS “server hello” packet, and then if they agree that they should use encryption, the TLS handshake starts. However, all TLS handshake packets are encapsulated in TDS packets.

However, the erlang :ssl module doesn’t seem like it’s designed to work this way. It wants to own the tcp port and directly send the TLS handshake packets without giving anybody an opportunity to wrap them.

Does anybody have thoughts on the best way to make this work without writing a custom TLS implementation?


Oops, misread the question, let’s try again…

You can specify a custom transport module, to replace :gen_tcp, by passing in the cb_info option, described under ‘transport_option’ in the docs. It should specify the name of a module that behaves much like :gen_tcp, and the message tags that :ssl can expect to receive in active mode.


Hi @voltone,

Thanks for the reply. That was my first thought, but I was discouraged by the data types in the docs which make it seem like the cb_info option can only be specified when creating a new connection, not when passing an existing socket to ssl.

However, after reviewing the code it looks like the option is supported and should work great. Does this look like a docs issue or am I reading them wrong?


The way the transport_option() type is singled out and excluded for upgrade calls suggest that this was deliberate. So that would make this an undocumented feature.

If you prefer you could also call the connect(host, port, options) variant, but instead of a hostname pass in a handle for your existing connection, such as a PID or a struct with the necessary information. :ssl does not interpret the Host and Port parameters, it just passes them along to the connect function in your transport callback module. This function would simply return {:ok, handle} back to :ssl.