Skip to content

Commit

Permalink
verify the server's certificate using tls.Config.VerifyPeerCertificate
Browse files Browse the repository at this point in the history
Fixes #2.
  • Loading branch information
marten-seemann committed Feb 22, 2018
1 parent 5eaaf4c commit 1b0d978
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 26 deletions.
8 changes: 4 additions & 4 deletions p2p/transport/quic/conn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,14 @@ var _ = Describe("Connection", func() {
thirdPartyID, err := peer.IDFromPrivateKey(createPeer())
Expect(err).ToNot(HaveOccurred())

serverAddrChan, _ := runServer()
serverAddrChan, serverConnChan := runServer()
clientTransport, err := NewTransport(clientKey)
Expect(err).ToNot(HaveOccurred())
serverAddr := <-serverAddrChan
// dial, but expect the wrong peer ID
_, err = clientTransport.Dial(context.Background(), serverAddr, thirdPartyID)
Expect(err).To(MatchError("peer IDs don't match"))
// TODO(#2): don't accept a connection if the client's peer verification fails
// Consistently(serverConnChan).ShouldNot(Receive())
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("TLS handshake error: bad certificate"))
Consistently(serverConnChan).ShouldNot(Receive())
})
})
17 changes: 5 additions & 12 deletions p2p/transport/quic/crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import (
"math/big"
"time"

"github.com/lucas-clemente/quic-go"

"github.com/gogo/protobuf/proto"
ic "github.com/libp2p/go-libp2p-crypto"
pb "github.com/libp2p/go-libp2p-crypto/pb"
Expand All @@ -20,10 +18,6 @@ import (
// mint certificate selection is broken.
const hostname = "quic.ipfs"

type connectionStater interface {
ConnectionState() quic.ConnectionState
}

// TODO: make this private
func GenerateConfig(privKey ic.PrivKey) (*tls.Config, error) {
key, hostCert, err := keyToCertificate(privKey)
Expand Down Expand Up @@ -63,17 +57,16 @@ func GenerateConfig(privKey ic.PrivKey) (*tls.Config, error) {
}, nil
}

func getRemotePubKey(conn connectionStater) (ic.PubKey, error) {
certChain := conn.ConnectionState().PeerCertificates
if len(certChain) != 2 {
func getRemotePubKey(chain []*x509.Certificate) (ic.PubKey, error) {
if len(chain) != 2 {
return nil, errors.New("expected 2 certificates in the chain")
}
pool := x509.NewCertPool()
pool.AddCert(certChain[1])
if _, err := certChain[0].Verify(x509.VerifyOptions{Roots: pool}); err != nil {
pool.AddCert(chain[1])
if _, err := chain[0].Verify(x509.VerifyOptions{Roots: pool}); err != nil {
return nil, err
}
remotePubKey, err := x509.MarshalPKIXPublicKey(certChain[1].PublicKey)
remotePubKey, err := x509.MarshalPKIXPublicKey(chain[1].PublicKey)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion p2p/transport/quic/listener.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func (l *listener) Accept() (tpt.Conn, error) {
if err != nil {
return nil, err
}
remotePubKey, err := getRemotePubKey(sess)
remotePubKey, err := getRemotePubKey(sess.ConnectionState().PeerCertificates)
if err != nil {
return nil, err
}
Expand Down
30 changes: 21 additions & 9 deletions p2p/transport/quic/transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package libp2pquic

import (
"context"
"crypto/x509"
"errors"

ic "github.com/libp2p/go-libp2p-crypto"
Expand Down Expand Up @@ -45,23 +46,34 @@ func (t *transport) Dial(ctx context.Context, raddr ma.Multiaddr, p peer.ID) (tp
if err != nil {
return nil, err
}
sess, err := quicDialAddr(host, tlsConf, &quic.Config{Versions: []quic.VersionNumber{101}})
if err != nil {
return nil, err
var remotePubKey ic.PubKey
tlsConf.VerifyPeerCertificate = func(rawCerts [][]byte, _ [][]*x509.Certificate) error {
chain := make([]*x509.Certificate, len(rawCerts))
for i := 0; i < len(rawCerts); i++ {
cert, err := x509.ParseCertificate(rawCerts[i])
if err != nil {
return err
}
chain[i] = cert
}
var err error
remotePubKey, err = getRemotePubKey(chain)
if err != nil {
return err
}
if !p.MatchesPublicKey(remotePubKey) {
return errors.New("peer IDs don't match")
}
return nil
}
remotePubKey, err := getRemotePubKey(sess)
sess, err := quicDialAddr(host, tlsConf, &quic.Config{Versions: []quic.VersionNumber{101}})
if err != nil {
return nil, err
}
localMultiaddr, err := quicMultiaddr(sess.LocalAddr())
if err != nil {
return nil, err
}
if !p.MatchesPublicKey(remotePubKey) {
err := errors.New("peer IDs don't match")
sess.Close(err)
return nil, err
}
return &conn{
privKey: t.privKey,
localPeer: t.localPeer,
Expand Down

0 comments on commit 1b0d978

Please sign in to comment.