Skip to content

Commit 10e5de0

Browse files
yacovmguoger
authored andcommitted
[FAB-14852] Validate TLS certs are x509 encoded
This change set adds validation that the TLS certificates in a config update are x509 certificates. Change-Id: Id68202ff1ae47970d76e8435f271329da7ebfaec Signed-off-by: yacovm <yacovm@il.ibm.com>
1 parent fccb78a commit 10e5de0

File tree

2 files changed

+33
-19
lines changed

2 files changed

+33
-19
lines changed

orderer/consensus/etcdraft/chain_test.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1751,15 +1751,26 @@ var _ = Describe("Chain", func() {
17511751
"empty consenter set"))
17521752
})
17531753

1754-
It("fails with invalid certificate", func() {
1754+
It("fails with invalid certificate for non PEM certificates", func() {
17551755
metadata := &raftprotos.ConfigMetadata{Options: options}
17561756
for _, consenter := range consenters {
17571757
metadata.Consenters = append(metadata.Consenters, consenter)
17581758
}
1759-
metadata.Consenters[0].ClientTlsCert = []byte("Hello")
1759+
metadata.Consenters[0].ClientTlsCert = []byte("hello")
17601760

17611761
Expect(c1.Configure(createChannelEnv(metadata), 0)).To(MatchError(
1762-
"invalid client TLS cert: Hello"))
1762+
"client TLS certificate is not PEM encoded: hello"))
1763+
})
1764+
1765+
It("fails with invalid certificate for malformed certificates", func() {
1766+
metadata := &raftprotos.ConfigMetadata{Options: options}
1767+
for _, consenter := range consenters {
1768+
metadata.Consenters = append(metadata.Consenters, consenter)
1769+
}
1770+
metadata.Consenters[0].ServerTlsCert = pem.EncodeToMemory(&pem.Block{Bytes: []byte("hello")})
1771+
1772+
Expect(c1.Configure(createChannelEnv(metadata), 0).Error()).To(ContainSubstring(
1773+
"server TLS certificate has invalid ASN1 structure"))
17631774
})
17641775

17651776
It("fails with extra consenter", func() {
@@ -1830,7 +1841,7 @@ var _ = Describe("Chain", func() {
18301841
c1.cutter.CutNext = true
18311842

18321843
By("sending config transaction")
1833-
Expect(c1.Configure(configEnv, 0)).To(MatchError("invalid server TLS cert: hello"))
1844+
Expect(c1.Configure(configEnv, 0)).To(MatchError("server TLS certificate is not PEM encoded: hello"))
18341845
})
18351846

18361847
It("can rotate certificate by adding and removing 1 node in one config update", func() {

orderer/consensus/etcdraft/util.go

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package etcdraft
88

99
import (
1010
"bytes"
11+
"crypto/x509"
1112
"encoding/pem"
1213
"fmt"
1314
"sync"
@@ -416,12 +417,11 @@ func CheckConfigMetadata(metadata *etcdraft.ConfigMetadata) error {
416417

417418
// sanity check of certificates
418419
for _, consenter := range metadata.Consenters {
419-
if bl, _ := pem.Decode(consenter.ServerTlsCert); bl == nil {
420-
return errors.Errorf("invalid server TLS cert: %s", string(consenter.ServerTlsCert))
420+
if err := validateCert(consenter.ServerTlsCert, "server"); err != nil {
421+
return err
421422
}
422-
423-
if bl, _ := pem.Decode(consenter.ClientTlsCert); bl == nil {
424-
return errors.Errorf("invalid client TLS cert: %s", string(consenter.ClientTlsCert))
423+
if err := validateCert(consenter.ClientTlsCert, "client"); err != nil {
424+
return err
425425
}
426426
}
427427

@@ -432,6 +432,19 @@ func CheckConfigMetadata(metadata *etcdraft.ConfigMetadata) error {
432432
return nil
433433
}
434434

435+
func validateCert(pemData []byte, certRole string) error {
436+
bl, _ := pem.Decode(pemData)
437+
438+
if bl == nil {
439+
return errors.Errorf("%s TLS certificate is not PEM encoded: %s", certRole, string(pemData))
440+
}
441+
442+
if _, err := x509.ParseCertificate(bl.Bytes); err != nil {
443+
return errors.Errorf("%s TLS certificate has invalid ASN1 structure, %v: %s", certRole, err, string(pemData))
444+
}
445+
return nil
446+
}
447+
435448
// ConsenterCertificate denotes a TLS certificate of a consenter
436449
type ConsenterCertificate []byte
437450

@@ -467,16 +480,6 @@ func (conCert ConsenterCertificate) IsConsenterOfChannel(configBlock *common.Blo
467480
return cluster.ErrNotInChannel
468481
}
469482

470-
// SliceOfConsentersIDs converts maps of consenters into slice of consenters ids
471-
func SliceOfConsentersIDs(consenters map[uint64]*etcdraft.Consenter) []uint64 {
472-
result := make([]uint64, 0)
473-
for id := range consenters {
474-
result = append(result, id)
475-
}
476-
477-
return result
478-
}
479-
480483
// NodeExists returns trues if node id exists in the slice
481484
// and false otherwise
482485
func NodeExists(id uint64, nodes []uint64) bool {

0 commit comments

Comments
 (0)