Commit de3f35a2 authored by Marten Seemann's avatar Marten Seemann
Browse files

verify the server's certificate using tls.Config.VerifyPeerCertificate

Fixes #2.
parent c8b9d442
...@@ -9,4 +9,3 @@ This is an implementation of the [libp2p transport](https://github.com/libp2p/go ...@@ -9,4 +9,3 @@ This is an implementation of the [libp2p transport](https://github.com/libp2p/go
## Known limitations ## Known limitations
* currently only works with RSA host keys * currently only works with RSA host keys
* [#2](https://github.com/marten-seemann/libp2p-quic-transport/issues/2)
...@@ -80,14 +80,14 @@ var _ = Describe("Connection", func() { ...@@ -80,14 +80,14 @@ var _ = Describe("Connection", func() {
thirdPartyID, err := peer.IDFromPrivateKey(createPeer()) thirdPartyID, err := peer.IDFromPrivateKey(createPeer())
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
serverAddrChan, _ := runServer() serverAddrChan, serverConnChan := runServer()
clientTransport, err := NewTransport(clientKey) clientTransport, err := NewTransport(clientKey)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
serverAddr := <-serverAddrChan serverAddr := <-serverAddrChan
// dial, but expect the wrong peer ID // dial, but expect the wrong peer ID
_, err = clientTransport.Dial(context.Background(), serverAddr, thirdPartyID) _, err = clientTransport.Dial(context.Background(), serverAddr, thirdPartyID)
Expect(err).To(MatchError("peer IDs don't match")) Expect(err).To(HaveOccurred())
// TODO(#2): don't accept a connection if the client's peer verification fails Expect(err.Error()).To(ContainSubstring("TLS handshake error: bad certificate"))
// Consistently(serverConnChan).ShouldNot(Receive()) Consistently(serverConnChan).ShouldNot(Receive())
}) })
}) })
...@@ -10,8 +10,6 @@ import ( ...@@ -10,8 +10,6 @@ import (
"math/big" "math/big"
"time" "time"
"github.com/lucas-clemente/quic-go"
"github.com/gogo/protobuf/proto" "github.com/gogo/protobuf/proto"
ic "github.com/libp2p/go-libp2p-crypto" ic "github.com/libp2p/go-libp2p-crypto"
pb "github.com/libp2p/go-libp2p-crypto/pb" pb "github.com/libp2p/go-libp2p-crypto/pb"
...@@ -20,10 +18,6 @@ import ( ...@@ -20,10 +18,6 @@ import (
// mint certificate selection is broken. // mint certificate selection is broken.
const hostname = "quic.ipfs" const hostname = "quic.ipfs"
type connectionStater interface {
ConnectionState() quic.ConnectionState
}
// TODO: make this private // TODO: make this private
func GenerateConfig(privKey ic.PrivKey) (*tls.Config, error) { func GenerateConfig(privKey ic.PrivKey) (*tls.Config, error) {
key, hostCert, err := keyToCertificate(privKey) key, hostCert, err := keyToCertificate(privKey)
...@@ -63,17 +57,16 @@ func GenerateConfig(privKey ic.PrivKey) (*tls.Config, error) { ...@@ -63,17 +57,16 @@ func GenerateConfig(privKey ic.PrivKey) (*tls.Config, error) {
}, nil }, nil
} }
func getRemotePubKey(conn connectionStater) (ic.PubKey, error) { func getRemotePubKey(chain []*x509.Certificate) (ic.PubKey, error) {
certChain := conn.ConnectionState().PeerCertificates if len(chain) != 2 {
if len(certChain) != 2 {
return nil, errors.New("expected 2 certificates in the chain") return nil, errors.New("expected 2 certificates in the chain")
} }
pool := x509.NewCertPool() pool := x509.NewCertPool()
pool.AddCert(certChain[1]) pool.AddCert(chain[1])
if _, err := certChain[0].Verify(x509.VerifyOptions{Roots: pool}); err != nil { if _, err := chain[0].Verify(x509.VerifyOptions{Roots: pool}); err != nil {
return nil, err return nil, err
} }
remotePubKey, err := x509.MarshalPKIXPublicKey(certChain[1].PublicKey) remotePubKey, err := x509.MarshalPKIXPublicKey(chain[1].PublicKey)
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -60,7 +60,7 @@ func (l *listener) Accept() (tpt.Conn, error) { ...@@ -60,7 +60,7 @@ func (l *listener) Accept() (tpt.Conn, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
remotePubKey, err := getRemotePubKey(sess) remotePubKey, err := getRemotePubKey(sess.ConnectionState().PeerCertificates)
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -2,6 +2,7 @@ package libp2pquic ...@@ -2,6 +2,7 @@ package libp2pquic
import ( import (
"context" "context"
"crypto/x509"
"errors" "errors"
ic "github.com/libp2p/go-libp2p-crypto" ic "github.com/libp2p/go-libp2p-crypto"
...@@ -45,11 +46,27 @@ func (t *transport) Dial(ctx context.Context, raddr ma.Multiaddr, p peer.ID) (tp ...@@ -45,11 +46,27 @@ func (t *transport) Dial(ctx context.Context, raddr ma.Multiaddr, p peer.ID) (tp
if err != nil { if err != nil {
return nil, err return nil, err
} }
sess, err := quicDialAddr(host, tlsConf, &quic.Config{Versions: []quic.VersionNumber{101}}) var remotePubKey ic.PubKey
if err != nil { tlsConf.VerifyPeerCertificate = func(rawCerts [][]byte, _ [][]*x509.Certificate) error {
return nil, err 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 { if err != nil {
return nil, err return nil, err
} }
...@@ -57,11 +74,6 @@ func (t *transport) Dial(ctx context.Context, raddr ma.Multiaddr, p peer.ID) (tp ...@@ -57,11 +74,6 @@ func (t *transport) Dial(ctx context.Context, raddr ma.Multiaddr, p peer.ID) (tp
if err != nil { if err != nil {
return nil, err return nil, err
} }
if !p.MatchesPublicKey(remotePubKey) {
err := errors.New("peer IDs don't match")
sess.Close(err)
return nil, err
}
return &conn{ return &conn{
privKey: t.privKey, privKey: t.privKey,
localPeer: t.localPeer, localPeer: t.localPeer,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment