Skip to content
This repository has been archived by the owner on Oct 13, 2022. It is now read-only.

Commit

Permalink
initialize a certiticate manager and pass it to the listeners
Browse files Browse the repository at this point in the history
  • Loading branch information
marten-seemann committed Apr 18, 2022
1 parent a13cabb commit f196900
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 29 deletions.
31 changes: 11 additions & 20 deletions listener.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"crypto/tls"
"errors"
"github.com/lucas-clemente/quic-go/http3"
"net"
"net/http"
"time"
Expand All @@ -13,11 +12,10 @@ import (

noise "github.com/libp2p/go-libp2p-noise"

"github.com/lucas-clemente/quic-go/http3"
"github.com/marten-seemann/webtransport-go"
ma "github.com/multiformats/go-multiaddr"
manet "github.com/multiformats/go-multiaddr/net"
"github.com/multiformats/go-multibase"
"github.com/multiformats/go-multihash"
)

var errClosed = errors.New("closed")
Expand All @@ -26,11 +24,11 @@ const queueLen = 16
const handshakeTimeout = 10 * time.Second

type listener struct {
transport tpt.Transport
noise *noise.Transport
transport tpt.Transport
noise *noise.Transport
certManager *certManager

server webtransport.Server
tlsConf *tls.Config
server webtransport.Server

ctx context.Context
ctxCancel context.CancelFunc
Expand All @@ -45,7 +43,7 @@ type listener struct {

var _ tpt.Listener = &listener{}

func newListener(laddr ma.Multiaddr, tlsConf *tls.Config, transport tpt.Transport, noise *noise.Transport) (tpt.Listener, error) {
func newListener(laddr ma.Multiaddr, transport tpt.Transport, noise *noise.Transport, certManager *certManager) (tpt.Listener, error) {
network, addr, err := manet.DialArgs(laddr)
if err != nil {
return nil, err
Expand All @@ -65,15 +63,17 @@ func newListener(laddr ma.Multiaddr, tlsConf *tls.Config, transport tpt.Transpor
ln := &listener{
transport: transport,
noise: noise,
certManager: certManager,
queue: make(chan *webtransport.Conn, queueLen),
serverClosed: make(chan struct{}),
addr: udpConn.LocalAddr(),
tlsConf: tlsConf,
multiaddr: localMultiaddr,
server: webtransport.Server{
H3: http3.Server{
Server: &http.Server{
TLSConfig: tlsConf,
TLSConfig: &tls.Config{GetConfigForClient: func(*tls.ClientHelloInfo) (*tls.Config, error) {
return certManager.GetConfig(), nil
}},
},
},
},
Expand Down Expand Up @@ -154,16 +154,7 @@ func (l *listener) Addr() net.Addr {
}

func (l *listener) Multiaddr() ma.Multiaddr {
certHash := certificateHash(l.tlsConf)
h, err := multihash.Encode(certHash[:], multihash.SHA2_256)
if err != nil {
panic(err)
}
certHashStr, err := multibase.Encode(multibase.Base58BTC, h)
if err != nil {
panic(err)
}
return l.multiaddr.Encapsulate(ma.StringCast("/certhash/" + certHashStr))
return l.multiaddr.Encapsulate(l.certManager.AddrComponent())
}

func (l *listener) Close() error {
Expand Down
22 changes: 13 additions & 9 deletions transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"crypto/tls"
"fmt"
"sync"
"time"

ic "github.com/libp2p/go-libp2p-core/crypto"
Expand All @@ -29,8 +30,11 @@ type transport struct {
privKey ic.PrivKey
pid peer.ID

tlsConf *tls.Config
dialer webtransport.Dialer
dialer webtransport.Dialer

listenOnce sync.Once
listenOnceErr error
certManager *certManager

noise *noise.Transport
}
Expand All @@ -42,19 +46,13 @@ func New(key ic.PrivKey) (tpt.Transport, error) {
if err != nil {
return nil, err
}
now := time.Now()
tlsConf, err := getTLSConf(now, now.Add(certValidity)) // TODO: only do this when initializing a listener
if err != nil {
return nil, err
}
noise, err := noise.New(key)
if err != nil {
return nil, err
}
return &transport{
pid: id,
privKey: key,
tlsConf: tlsConf,
dialer: webtransport.Dialer{
TLSClientConf: &tls.Config{InsecureSkipVerify: true}, // TODO: verify certificate,
},
Expand Down Expand Up @@ -129,7 +127,13 @@ func (t *transport) Listen(laddr ma.Multiaddr) (tpt.Listener, error) {
if !webtransportMatcher.Matches(laddr) {
return nil, fmt.Errorf("cannot listen on non-WebTransport addr: %s", laddr)
}
return newListener(laddr, t.tlsConf, t, t.noise)
t.listenOnce.Do(func() {
t.certManager, t.listenOnceErr = newCertManager(certValidity)
})
if t.listenOnceErr != nil {
return nil, t.listenOnceErr
}
return newListener(laddr, t, t.noise, t.certManager)
}

func (t *transport) Protocols() []int {
Expand Down
26 changes: 26 additions & 0 deletions transport_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,17 @@ func randomMultihash(t *testing.T) string {
return s
}

func extractCertHashes(t *testing.T, addr ma.Multiaddr) []string {
var certHashesStr []string
ma.ForEach(addr, func(c ma.Component) bool {
if c.Protocol().Code == ma.P_CERTHASH {
certHashesStr = append(certHashesStr, c.Value())
}
return true
})
return certHashesStr
}

func TestTransport(t *testing.T) {
serverID, serverKey := newIdentity(t)
tr, err := libp2pwebtransport.New(serverKey)
Expand Down Expand Up @@ -112,3 +123,18 @@ func TestListenAddrValidity(t *testing.T) {
require.Errorf(t, err, "expected to not be able to listen on %s", addr)
}
}

func TestListenerAddrs(t *testing.T) {
_, key := newIdentity(t)
tr, err := libp2pwebtransport.New(key)
require.NoError(t, err)

ln1, err := tr.Listen(ma.StringCast("/ip4/127.0.0.1/udp/0/quic/webtransport"))
require.NoError(t, err)
ln2, err := tr.Listen(ma.StringCast("/ip4/127.0.0.1/udp/0/quic/webtransport"))
require.NoError(t, err)
hashes1 := extractCertHashes(t, ln1.Multiaddr())
require.Len(t, hashes1, 1)
hashes2 := extractCertHashes(t, ln2.Multiaddr())
require.Equal(t, hashes1, hashes2)
}

0 comments on commit f196900

Please sign in to comment.