Handshake the data connection, so an empty transfer over TLS works - #79
Open
christhomas wants to merge 1 commit into
Open
Handshake the data connection, so an empty transfer over TLS works#79christhomas wants to merge 1 commit into
christhomas wants to merge 1 commit into
Conversation
Fixes secsy#63. crypto/tls handshakes lazily, on the first Read or Write. A transfer that moves no bytes never triggers one, so the server is handed a plain TCP connection that opens and closes without ever speaking TLS. It rejects that and drops the control connection, and the caller sees: error reading response: EOF from a store that was otherwise perfectly valid. Storing an empty file over TLS is the case that hits it, which is exactly what was reported against vsftpd — and reproduces here against pure-ftpd, while the same store without TLS succeeds. The handshake is now explicit. Where it goes matters more than that it happens: it has to be in the getter prepareDataConn returns, not beside the tls.Client call. prepareDataConn runs before the transfer command is sent. The server does not begin the data channel's handshake until it has that command, so handshaking at connection time waits for a server that is itself waiting for us — the first attempt at this deadlocked, which is presumably why the handshake was left implicit in the first place. The getter runs after the command has been sent and acknowledged, which is the first moment the handshake can complete. Also fixes proftpd answering "425 Unable to build data connection" to the same operation, which had looked like a separate problem. Red before green: both test servers failed an empty TLS store and passed the same store without TLS. Full suite green three consecutive runs, which matters here because this changes every TLS transfer and not only the empty one.
Open
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #63.
crypto/tlshandshakes lazily, on the first Read or Write. A transfer that moves no bytes never triggers one, so the server is handed a plain TCP connection that opens and closes without ever speaking TLS. It rejects that and drops the control connection, and the caller sees:from a store that was otherwise perfectly valid.
@ior308 reported this against vsftpd, and noted the same store without TLS worked. It reproduces here against pure-ftpd, with exactly that asymmetry.
Where the handshake goes matters more than that it happens
My first attempt put it beside the
tls.Clientcall inprepareDataConnand deadlocked. That function runs before the transfer command is sent, and the server does not begin the data channel's handshake until it has the command — so handshaking there waits for a server that is itself waiting for us. I assume that is why it was left implicit.It belongs in the getter
prepareDataConnreturns, which runs after the command has been sent and acknowledged. That is the first moment it can complete.An unexpected second fix
proftpd answered
425 Unable to build data connection: Operation not permittedto the same operation, which had looked like an unrelated server or config problem. The eager handshake fixes that too — it was the same cause seen from the other end.Tests
empty_store_test.go— an empty store over TLS and the same without, so a failure distinguishes "TLS" from "empty". Confirmed red before the fix.Full suite green three consecutive runs, which matters here: this changes every TLS transfer, not only the empty one.
One note on running them: this branch is off
master, soTestMainstill requires./build_test_server.sh. I verified via the container harness in #73.