mirror of https://github.com/libp2p/go-libp2p.git
Marten Seemann
2 years ago
12 changed files with 152 additions and 342 deletions
@ -1,23 +0,0 @@ |
|||
package config |
|||
|
|||
import ( |
|||
"github.com/libp2p/go-libp2p/core/crypto" |
|||
"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-libp2p/p2p/net/conn-security-multistream" |
|||
) |
|||
|
|||
func makeInsecureTransport(id peer.ID, privKey crypto.PrivKey) sec.SecureMuxer { |
|||
secMuxer := new(csms.SSMuxer) |
|||
secMuxer.AddTransport(insecure.ID, insecure.NewWithIdentity(insecure.ID, id, privKey)) |
|||
return secMuxer |
|||
} |
|||
|
|||
func makeSecurityMuxer(tpts []sec.SecureTransport) sec.SecureMuxer { |
|||
secMuxer := new(csms.SSMuxer) |
|||
for _, tpt := range tpts { |
|||
secMuxer.AddTransport(string(tpt.ID()), tpt) |
|||
} |
|||
return secMuxer |
|||
} |
@ -1,101 +0,0 @@ |
|||
package csms |
|||
|
|||
import ( |
|||
"context" |
|||
"fmt" |
|||
"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 |
|||
} |
|||
|
|||
if server { |
|||
sconn, err := tpt.SecureInbound(ctx, insecure, p) |
|||
if err != nil { |
|||
return nil, false, fmt.Errorf("failed to secure inbound connection: %s", err) |
|||
} |
|||
return sconn, true, nil |
|||
} |
|||
sconn, err := tpt.SecureOutbound(ctx, insecure, p) |
|||
return sconn, false, 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() |
|||
} |
|||
} |
@ -1,121 +0,0 @@ |
|||
package csms |
|||
|
|||
import ( |
|||
"context" |
|||
"crypto/rand" |
|||
"io" |
|||
"net" |
|||
"sync" |
|||
"testing" |
|||
|
|||
"github.com/libp2p/go-libp2p/core/crypto" |
|||
"github.com/libp2p/go-libp2p/core/peer" |
|||
"github.com/libp2p/go-libp2p/core/sec" |
|||
"github.com/libp2p/go-libp2p/core/sec/insecure" |
|||
|
|||
"github.com/stretchr/testify/require" |
|||
) |
|||
|
|||
func newPeer(t *testing.T) (crypto.PrivKey, peer.ID) { |
|||
priv, _, err := crypto.GenerateEd25519Key(rand.Reader) |
|||
require.NoError(t, err) |
|||
id, err := peer.IDFromPrivateKey(priv) |
|||
require.NoError(t, err) |
|||
return priv, id |
|||
} |
|||
|
|||
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) { |
|||
privA, idA := newPeer(t) |
|||
privB, idB := newPeer(t) |
|||
|
|||
var at, bt SSMuxer |
|||
|
|||
atInsecure := insecure.NewWithIdentity(insecure.ID, idA, privA) |
|||
btInsecure := insecure.NewWithIdentity(insecure.ID, idB, privB) |
|||
at.AddTransport("/plaintext/1.0.0", atInsecure) |
|||
bt.AddTransport("/plaintext/1.1.0", btInsecure) |
|||
bt.AddTransport("/plaintext/1.0.0", btInsecure) |
|||
|
|||
ln, err := net.Listen("tcp", "localhost:0") |
|||
require.NoError(t, err) |
|||
muxB := &TransportAdapter{mux: &bt} |
|||
connChan := make(chan sec.SecureConn) |
|||
go func() { |
|||
conn, err := ln.Accept() |
|||
require.NoError(t, err) |
|||
c, err := muxB.SecureInbound(context.Background(), conn, idA) |
|||
require.NoError(t, err) |
|||
connChan <- c |
|||
}() |
|||
|
|||
muxA := &TransportAdapter{mux: &at} |
|||
|
|||
cconn, err := net.Dial("tcp", ln.Addr().String()) |
|||
require.NoError(t, err) |
|||
|
|||
cc, err := muxA.SecureOutbound(context.Background(), cconn, idB) |
|||
require.NoError(t, err) |
|||
require.Equal(t, cc.LocalPeer(), idA) |
|||
require.Equal(t, cc.RemotePeer(), idB) |
|||
_, err = cc.Write([]byte("foobar")) |
|||
require.NoError(t, err) |
|||
require.NoError(t, cc.Close()) |
|||
|
|||
sc := <-connChan |
|||
require.Equal(t, sc.LocalPeer(), idB) |
|||
require.Equal(t, sc.RemotePeer(), idA) |
|||
b, err := io.ReadAll(sc) |
|||
require.NoError(t, err) |
|||
require.Equal(t, "foobar", string(b)) |
|||
} |
|||
|
|||
func TestNoCommonProto(t *testing.T) { |
|||
privA, idA := newPeer(t) |
|||
privB, idB := newPeer(t) |
|||
|
|||
var at, bt SSMuxer |
|||
atInsecure := insecure.NewWithIdentity(insecure.ID, idA, privA) |
|||
btInsecure := insecure.NewWithIdentity(insecure.ID, idB, privB) |
|||
|
|||
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() |
|||
} |
Loading…
Reference in new issue