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: add Dialer with Dial, DialContext methods #18482

Closed
akalin-keybase opened this issue Dec 31, 2016 · 23 comments
Closed

crypto/tls: add Dialer with Dial, DialContext methods #18482

akalin-keybase opened this issue Dec 31, 2016 · 23 comments
Labels
FeatureRequest FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done. Proposal-Accepted
Milestone

Comments

@akalin-keybase
Copy link

In go 1.7, Dialer now has DialContext, which takes a context.Context and uses it for expiration.

However, DialWithDialer just calls Dial on its given Dialer, and doesn't take a context.Context.

To be backwards compatible, probably need to provide a separate function, say, DialContextWithDialer, that is like DialWithDialer except it takes a context.Context and calls DialContext, and have DialWithDialer call DialContextWithDialer with context.Background().

It looks like as a workaround, callers can write their own DialContextWithDialer function and copy most of DialWithDialer.

@bradfitz
Copy link
Contributor

The review period for Go 1.7 APIs ended 6 months ago.

The review period for Go 1.8 APIs ended approximately 3 weeks ago.

We can consider something new in crypto/tls for Go 1.9.

For now, you'll just have to dial first, and then use https://golang.org/pkg/crypto/tls/#Client to start the client handshake on the already-connected TCP (or whatever) Conn.

@bradfitz bradfitz changed the title [crypto/tls] DialWithDialer doesn't take a context argument crypto/tls: add API to Dial with a context? Dec 31, 2016
@bradfitz bradfitz added this to the Go1.9Maybe milestone Dec 31, 2016
@bradfitz bradfitz added the NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made. label Dec 31, 2016
@bradfitz bradfitz modified the milestones: Go1.10, Go1.9Maybe Jun 7, 2017
@rosenhouse
Copy link
Contributor

rosenhouse commented Aug 17, 2017

I believe I have a use-case for this feature and would be curious if there's a suggested work-around.

We're trying to configure a http.Transport such that the client does extra validation of the server-provided certificate before sending any data. We want this client to compare server-provided certificate fields against values present on the req.Context. We see Transport.DialContext() but there's no Transport.DialTLSContext(), and setting a DialContext function that does TLS internally looks like it won't work.

Edit: perhaps I'm asking in the wrong issue -- this is bigger than just the crypto/tls package...

@gobwas
Copy link

gobwas commented Nov 3, 2017

Hello! Sorry for "pinging", but will this issue be landed in 1.10? Milestone is 1.10 but no NeedsFix label... Im okay with the work-around, but it looks like little dirty when I need to copy logic of adding tls.Config.ServerName from tls.DialWithDialer().

@ianlancetaylor
Copy link
Contributor

@gobwas There has been no definite decision to implement this, and there is no patch. At this point I would say that it is unlikely to be fixed for 1.10. Sorry.

@bradfitz bradfitz modified the milestones: Go1.10, Go1.11 Nov 16, 2017
@gopherbot
Copy link

Change https://golang.org/cl/93255 mentions this issue: crypto/tls: add DialContextWithDialer function

@maja42
Copy link

maja42 commented Jun 28, 2018

Is there currently a workaround for this issue?

@filipochnik
Copy link

filipochnik commented Jun 28, 2018

@maja42 As @akalin-keybase said

It looks like as a workaround, callers can write their own DialContextWithDialer function and copy most of DialWithDialer.

I submitted a patch implementing this a few months ago but I'm not sure if there's a decision to add this to the API.

@bradfitz is there a decision one way or the other?

@FiloSottile FiloSottile added Proposal Proposal-Crypto Proposal related to crypto packages or other security issues and removed NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made. labels Sep 5, 2018
@FiloSottile FiloSottile changed the title crypto/tls: add API to Dial with a context? crypto/tls: add DialContextWithDialer Sep 5, 2018
@bradfitz
Copy link
Contributor

bradfitz commented Oct 2, 2018

@FiloSottile, I'm going to remove the Proposal-Crypto review so this gets some attention during the proposal review meetings (which exclude Crypto).

This is more standard library API than it is crypto, and you also seem to be backlogged on other crypto stuff.

@bradfitz bradfitz added NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made. and removed Proposal-Crypto Proposal related to crypto packages or other security issues labels Oct 2, 2018
@bradfitz
Copy link
Contributor

bradfitz commented Oct 5, 2018

Counter proposal:

What if we add a new crypto/tls.Dialer type, with two fields:

// Dialer dials TLS connections given a configuration and a Dialer for the
// underlying connection. 
type Dialer struct {
     Config    *Config
     NetDialer *net.Dialer
}

Then the new Dialer can have Dial and DialContext methods with the normal signatures.

Thoughts?

@FiloSottile
Copy link
Contributor

crypto/tls.Dialer LGTM, with deprecation of crypto/tls.DialWithDialer in favor of crypto/tls.Dialer.Dial.

If this is approved, I'll implement it in the TLS 1.3 dev cycle.

@akalin-keybase
Copy link
Author

Works for me!

@jsha
Copy link

jsha commented Oct 29, 2018

Another possibility: What about adding a context.Context field on tls.Config? This has a few advantages I can see:

  • Doesn't require new methods in crypto/tls
  • Easier to plumb through from net/http, which has a TLSClientConfig field on Transport
  • Allows the context to be applied to handshaking, not just TCP dialing. In Boulder, we just found a connection leak when a remote host times out a handshake.

@bradfitz
Copy link
Contributor

@jsha, that would violate the context rules of not storing them in long-lived or shared structures, and *tls.Config is generally both.

I don't understand your handshake concern: we already do the handshake under the provided timeout. That wouldn't change with the design proposed above. The handshake would still be under the context's deadline.

@jsha
Copy link

jsha commented Oct 29, 2018

@jsha, that would violate the context rules of not storing them in long-lived or shared structures, and *tls.Config is generally both.

Ah, good point. I was looking primarily at the conn.Client method, where *tls.Config is short-lived and non-shared. Is it accurate to say that *tls.Config is short-lived and non-shared when used by a client, but not when used by a server?

I don't understand your handshake concern: we already do the handshake under the provided timeout. That wouldn't change with the design proposed above. The handshake would still be under the context's deadline.

The Handshake concern applies only in code where you build your own TCP connection then hand it off to crypto/tls for the handshake:

netConn, _ := dialer.DialContext(ctx, "tcp", hostPort)
conn := tls.Client(netConn, config) 
conn.Handshake()

It's not strictly related to implementing DialContextWithDialer, but it's another place in crypto/tls that appears to need the context treatment, so I wanted to suggest an idea that might kill two birds with one stone. I'm also happy to file a separate issue about Handshake.

@jsha
Copy link

jsha commented Oct 29, 2018

Is it accurate to say that *tls.Config is short-lived and non-shared when used by a client, but not when used by a server?

Nevermind on this; I looked again and realized that yes, clients will typically reuse a *tls.Config many times, though it is not required by the API.

@jlaffaye
Copy link

Any progress on this issue ?

@FiloSottile
Copy link
Contributor

Should the methods on tls.Dialer return net.Conn (to match the common signatures) or *tls.Conn?

func (*Dialer) Dial(network, address string) (*Conn, error)
func (*Dialer) DialContext(ctx context.Context, network, address string) (*Conn, error)
func (*Dialer) Dial(network, address string) (net.Conn, error)
func (*Dialer) DialContext(ctx context.Context, network, address string) (net.Conn, error)

Also, we should probably allow Dialer.NetDialer to be nil, so DialContext can be used without a custom net.Dialer.

@dcormier
Copy link
Contributor

dcormier commented Dec 3, 2019

Seeing as the two existing TLS dial functions (tls.Dial and tls.DialWithDialer) both return *tls.Conn, I think these should also return *tls.Conn.

@rsc rsc added this to Incoming in Proposals (old) Dec 4, 2019
@rsc rsc changed the title crypto/tls: add DialContextWithDialer crypto/tls: add Dialer with Dial, DialContext methods Jan 15, 2020
@rsc
Copy link
Contributor

rsc commented Jan 15, 2020

@bradfitz points out that net/http.Transport has function fields that would be type-matched by these methods if we made them return net.Conn instead of *tls.Conn. So probably we should return net.Conn here. We could still document that the underlying type is *tls.Conn.

Otherwise this seems like a likely accept based on the discussion above.

Leaving open for a week for final comments.

@rosenhouse
Copy link
Contributor

(I think that's referring to #21526 ?)

@rsc
Copy link
Contributor

rsc commented Jan 15, 2020

@rosenhouse, yes, the point is that if this tls.Dialer's Dial and DialContext methods return net.Conn (not *tls.Conn), then you can do assignments like this without adapters:

var d tls.Dialer
var t http.Transport
t.Dial = d.Dial
t.DialContext = d.DialContext

@gopherbot
Copy link

Change https://golang.org/cl/214977 mentions this issue: crypto/tls: add Dialer

@rsc rsc moved this from Incoming to Active in Proposals (old) Jan 15, 2020
@rsc rsc moved this from Active to Likely Accept in Proposals (old) Jan 15, 2020
@rsc
Copy link
Contributor

rsc commented Jan 22, 2020

No change in consensus, so accepted.

@rsc rsc moved this from Likely Accept to Accepted in Proposals (old) Jan 22, 2020
@rsc rsc modified the milestones: Unplanned, Backlog Jan 22, 2020
@FiloSottile FiloSottile added NeedsFix The path to resolution is known, but the work has not been done. and removed NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made. Proposal labels Mar 31, 2020
@golang golang locked and limited conversation to collaborators Apr 20, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FeatureRequest FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done. Proposal-Accepted
Projects
No open projects
Development

No branches or pull requests