Skip to content

Resume the control session on the data connection - #82

Open
christhomas wants to merge 1 commit into
secsy:masterfrom
antimatter-studios:cth/tls-session-reuse-upstream
Open

Resume the control session on the data connection#82
christhomas wants to merge 1 commit into
secsy:masterfrom
antimatter-studios:cth/tls-session-reuse-upstream

Conversation

@christhomas

Copy link
Copy Markdown

Fixes #49.

Servers commonly require the data connection to resume the control connection's TLS session — it is proftpd's default and vsftpd's require_ssl_reuse — and refuse one that has not:

425-Unable to build data connection: Operation not permitted
522-SSL connection failed; session reuse required

Why ClientSessionCache alone did nothing

You suggested it in the thread, and @wackerm and @mickael-kerjean both reported it changed nothing. They were right, and here is why.

Two conditions have to hold for crypto/tls to resume, and the cache is only one:

  1. there must be a cache;
  2. the cache key has to match — and when ServerName is empty, crypto/tls keys the cache by address, which includes the port. The data connection is on a different port, so it never finds the control connection's session. Resumption simply does not happen, and nothing reports that it didn't.

Setting ServerName to the host makes both channels agree on one key. That is the missing half.

So: one cache per client, shared by every connection it opens, and ServerName defaulted to the host when the caller has not set one.

What it does not do

The caller's tls.Config is cloned, not modified — it is theirs and may be shared with connections this package knows nothing about — and a cache they supplied is used rather than replaced. Both are tested.

InsecureSkipVerify is carried across explicitly, so naming the server for a cache key does not quietly start verifying a certificate the caller did not ask to have verified.

On the two resumption mechanisms

@wackerm's analysis in the thread is correct: session IDs are what older proftpd and vsftpd use, and Go's client does not implement them — only session tickets. This fixes the ticket path, which modern builds of both support. A server old enough to offer only session IDs still cannot be resumed against, and that is a crypto/tls limitation rather than one this package can route around.

Verified against proftpd 1.3.8 configured to require reuse, which is its default. My test config had TLSOptions NoSessionReuseRequired — the workaround from the issue — and removing it reproduced the reported error exactly; the tests pass with it removed.

The server-config half of that lives in #73, so this branch carries only the library change. Same note as my other PRs: off master, so TestMain still needs ./build_test_server.sh.

Fixes secsy#49.

Servers commonly require the data connection to resume the control
connection's TLS session. It is proftpd's default and vsftpd's
require_ssl_reuse, and a data connection that has not resumed is refused:

    425-Unable to build data connection: Operation not permitted
    522-SSL connection failed; session reuse required

Two things have to be true for crypto/tls to resume, and the advice in
the issue — set ClientSessionCache — supplies only the first. That is why
several people tried it and reported no change.

The second is that the cache key has to match. With ServerName empty,
crypto/tls keys the cache by *address*, and the address includes the
port. The data connection is on a different port, so it never finds the
control connection's session; resumption simply does not happen, and
nothing says so. Setting ServerName to the host makes both channels agree
on one key.

So: one cache per client, shared by every connection it opens, and a
ServerName defaulted to the host when the caller has not set one.

The caller's tls.Config is cloned rather than modified — it is theirs and
may be shared with connections this package knows nothing about — and a
cache they supplied is used rather than replaced. Both are tested.
InsecureSkipVerify is carried across explicitly, so naming the server for
the cache key does not start verifying a certificate the caller did not
ask to have verified.

test-servers/proftpd.conf carried TLSOptions NoSessionReuseRequired,
which is exactly the workaround the reporter found. With it, the suite
was passing against a configuration almost nobody runs, and this bug was
invisible.

It is gone. Removing it turned TestExplicitTLS and TestStoreEmptyFileOverTLS
red with the reported error, which is how this was reproduced; both pass
now. Full suite green three consecutive runs against the stricter server.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Failing data connection with STARTTLS (Explicit TLS): tls session not reused

1 participant