From 97e739f0a872abf72f75c26549aa70870140ddd9 Mon Sep 17 00:00:00 2001 From: Marten Seemann Date: Sat, 3 Sep 2022 13:52:50 +0300 Subject: [PATCH] update to the current master of go-libp2p (#23) --- p2p/transport/webtransport/conn.go | 4 +- p2p/transport/webtransport/listener.go | 75 +++++++++++++------ .../mock_connection_gater_test.go | 8 +- .../webtransport/noise_early_data.go | 34 +++++++++ p2p/transport/webtransport/stream.go | 2 +- p2p/transport/webtransport/transport.go | 48 ++++-------- p2p/transport/webtransport/transport_test.go | 10 +-- 7 files changed, 113 insertions(+), 68 deletions(-) create mode 100644 p2p/transport/webtransport/noise_early_data.go diff --git a/p2p/transport/webtransport/conn.go b/p2p/transport/webtransport/conn.go index 409cea3383..f68595293f 100644 --- a/p2p/transport/webtransport/conn.go +++ b/p2p/transport/webtransport/conn.go @@ -3,8 +3,8 @@ package libp2pwebtransport import ( "context" - "github.com/libp2p/go-libp2p-core/network" - tpt "github.com/libp2p/go-libp2p-core/transport" + "github.com/libp2p/go-libp2p/core/network" + tpt "github.com/libp2p/go-libp2p/core/transport" "github.com/marten-seemann/webtransport-go" ma "github.com/multiformats/go-multiaddr" diff --git a/p2p/transport/webtransport/listener.go b/p2p/transport/webtransport/listener.go index 872e65804b..4c87512d29 100644 --- a/p2p/transport/webtransport/listener.go +++ b/p2p/transport/webtransport/listener.go @@ -5,15 +5,16 @@ import ( "crypto/tls" "errors" "fmt" + pb "github.com/marten-seemann/go-libp2p-webtransport/pb" + "github.com/multiformats/go-multihash" "net" "net/http" "time" - "github.com/libp2p/go-libp2p-core/connmgr" - "github.com/libp2p/go-libp2p-core/network" - tpt "github.com/libp2p/go-libp2p-core/transport" - - noise "github.com/libp2p/go-libp2p-noise" + "github.com/libp2p/go-libp2p/core/connmgr" + "github.com/libp2p/go-libp2p/core/network" + tpt "github.com/libp2p/go-libp2p/core/transport" + "github.com/libp2p/go-libp2p/p2p/security/noise" "github.com/lucas-clemente/quic-go/http3" "github.com/marten-seemann/webtransport-go" @@ -27,10 +28,11 @@ const queueLen = 16 const handshakeTimeout = 10 * time.Second type listener struct { - transport tpt.Transport - noise *noise.Transport - certManager *certManager - staticTLSConf *tls.Config + transport tpt.Transport + noise *noise.Transport + certManager *certManager + tlsConf *tls.Config + isStaticTLSConf bool rcmgr network.ResourceManager gater connmgr.ConnectionGater @@ -67,23 +69,25 @@ func newListener(laddr ma.Multiaddr, transport tpt.Transport, noise *noise.Trans if err != nil { return nil, err } + isStaticTLSConf := tlsConf != nil if tlsConf == nil { tlsConf = &tls.Config{GetConfigForClient: func(*tls.ClientHelloInfo) (*tls.Config, error) { return certManager.GetConfig(), nil }} } ln := &listener{ - transport: transport, - noise: noise, - certManager: certManager, - staticTLSConf: tlsConf, - rcmgr: rcmgr, - gater: gater, - queue: make(chan tpt.CapableConn, queueLen), - serverClosed: make(chan struct{}), - addr: udpConn.LocalAddr(), - multiaddr: localMultiaddr, - server: webtransport.Server{H3: http3.Server{TLSConfig: tlsConf}}, + transport: transport, + noise: noise, + certManager: certManager, + tlsConf: tlsConf, + isStaticTLSConf: isStaticTLSConf, + rcmgr: rcmgr, + gater: gater, + queue: make(chan tpt.CapableConn, queueLen), + serverClosed: make(chan struct{}), + addr: udpConn.LocalAddr(), + multiaddr: localMultiaddr, + server: webtransport.Server{H3: http3.Server{TLSConfig: tlsConf}}, } ln.ctx, ln.ctxCancel = context.WithCancel(context.Background()) mux := http.NewServeMux() @@ -184,7 +188,11 @@ func (l *listener) handshake(ctx context.Context, sess *webtransport.Session) (c if err != nil { return nil, err } - c, err := l.noise.SecureInbound(ctx, &webtransportStream{Stream: str, wsess: sess}, "") + n, err := l.noise.WithSessionOptions(noise.EarlyData(newEarlyDataReceiver(l.checkEarlyData))) + if err != nil { + return nil, fmt.Errorf("failed to initialize Noise session: %w", err) + } + c, err := n.SecureInbound(ctx, &webtransportStream{Stream: str, wsess: sess}, "") if err != nil { return nil, err } @@ -195,6 +203,31 @@ func (l *listener) handshake(ctx context.Context, sess *webtransport.Session) (c }, nil } +func (l *listener) checkEarlyData(b []byte) error { + var msg pb.WebTransport + if err := msg.Unmarshal(b); err != nil { + fmt.Println(1) + return fmt.Errorf("failed to unmarshal early data protobuf: %w", err) + } + + if l.isStaticTLSConf { + if len(msg.CertHashes) > 0 { + return errors.New("using static TLS config, didn't expect any certificate hashes") + } + return nil + } + + hashes := make([]multihash.DecodedMultihash, 0, len(msg.CertHashes)) + for _, h := range msg.CertHashes { + dh, err := multihash.Decode(h) + if err != nil { + return fmt.Errorf("failed to decode hash: %w", err) + } + hashes = append(hashes, *dh) + } + return l.certManager.Verify(hashes) +} + func (l *listener) Addr() net.Addr { return l.addr } diff --git a/p2p/transport/webtransport/mock_connection_gater_test.go b/p2p/transport/webtransport/mock_connection_gater_test.go index 071ed7494f..c6e7dbaad6 100644 --- a/p2p/transport/webtransport/mock_connection_gater_test.go +++ b/p2p/transport/webtransport/mock_connection_gater_test.go @@ -1,5 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/libp2p/go-libp2p-core/connmgr (interfaces: ConnectionGater) +// Source: github.com/libp2p/go-libp2p/core/connmgr (interfaces: ConnectionGater) // Package libp2pwebtransport_test is a generated GoMock package. package libp2pwebtransport_test @@ -8,9 +8,9 @@ import ( reflect "reflect" gomock "github.com/golang/mock/gomock" - control "github.com/libp2p/go-libp2p-core/control" - network "github.com/libp2p/go-libp2p-core/network" - peer "github.com/libp2p/go-libp2p-core/peer" + control "github.com/libp2p/go-libp2p/core/control" + network "github.com/libp2p/go-libp2p/core/network" + peer "github.com/libp2p/go-libp2p/core/peer" multiaddr "github.com/multiformats/go-multiaddr" ) diff --git a/p2p/transport/webtransport/noise_early_data.go b/p2p/transport/webtransport/noise_early_data.go new file mode 100644 index 0000000000..ec01c6d7a2 --- /dev/null +++ b/p2p/transport/webtransport/noise_early_data.go @@ -0,0 +1,34 @@ +package libp2pwebtransport + +import ( + "context" + "github.com/libp2p/go-libp2p/core/peer" + "github.com/libp2p/go-libp2p/p2p/security/noise" + "net" +) + +type earlyDataHandler struct { + earlyData []byte + receive func([]byte) error +} + +var _ noise.EarlyDataHandler = &earlyDataHandler{} + +func newEarlyDataSender(earlyData []byte) noise.EarlyDataHandler { + return &earlyDataHandler{earlyData: earlyData} +} + +func newEarlyDataReceiver(receive func([]byte) error) noise.EarlyDataHandler { + return &earlyDataHandler{receive: receive} +} + +func (e *earlyDataHandler) Send(context.Context, net.Conn, peer.ID) []byte { + return e.earlyData +} + +func (e *earlyDataHandler) Received(_ context.Context, _ net.Conn, b []byte) error { + if e.receive == nil { + return nil + } + return e.receive(b) +} diff --git a/p2p/transport/webtransport/stream.go b/p2p/transport/webtransport/stream.go index 6aa58cb8d8..ff17b3083f 100644 --- a/p2p/transport/webtransport/stream.go +++ b/p2p/transport/webtransport/stream.go @@ -6,7 +6,7 @@ import ( "github.com/marten-seemann/webtransport-go" - "github.com/libp2p/go-libp2p-core/network" + "github.com/libp2p/go-libp2p/core/network" ) const ( diff --git a/p2p/transport/webtransport/transport.go b/p2p/transport/webtransport/transport.go index e027e1fe8f..faa13db86c 100644 --- a/p2p/transport/webtransport/transport.go +++ b/p2p/transport/webtransport/transport.go @@ -4,7 +4,6 @@ import ( "context" "crypto/tls" "crypto/x509" - "errors" "fmt" "io" "sync" @@ -12,13 +11,12 @@ import ( pb "github.com/marten-seemann/go-libp2p-webtransport/pb" - "github.com/libp2p/go-libp2p-core/connmgr" - ic "github.com/libp2p/go-libp2p-core/crypto" - "github.com/libp2p/go-libp2p-core/network" - "github.com/libp2p/go-libp2p-core/peer" - tpt "github.com/libp2p/go-libp2p-core/transport" - - noise "github.com/libp2p/go-libp2p-noise" + "github.com/libp2p/go-libp2p/core/connmgr" + ic "github.com/libp2p/go-libp2p/core/crypto" + "github.com/libp2p/go-libp2p/core/network" + "github.com/libp2p/go-libp2p/core/peer" + tpt "github.com/libp2p/go-libp2p/core/transport" + "github.com/libp2p/go-libp2p/p2p/security/noise" "github.com/benbjohnson/clock" logging "github.com/ipfs/go-log/v2" @@ -102,11 +100,11 @@ func New(key ic.PrivKey, gater connmgr.ConnectionGater, rcmgr network.ResourceMa return nil, err } } - noise, err := noise.New(key, noise.WithEarlyDataHandler(t.checkEarlyData)) + n, err := noise.New(key) if err != nil { return nil, err } - t.noise = noise + t.noise = n return t, nil } @@ -207,7 +205,11 @@ func (t *transport) upgrade(ctx context.Context, sess *webtransport.Session, p p if err != nil { return nil, fmt.Errorf("failed to marshal WebTransport protobuf: %w", err) } - c, err := t.noise.SecureOutboundWithEarlyData(ctx, &webtransportStream{Stream: str, wsess: sess}, p, msgBytes) + n, err := t.noise.WithSessionOptions(noise.EarlyData(newEarlyDataSender(msgBytes))) + if err != nil { + return nil, fmt.Errorf("failed to create Noise transport: %w", err) + } + c, err := n.SecureOutbound(ctx, &webtransportStream{Stream: str, wsess: sess}, p) if err != nil { return nil, err } @@ -217,30 +219,6 @@ func (t *transport) upgrade(ctx context.Context, sess *webtransport.Session, p p }, nil } -func (t *transport) checkEarlyData(b []byte) error { - var msg pb.WebTransport - if err := msg.Unmarshal(b); err != nil { - return fmt.Errorf("failed to unmarshal early data protobuf: %w", err) - } - hashes := make([]multihash.DecodedMultihash, 0, len(msg.CertHashes)) - - if t.staticTLSConf != nil { - if len(hashes) > 0 { - return errors.New("using static TLS config, didn't expect any certificate hashes") - } - return nil - } - - for _, h := range msg.CertHashes { - dh, err := multihash.Decode(h) - if err != nil { - return fmt.Errorf("failed to decode hash: %w", err) - } - hashes = append(hashes, *dh) - } - return t.certManager.Verify(hashes) -} - func (t *transport) CanDial(addr ma.Multiaddr) bool { var numHashes int ma.ForEach(addr, func(c ma.Component) bool { diff --git a/p2p/transport/webtransport/transport_test.go b/p2p/transport/webtransport/transport_test.go index d436af4bd2..02f065bc8c 100644 --- a/p2p/transport/webtransport/transport_test.go +++ b/p2p/transport/webtransport/transport_test.go @@ -20,12 +20,12 @@ import ( libp2pwebtransport "github.com/marten-seemann/go-libp2p-webtransport" - ic "github.com/libp2p/go-libp2p-core/crypto" - "github.com/libp2p/go-libp2p-core/network" - "github.com/libp2p/go-libp2p-core/peer" + ic "github.com/libp2p/go-libp2p/core/crypto" + "github.com/libp2p/go-libp2p/core/network" + mocknetwork "github.com/libp2p/go-libp2p/core/network/mocks" + "github.com/libp2p/go-libp2p/core/peer" "github.com/golang/mock/gomock" - mocknetwork "github.com/libp2p/go-libp2p-testing/mocks/network" ma "github.com/multiformats/go-multiaddr" manet "github.com/multiformats/go-multiaddr/net" "github.com/multiformats/go-multibase" @@ -338,7 +338,7 @@ func TestResourceManagerListening(t *testing.T) { } // TODO: unify somehow. We do the same in libp2pquic. -//go:generate sh -c "mockgen -package libp2pwebtransport_test -destination mock_connection_gater_test.go github.com/libp2p/go-libp2p-core/connmgr ConnectionGater && goimports -w mock_connection_gater_test.go" +//go:generate sh -c "mockgen -package libp2pwebtransport_test -destination mock_connection_gater_test.go github.com/libp2p/go-libp2p/core/connmgr ConnectionGater && goimports -w mock_connection_gater_test.go" func TestConnectionGaterDialing(t *testing.T) { ctrl := gomock.NewController(t)