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

crypto/tls: safely shutdown #29462

Open
kazzmir opened this Issue Dec 29, 2018 · 1 comment

Comments

Projects
None yet
2 participants
@kazzmir
Copy link

kazzmir commented Dec 29, 2018

$ go version
go version go1.11.2 linux/amd64

Does this issue reproduce with the latest release?

Yes

Safely and reliably shutting down an SSL transport while keeping the underlying connection still open is not supported by the API in an intuitive way. I have posted this question on stackoverflow here: https://stackoverflow.com/questions/53825725/how-to-safely-shutdown-ssl-connection

But to repeat the question:

Using Go, how can a tls.Conn be safely shutdown without entirely closing the underlying connection? I have a working solution, but I am not sure if there is a better way.

In my application I have a non-SSL connection that is eventually 'upgraded' to an SSL connection. Then at some point the SSL connection should be closed cleanly, and the connection should return to the non-SSL version (where unencrypted traffic can be sent between the two parties).

import "crypto/tls"
func app(connection net.Conn){
   // process some data on the connection, then eventually change it to SSL
   ssl = tls.Client(connection, sslConfig) // sslConfig defined elsewhere
   ssl.Handshake()
   // process data using ssl for a while
   // now shut down SSL but maintin the original connection
   ssl.CloseWrite()
   // at this point we have sent a closeNotify alert to the remote side and are expecting a closeNotify be sent back to us.
   // the only way to read the closeNotify is to attempt to read 1 byte
   b := make([]byte, 1)
   ssl.Read(b)
   // assuming the remote side shut down the connection properly, the SSL transport should be finished

   connection.Read(...) // can go back to the unencrypted connection
}

This works because if a closeNotify alert record is received then c.readRecord in crypto/tls/conn.go will return an error value, and will not read any bytes (so presumably the b byte array could have been any size).

This is a bit confusing from a user's point of view. It would be preferable to have an API like ssl.Shutdown() that internally maybe does

   c.CloseWrite()
   b := make([]byte, 1)
   c.Read(b)

Or maybe there is a better way to cleanly shutdown, but that is for the library writer's to decide.

I realize it is a bit strange to want to shutdown an SSL transport and continue to use the underlying connection but that is the constraint I am working under.

If it is helpful I can provide a small working example.

@katiehockman

This comment has been minimized.

Copy link
Contributor

katiehockman commented Jan 2, 2019

@katiehockman katiehockman added this to the Unplanned milestone Jan 2, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.