Compare commits

...

15 Commits

Author SHA1 Message Date
Anton Kaliaev
0545f4c2c0 update changelog and bump version to v0.31.10 2019-10-10 09:01:50 -07:00
Anton Kaliaev
5c9b5cfa1d p2p: only allow ed25519 pubkeys when connecting
also, recover from any possible failures in acceptPeers

Refs #4030
2019-10-10 09:01:50 -07:00
Marko
2cda97eaa9 Merge PR #4029: golangci remove 2019-10-01 23:32:55 -07:00
Anton Kaliaev
dee855cf6b update changelog 2019-10-01 23:32:55 -07:00
Anton Kaliaev
882e854d10 Mergerun profileer in go func 2019-10-01 23:32:55 -07:00
Anton Kaliaev
a4f9c6a5ba Merge node bug fix 2019-10-01 23:32:55 -07:00
Zaki Manian
832a98b1a0 Update CHANGELOG.md
Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com>
2019-10-01 23:32:55 -07:00
Zaki Manian
798354ab95 Update changelog 2019-10-01 23:32:55 -07:00
Zaki Manian
97a63681a8 Update version.go for release 2019-10-01 23:32:55 -07:00
Zaki Manian
9939562bbe Fix for panic in signature verification if a peer sends a nil public key. 2019-10-01 23:32:55 -07:00
Ethan Buchman
cb7aea79db Merge pull request #3843 from tendermint/v0.31.8
v0.31.8 release
2019-07-29 10:16:28 -04:00
Anton Kaliaev
bb9ee2ca28 bump version and update changelog 2019-07-29 17:58:58 +04:00
Ethan Buchman
fe54b3323c Merge pull request #3837 from ruseinov/v0.31.8
V0.31.8
2019-07-29 07:43:40 -04:00
Anton Kaliaev
7924c76815 p2p: dial addrs which came from seed instead of calling ensurePeers (#3762)
Calling ensurePeers outside of ensurePeersRoutine can lead to nodes
disconnecting from us due to "sent next PEX request too soon" error.

Solution is to just dial addrs we got from src instead of calling
ensurePeers.

Refs #2093

Fixes #3338
2019-07-26 11:44:13 +02:00
Roman Useinov
e2775ba0e3 abci/server: recover from app panics in socket server (#3809)
fixes #3800
2019-07-26 11:43:52 +02:00
11 changed files with 203 additions and 21 deletions

View File

@@ -1,5 +1,65 @@
# Changelog
## v0.31.10
*October 8, 2019*
The previous patch was insufficient because the attacker could still find a way
to submit a `nil` pubkey by constructing a `PubKeyMultisigThreshold` pubkey
with `nil` subpubkeys for example.
This release provides multiple fixes, which include recovering from panics when
accepting new peers and only allowing `ed25519` pubkeys.
**All clients are recommended to upgrade**
Special thanks to [fudongbai](https://hackerone.com/fudongbai) for pointing
this out.
Friendly reminder, we have a [bug bounty
program](https://hackerone.com/tendermint).
### SECURITY:
- [p2p] [\#4030](https://github.com/tendermint/tendermint/issues/4030) Only allow ed25519 pubkeys when connecting
## v0.31.9
*September 30, 2019*
This release fixes a major security vulnerability found in the `p2p` package.
All clients are recommended to upgrade. See [TODO](hxxp://githublink) for
details.
Special thanks to [fudongbai](https://hackerone.com/fudongbai) for discovering
and reporting this issue.
Friendly reminder, we have a [bug bounty
program](https://hackerone.com/tendermint).
### SECURITY:
- [p2p] [\#4030](https://github.com/tendermint/tendermint/issues/4030) Fix for panic on nil public key send to a peer
### BUG FIXES:
- [node] [\#3716](https://github.com/tendermint/tendermint/issues/3716) Fix a bug where `nil` is recorded as node's address
- [node] [\#3741](https://github.com/tendermint/tendermint/issues/3741) Fix profiler blocking the entire node
## v0.31.8
*July 29, 2019*
This releases fixes one bug in the PEX reactor and adds a `recover` to the Go's
ABCI server, which allows it to properly cleanup.
### IMPROVEMENTS:
- [abci] [\#3809](https://github.com/tendermint/tendermint/issues/3809) Recover from application panics in `server/socket_server.go` to allow socket cleanup (@ruseinov)
### BUG FIXES:
- [p2p] [\#3338](https://github.com/tendermint/tendermint/issues/3338) Prevent "sent next PEX request too soon" errors by not calling
ensurePeers outside of ensurePeersRoutine
## v0.31.7
*June 3, 2019*
@@ -9,11 +69,11 @@ The regression caused the invalid committed txs to be proposed in blocks over an
over again.
### BUG FIXES:
- [mempool] \#3699 Remove all committed txs from the mempool.
- [mempool] [\#3699](https://github.com/tendermint/tendermint/issues/3699) Remove all committed txs from the mempool.
This reverts the change from v0.31.6 where we only remove valid txs from the mempool.
Note this means malicious proposals can cause txs to be dropped from the
mempools of other nodes by including them in blocks before they are valid.
See \#3322.
See [\#3322](https://github.com/tendermint/tendermint/issues/3322).
## v0.31.6

View File

@@ -1,4 +1,4 @@
## v0.31.8
## v0.31.11
**

View File

@@ -146,6 +146,16 @@ func (s *SocketServer) waitForClose(closeConn chan error, connID int) {
func (s *SocketServer) handleRequests(closeConn chan error, conn net.Conn, responses chan<- *types.Response) {
var count int
var bufReader = bufio.NewReader(conn)
defer func() {
// make sure to recover from any app-related panics to allow proper socket cleanup
r := recover()
if r != nil {
closeConn <- fmt.Errorf("recovered from panic: %v", r)
s.appMtx.Unlock()
}
}()
for {
var req = &types.Request{}
@@ -154,7 +164,7 @@ func (s *SocketServer) handleRequests(closeConn chan error, conn net.Conn, respo
if err == io.EOF {
closeConn <- err
} else {
closeConn <- fmt.Errorf("Error reading message: %v", err.Error())
closeConn <- fmt.Errorf("error reading message: %v", err)
}
return
}

View File

@@ -21,6 +21,11 @@ func NewPubKeyMultisigThreshold(k int, pubkeys []crypto.PubKey) crypto.PubKey {
if len(pubkeys) < k {
panic("threshold k of n multisignature: len(pubkeys) < k")
}
for _, pubkey := range pubkeys {
if pubkey == nil {
panic("nil pubkey")
}
}
return PubKeyMultisigThreshold{uint(k), pubkeys}
}

View File

@@ -441,17 +441,30 @@ func createSwitch(config *cfg.Config,
}
func createAddrBookAndSetOnSwitch(config *cfg.Config, sw *p2p.Switch,
p2pLogger log.Logger) pex.AddrBook {
p2pLogger log.Logger, nodeKey *p2p.NodeKey) (pex.AddrBook, error) {
addrBook := pex.NewAddrBook(config.P2P.AddrBookFile(), config.P2P.AddrBookStrict)
addrBook.SetLogger(p2pLogger.With("book", config.P2P.AddrBookFile()))
// Add ourselves to addrbook to prevent dialing ourselves
addrBook.AddOurAddress(sw.NetAddress())
if config.P2P.ExternalAddress != "" {
addr, err := p2p.NewNetAddressString(p2p.IDAddressString(nodeKey.ID(), config.P2P.ExternalAddress))
if err != nil {
return nil, errors.Wrap(err, "p2p.external_address is incorrect")
}
addrBook.AddOurAddress(addr)
}
if config.P2P.ListenAddress != "" {
addr, err := p2p.NewNetAddressString(p2p.IDAddressString(nodeKey.ID(), config.P2P.ListenAddress))
if err != nil {
return nil, errors.Wrap(err, "p2p.laddr is incorrect")
}
addrBook.AddOurAddress(addr)
}
sw.SetAddrBook(addrBook)
return addrBook
return addrBook, nil
}
func createPEXReactorAndAddToSwitch(addrBook pex.AddrBook, config *cfg.Config,
@@ -594,7 +607,10 @@ func NewNode(config *cfg.Config,
return nil, errors.Wrap(err, "could not add peers from persistent_peers field")
}
addrBook := createAddrBookAndSetOnSwitch(config, sw, p2pLogger)
addrBook, err := createAddrBookAndSetOnSwitch(config, sw, p2pLogger, nodeKey)
if err != nil {
return nil, errors.Wrap(err, "could not create addrbook")
}
// Optionally, start the pex reactor
//
@@ -614,7 +630,9 @@ func NewNode(config *cfg.Config,
}
if config.ProfListenAddress != "" {
go logger.Error("Profile server", "err", http.ListenAndServe(config.ProfListenAddress, nil))
go func() {
logger.Error("Profile server", "err", http.ListenAndServe(config.ProfListenAddress, nil))
}()
}
node := &Node{

View File

@@ -6,20 +6,21 @@ import (
"crypto/sha256"
"crypto/subtle"
"encoding/binary"
"errors"
"io"
"math"
"net"
"sync"
"time"
"github.com/pkg/errors"
"golang.org/x/crypto/chacha20poly1305"
"golang.org/x/crypto/curve25519"
"golang.org/x/crypto/hkdf"
"golang.org/x/crypto/nacl/box"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/ed25519"
cmn "github.com/tendermint/tendermint/libs/common"
"golang.org/x/crypto/hkdf"
)
// 4 + 1024 == 1028 total frame size
@@ -122,8 +123,13 @@ func MakeSecretConnection(conn io.ReadWriteCloser, locPrivKey crypto.PrivKey) (*
}
remPubKey, remSignature := authSigMsg.Key, authSigMsg.Sig
if _, ok := remPubKey.(ed25519.PubKeyEd25519); !ok {
return nil, errors.Errorf("expected ed25519 pubkey, got %T", remPubKey)
}
if !remPubKey.VerifyBytes(challenge[:], remSignature) {
return nil, errors.New("Challenge verification failed")
return nil, errors.New("challenge verification failed")
}
// We've authorized.
@@ -205,7 +211,7 @@ func (sc *SecretConnection) Read(data []byte) (n int, err error) {
var frame = make([]byte, totalFrameSize)
_, err = aead.Open(frame[:0], sc.recvNonce[:], sealedFrame, nil)
if err != nil {
return n, errors.New("Failed to decrypt SecretConnection")
return n, errors.New("failed to decrypt SecretConnection")
}
incrNonce(sc.recvNonce)
// end decryption

View File

@@ -17,7 +17,9 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/crypto/secp256k1"
cmn "github.com/tendermint/tendermint/libs/common"
)
@@ -363,6 +365,51 @@ func TestDeriveSecretsAndChallengeGolden(t *testing.T) {
}
}
type privKeyWithNilPubKey struct {
orig crypto.PrivKey
}
func (pk privKeyWithNilPubKey) Bytes() []byte { return pk.orig.Bytes() }
func (pk privKeyWithNilPubKey) Sign(msg []byte) ([]byte, error) { return pk.orig.Sign(msg) }
func (pk privKeyWithNilPubKey) PubKey() crypto.PubKey { return nil }
func (pk privKeyWithNilPubKey) Equals(pk2 crypto.PrivKey) bool { return pk.orig.Equals(pk2) }
func TestNilPubkey(t *testing.T) {
var fooConn, barConn = makeKVStoreConnPair()
var fooPrvKey = ed25519.GenPrivKey()
var barPrvKey = privKeyWithNilPubKey{ed25519.GenPrivKey()}
go func() {
_, err := MakeSecretConnection(barConn, barPrvKey)
assert.NoError(t, err)
}()
assert.NotPanics(t, func() {
_, err := MakeSecretConnection(fooConn, fooPrvKey)
if assert.Error(t, err) {
assert.Equal(t, "expected ed25519 pubkey, got <nil>", err.Error())
}
})
}
func TestNonEd25519Pubkey(t *testing.T) {
var fooConn, barConn = makeKVStoreConnPair()
var fooPrvKey = ed25519.GenPrivKey()
var barPrvKey = secp256k1.GenPrivKey()
go func() {
_, err := MakeSecretConnection(barConn, barPrvKey)
assert.NoError(t, err)
}()
assert.NotPanics(t, func() {
_, err := MakeSecretConnection(fooConn, fooPrvKey)
if assert.Error(t, err) {
assert.Equal(t, "expected ed25519 pubkey, got secp256k1.PubKeySecp256k1", err.Error())
}
})
}
// Creates the data for a test vector file.
// The file format is:
// Hex(diffie_hellman_secret), loc_is_least, Hex(recvSecret), Hex(sendSecret), Hex(challenge)

View File

@@ -340,6 +340,15 @@ func (r *PEXReactor) ReceiveAddrs(addrs []*p2p.NetAddress, src Peer) error {
if err != nil {
return err
}
srcIsSeed := false
for _, seedAddr := range r.seedAddrs {
if seedAddr.Equals(srcAddr) {
srcIsSeed = true
break
}
}
for _, netAddr := range addrs {
// Validate netAddr. Disconnect from a peer if it sends us invalid data.
if netAddr == nil {
@@ -365,13 +374,23 @@ func (r *PEXReactor) ReceiveAddrs(addrs []*p2p.NetAddress, src Peer) error {
}
// If this address came from a seed node, try to connect to it without
// waiting.
for _, seedAddr := range r.seedAddrs {
if seedAddr.Equals(srcAddr) {
r.ensurePeers()
}
// waiting (#2093)
if srcIsSeed {
r.Logger.Info("Will dial address, which came from seed", "addr", netAddr, "seed", srcAddr)
go func(addr *p2p.NetAddress) {
err := r.dialPeer(addr)
if err != nil {
switch err.(type) {
case errMaxAttemptsToDial, errTooEarlyToDial:
r.Logger.Debug(err.Error(), "addr", addr)
default:
r.Logger.Error(err.Error(), "addr", addr)
}
}
}(netAddr)
}
}
return nil
}

View File

@@ -6,6 +6,8 @@ import (
"net"
"time"
"github.com/pkg/errors"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/p2p/conn"
)
@@ -270,6 +272,23 @@ func (mt *MultiplexTransport) acceptPeers() {
//
// [0] https://en.wikipedia.org/wiki/Head-of-line_blocking
go func(c net.Conn) {
defer func() {
if r := recover(); r != nil {
err := ErrRejected{
conn: c,
err: errors.Errorf("recovered from panic: %v", r),
isAuthFailure: true,
}
select {
case mt.acceptc <- accept{err: err}:
case <-mt.closec:
// Give up if the transport was closed.
_ = c.Close()
return
}
}
}()
var (
nodeInfo NodeInfo
secretConn *conn.SecretConnection

View File

@@ -59,8 +59,6 @@ installFromGithub square/certstrap e27060a3643e814151e65b9807b6b06d169580a7
# used to build tm-monitor & tm-bench binaries
installFromGithub mitchellh/gox 51ed453898ca5579fea9ad1f08dff6b121d9f2e8
## golangci-lint v1.13.2
installFromGithub golangci/golangci-lint 7b2421d55194c9dc385eff7720a037aa9244ca3c cmd/golangci-lint
## make test_with_deadlock
## XXX: https://github.com/tendermint/tendermint/issues/3242

View File

@@ -20,7 +20,7 @@ const (
// Must be a string because scripts like dist.sh read this file.
// XXX: Don't change the name of this variable or you will break
// automation :)
TMCoreSemVer = "0.31.7"
TMCoreSemVer = "0.31.10"
// ABCISemVer is the semantic version of the ABCI library
ABCISemVer = "0.16.0"