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

move go-conn-security-multistream here #1460

Merged
merged 18 commits into from
Apr 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions config/security.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ package config
import (
"fmt"

csms "github.com/libp2p/go-libp2p/p2p/net/conn-security-multistream"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feel free to rename to something sane.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe even have a multistream package? Or an upgraders package? Not sure.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have an upgrader. Can't think of something sensible for this package right now. Let's rename this later.


"github.com/libp2p/go-libp2p-core/crypto"
"github.com/libp2p/go-libp2p-core/host"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/libp2p/go-libp2p-core/sec"
"github.com/libp2p/go-libp2p-core/sec/insecure"

csms "github.com/libp2p/go-conn-security-multistream"
)

// SecC is a security transport constructor.
Expand Down
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ require (
github.com/ipfs/go-log/v2 v2.5.1
github.com/klauspost/compress v1.15.1
github.com/libp2p/go-buffer-pool v0.0.2
github.com/libp2p/go-conn-security-multistream v0.3.0
github.com/libp2p/go-eventbus v0.2.1
github.com/libp2p/go-libp2p-asn-util v0.1.0
github.com/libp2p/go-libp2p-circuit v0.6.0
Expand Down
109 changes: 109 additions & 0 deletions p2p/net/conn-security-multistream/ssms.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package csms

import (
"context"
"fmt"
"log"
"net"

"github.com/libp2p/go-libp2p-core/peer"
"github.com/libp2p/go-libp2p-core/sec"
mss "github.com/multiformats/go-multistream"
)

// SSMuxer is a multistream stream security transport multiplexer.
//
// SSMuxer is safe to use without initialization. However, it's not safe to move
// after use.
type SSMuxer struct {
mux mss.MultistreamMuxer
tpts map[string]sec.SecureTransport
OrderPreference []string
}

var _ sec.SecureMuxer = (*SSMuxer)(nil)

// AddTransport adds a stream security transport to this multistream muxer.
//
// This method is *not* thread-safe. It should be called only when initializing
// the SSMuxer.
func (sm *SSMuxer) AddTransport(path string, transport sec.SecureTransport) {
if sm.tpts == nil {
sm.tpts = make(map[string]sec.SecureTransport, 1)
}

sm.mux.AddHandler(path, nil)
sm.tpts[path] = transport
sm.OrderPreference = append(sm.OrderPreference, path)
}

// SecureInbound secures an inbound connection using this multistream
// multiplexed stream security transport.
func (sm *SSMuxer) SecureInbound(ctx context.Context, insecure net.Conn, p peer.ID) (sec.SecureConn, bool, error) {
tpt, _, err := sm.selectProto(ctx, insecure, true)
if err != nil {
return nil, false, err
}
sconn, err := tpt.SecureInbound(ctx, insecure, p)
return sconn, true, err
}

// SecureOutbound secures an outbound connection using this multistream
// multiplexed stream security transport.
func (sm *SSMuxer) SecureOutbound(ctx context.Context, insecure net.Conn, p peer.ID) (sec.SecureConn, bool, error) {
tpt, server, err := sm.selectProto(ctx, insecure, false)
if err != nil {
return nil, false, err
}

var sconn sec.SecureConn
if server {
sconn, err = tpt.SecureInbound(ctx, insecure, p)
if err != nil {
return nil, false, fmt.Errorf("failed to secure inbound connection: %s", err)
}
// ensure the correct peer connected to us
if sconn.RemotePeer() != p {
sconn.Close()
log.Printf("Handshake failed to properly authenticate peer. Authenticated %s, expected %s.", sconn.RemotePeer(), p)
return nil, false, fmt.Errorf("unexpected peer")
}
} else {
sconn, err = tpt.SecureOutbound(ctx, insecure, p)
}

return sconn, server, err
}

func (sm *SSMuxer) selectProto(ctx context.Context, insecure net.Conn, server bool) (sec.SecureTransport, bool, error) {
var proto string
var err error
var iamserver bool
done := make(chan struct{})
go func() {
defer close(done)
if server {
iamserver = true
proto, _, err = sm.mux.Negotiate(insecure)
} else {
proto, iamserver, err = mss.SelectWithSimopenOrFail(sm.OrderPreference, insecure)
}
}()

select {
case <-done:
if err != nil {
return nil, false, err
}
if tpt, ok := sm.tpts[proto]; ok {
return tpt, iamserver, nil
}
return nil, false, fmt.Errorf("selected unknown security transport")
case <-ctx.Done():
// We *must* do this. We have outstanding work on the connection
// and it's no longer safe to use.
insecure.Close()
<-done // wait to stop using the connection.
return nil, false, ctx.Err()
}
}
79 changes: 79 additions & 0 deletions p2p/net/conn-security-multistream/ssms_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package csms

import (
"context"
"net"
"sync"
"testing"

"github.com/libp2p/go-libp2p-core/peer"
"github.com/libp2p/go-libp2p-core/sec"
"github.com/libp2p/go-libp2p-core/sec/insecure"
tnet "github.com/libp2p/go-libp2p-testing/net"
sst "github.com/libp2p/go-libp2p-testing/suites/sec"
)

type TransportAdapter struct {
mux *SSMuxer
}

func (sm *TransportAdapter) SecureInbound(ctx context.Context, insecure net.Conn, p peer.ID) (sec.SecureConn, error) {
sconn, _, err := sm.mux.SecureInbound(ctx, insecure, p)
return sconn, err
}

func (sm *TransportAdapter) SecureOutbound(ctx context.Context, insecure net.Conn, p peer.ID) (sec.SecureConn, error) {
sconn, _, err := sm.mux.SecureOutbound(ctx, insecure, p)
return sconn, err
}

func TestCommonProto(t *testing.T) {
idA := tnet.RandIdentityOrFatal(t)
idB := tnet.RandIdentityOrFatal(t)

var at, bt SSMuxer

atInsecure := insecure.NewWithIdentity(idA.ID(), idA.PrivateKey())
btInsecure := insecure.NewWithIdentity(idB.ID(), idB.PrivateKey())
at.AddTransport("/plaintext/1.0.0", atInsecure)
bt.AddTransport("/plaintext/1.1.0", btInsecure)
bt.AddTransport("/plaintext/1.0.0", btInsecure)
sst.SubtestRW(t, &TransportAdapter{mux: &at}, &TransportAdapter{mux: &bt}, idA.ID(), idB.ID())
}

func TestNoCommonProto(t *testing.T) {
idA := tnet.RandIdentityOrFatal(t)
idB := tnet.RandIdentityOrFatal(t)

var at, bt SSMuxer
atInsecure := insecure.NewWithIdentity(idA.ID(), idA.PrivateKey())
btInsecure := insecure.NewWithIdentity(idB.ID(), idB.PrivateKey())

at.AddTransport("/plaintext/1.0.0", atInsecure)
bt.AddTransport("/plaintext/1.1.0", btInsecure)

ctx, cancel := context.WithCancel(context.Background())
defer cancel()
a, b := net.Pipe()

var wg sync.WaitGroup
wg.Add(2)
go func() {
defer wg.Done()
defer a.Close()
_, _, err := at.SecureInbound(ctx, a, "")
if err == nil {
t.Error("connection should have failed")
}
}()

go func() {
defer wg.Done()
defer b.Close()
_, _, err := bt.SecureOutbound(ctx, b, "peerA")
if err == nil {
t.Error("connection should have failed")
}
}()
wg.Wait()
}
2 changes: 1 addition & 1 deletion p2p/net/swarm/dial_worker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ import (
"time"

"github.com/libp2p/go-libp2p/p2p/muxer/yamux"
csms "github.com/libp2p/go-libp2p/p2p/net/conn-security-multistream"
quic "github.com/libp2p/go-libp2p/p2p/transport/quic"
"github.com/libp2p/go-libp2p/p2p/transport/tcp"

"github.com/libp2p/go-libp2p-core/peerstore"
"github.com/libp2p/go-libp2p-core/sec/insecure"
"github.com/libp2p/go-libp2p-core/transport"

csms "github.com/libp2p/go-conn-security-multistream"
"github.com/libp2p/go-libp2p-peerstore/pstoremem"
tnet "github.com/libp2p/go-libp2p-testing/net"
tptu "github.com/libp2p/go-libp2p-transport-upgrader"
Expand Down
2 changes: 1 addition & 1 deletion p2p/net/swarm/testing/testing.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"time"

"github.com/libp2p/go-libp2p/p2p/muxer/yamux"
csms "github.com/libp2p/go-libp2p/p2p/net/conn-security-multistream"
"github.com/libp2p/go-libp2p/p2p/net/swarm"
quic "github.com/libp2p/go-libp2p/p2p/transport/quic"
"github.com/libp2p/go-libp2p/p2p/transport/tcp"
Expand All @@ -19,7 +20,6 @@ import (
"github.com/libp2p/go-libp2p-core/sec/insecure"
"github.com/libp2p/go-libp2p-core/transport"

csms "github.com/libp2p/go-conn-security-multistream"
"github.com/libp2p/go-libp2p-peerstore/pstoremem"
tnet "github.com/libp2p/go-libp2p-testing/net"
tptu "github.com/libp2p/go-libp2p-transport-upgrader"
Expand Down
2 changes: 1 addition & 1 deletion p2p/transport/tcp/tcp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"testing"

"github.com/libp2p/go-libp2p/p2p/muxer/yamux"
csms "github.com/libp2p/go-libp2p/p2p/net/conn-security-multistream"

"github.com/libp2p/go-libp2p-core/crypto"
"github.com/libp2p/go-libp2p-core/network"
Expand All @@ -14,7 +15,6 @@ import (
"github.com/libp2p/go-libp2p-core/sec/insecure"
"github.com/libp2p/go-libp2p-core/transport"

csms "github.com/libp2p/go-conn-security-multistream"
mocknetwork "github.com/libp2p/go-libp2p-testing/mocks/network"
ttransport "github.com/libp2p/go-libp2p-testing/suites/transport"
tptu "github.com/libp2p/go-libp2p-transport-upgrader"
Expand Down
3 changes: 2 additions & 1 deletion p2p/transport/websocket/websocket_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import (
"testing"
"time"

csms "github.com/libp2p/go-libp2p/p2p/net/conn-security-multistream"

"github.com/libp2p/go-libp2p-core/crypto"
"github.com/libp2p/go-libp2p-core/network"
"github.com/libp2p/go-libp2p-core/peer"
Expand All @@ -24,7 +26,6 @@ import (
"github.com/libp2p/go-libp2p-core/transport"
"github.com/libp2p/go-libp2p/p2p/muxer/yamux"

csms "github.com/libp2p/go-conn-security-multistream"
ttransport "github.com/libp2p/go-libp2p-testing/suites/transport"
tptu "github.com/libp2p/go-libp2p-transport-upgrader"

Expand Down