insecure.go 6.32 KB
Newer Older
1 2 3 4 5 6 7
// Package insecure provides an insecure, unencrypted implementation of the the SecureConn and SecureTransport interfaces.
//
// Recommended only for testing and other non-production usage.
package insecure

import (
	"context"
8
	"fmt"
9
	"io"
10 11 12 13
	"net"

	"github.com/libp2p/go-libp2p-core/peer"
	"github.com/libp2p/go-libp2p-core/sec"
14
	"github.com/libp2p/go-msgio"
15 16

	ci "github.com/libp2p/go-libp2p-core/crypto"
17
	pb "github.com/libp2p/go-libp2p-core/sec/insecure/pb"
18 19 20 21
)

// ID is the multistream-select protocol ID that should be used when identifying
// this security transport.
22
const ID = "/plaintext/2.0.0"
23 24

// Transport is a no-op stream security transport. It provides no
25 26 27 28
// security and simply mocks the security methods. Identity methods
// return the local peer's ID and private key, and whatever the remote
// peer presents as their ID and public key.
// No authentication of the remote identity is performed.
29
type Transport struct {
30 31
	id  peer.ID
	key ci.PrivKey
32 33 34
}

// New constructs a new insecure transport.
35
// Deprecated: use NewWithIdentity instead.
36
func New(id peer.ID) *Transport {
37
	return &Transport{
38
		id: id,
39 40 41
	}
}

42 43 44 45 46 47 48 49 50 51 52 53
// New constructs a new insecure transport. The provided private key
// is stored and returned from LocalPrivateKey to satisfy the
// SecureTransport interface, and the public key is sent to
// remote peers. No security is provided.
func NewWithIdentity(id peer.ID, key ci.PrivKey) *Transport {
	return &Transport{
		id:  id,
		key: key,
	}
}

// LocalPeer returns the transport's local peer ID.
54 55 56 57
func (t *Transport) LocalPeer() peer.ID {
	return t.id
}

58 59
// LocalPrivateKey returns the local private key.
// This key is used only for identity generation and provides no security.
60
func (t *Transport) LocalPrivateKey() ci.PrivKey {
61
	return t.key
62 63
}

64
// SecureInbound *pretends to secure* an inbound connection to the given peer.
65 66 67 68 69 70
// It sends the local peer's ID and public key, and receives the same from the remote peer.
// No validation is performed as to the authenticity or ownership of the provided public key,
// and the key exchange provides no security.
//
// SecureInbound may fail if the remote peer sends an ID and public key that are inconsistent
// with each other, or if a network error occurs during the ID exchange.
71
func (t *Transport) SecureInbound(ctx context.Context, insecure net.Conn) (sec.SecureConn, error) {
72 73 74 75 76 77 78 79 80 81 82 83
	conn := &Conn{
		Conn:         insecure,
		local:        t.id,
		localPrivKey: t.key,
	}

	err := conn.runHandshakeSync()
	if err != nil {
		return nil, err
	}

	return conn, nil
84 85 86
}

// SecureOutbound *pretends to secure* an outbound connection to the given peer.
87 88 89 90 91 92 93
// It sends the local peer's ID and public key, and receives the same from the remote peer.
// No validation is performed as to the authenticity or ownership of the provided public key,
// and the key exchange provides no security.
//
// SecureOutbound may fail if the remote peer sends an ID and public key that are inconsistent
// with each other, or if the ID sent by the remote peer does not match the one dialed. It may
// also fail if a network error occurs during the ID exchange.
94
func (t *Transport) SecureOutbound(ctx context.Context, insecure net.Conn, p peer.ID) (sec.SecureConn, error) {
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
	conn := &Conn{
		Conn:         insecure,
		local:        t.id,
		localPrivKey: t.key,
	}

	err := conn.runHandshakeSync()
	if err != nil {
		return nil, err
	}

	if t.key != nil && p != conn.remote {
		return nil, fmt.Errorf("remote peer sent unexpected peer ID. expected=%s received=%s",
			p, conn.remote)
	}

	return conn, nil
112 113 114 115 116
}

// Conn is the connection type returned by the insecure transport.
type Conn struct {
	net.Conn
117

118 119
	local  peer.ID
	remote peer.ID
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153

	localPrivKey ci.PrivKey
	remotePubKey ci.PubKey
}

func makeExchangeMessage(pubkey ci.PubKey) (*pb.Exchange, error) {
	keyMsg, err := ci.PublicKeyToProto(pubkey)
	if err != nil {
		return nil, err
	}
	id, err := peer.IDFromPublicKey(pubkey)
	if err != nil {
		return nil, err
	}

	return &pb.Exchange{
		Id:     []byte(id),
		Pubkey: keyMsg,
	}, nil
}

func (ic *Conn) runHandshakeSync() error {
	// If we were initialized without keys, behave as in plaintext/1.0.0 (do nothing)
	if ic.localPrivKey == nil {
		return nil
	}

	// Generate an Exchange message
	msg, err := makeExchangeMessage(ic.localPrivKey.GetPublic())
	if err != nil {
		return err
	}

	// Send our Exchange and read theirs
154
	remoteMsg, err := readWriteMsg(ic.Conn, msg)
155 156 157 158 159 160 161 162 163 164
	if err != nil {
		return err
	}

	// Pull remote ID and public key from message
	remotePubkey, err := ci.PublicKeyFromProto(remoteMsg.Pubkey)
	if err != nil {
		return err
	}

165
	remoteID, err := peer.IDFromBytes(remoteMsg.Id)
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
	if err != nil {
		return err
	}

	// Validate that ID matches public key
	if !remoteID.MatchesPublicKey(remotePubkey) {
		calculatedID, _ := peer.IDFromPublicKey(remotePubkey)
		return fmt.Errorf("remote peer id does not match public key. id=%s calculated_id=%s",
			remoteID, calculatedID)
	}

	// Add remote ID and key to conn state
	ic.remotePubKey = remotePubkey
	ic.remote = remoteID
	return nil
}

// read and write a message at the same time.
184
func readWriteMsg(rw io.ReadWriter, out *pb.Exchange) (*pb.Exchange, error) {
185 186 187 188 189 190
	const maxMessageSize = 1 << 16

	outBytes, err := out.Marshal()
	if err != nil {
		return nil, err
	}
191 192
	wresult := make(chan error)
	go func() {
193 194
		w := msgio.NewVarintWriter(rw)
		wresult <- w.WriteMsg(outBytes)
195 196
	}()

197 198
	r := msgio.NewVarintReaderSize(rw, maxMessageSize)
	msg, err1 := r.ReadMsg()
199

200
	// Always wait for the read to finish.
201 202
	err2 := <-wresult

203 204
	if err1 != nil {
		return nil, err1
205 206
	}
	if err2 != nil {
207
		r.ReleaseMsg(msg)
208 209
		return nil, err2
	}
210 211 212
	inMsg := new(pb.Exchange)
	err = inMsg.Unmarshal(msg)
	return inMsg, err
213 214 215 216 217 218 219 220 221 222 223 224 225
}

// LocalPeer returns the local peer ID.
func (ic *Conn) LocalPeer() peer.ID {
	return ic.local
}

// RemotePeer returns the remote peer ID if we initiated the dial. Otherwise, it
// returns "" (because this connection isn't actually secure).
func (ic *Conn) RemotePeer() peer.ID {
	return ic.remote
}

226 227
// RemotePublicKey returns whatever public key was given by the remote peer.
// Note that no verification of ownership is done, as this connection is not secure.
228
func (ic *Conn) RemotePublicKey() ci.PubKey {
229
	return ic.remotePubKey
230 231
}

232
// LocalPrivateKey returns the private key for the local peer.
233
func (ic *Conn) LocalPrivateKey() ci.PrivKey {
234
	return ic.localPrivKey
235 236 237 238
}

var _ sec.SecureTransport = (*Transport)(nil)
var _ sec.SecureConn = (*Conn)(nil)