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 · 2 comments
Open

crypto/tls: safely shutdown #29462

kazzmir opened this issue Dec 29, 2018 · 2 comments
Labels
NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone

Comments

@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
Copy link
Contributor

/cc @FiloSottile

@katiehockman katiehockman added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Jan 2, 2019
@katiehockman katiehockman added this to the Unplanned milestone Jan 2, 2019
@noxxi
Copy link

noxxi commented Feb 21, 2022

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.

That kind of functionality is needed to implement the CCC command in FTP TLS, see RFC 4217 section 5. So it is maybe not that strange.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
Development

No branches or pull requests

3 participants