LAN connection string (#2653)
* Version bump * Implemented lan connection string functionality Also added more robust testing * Added ConnectionParams struct and related funcs * Add server mode to ConnectionParams
This commit is contained in:
parent
7f149f93c1
commit
05b8ddf57a
2
go.mod
2
go.mod
|
@ -15,6 +15,7 @@ replace github.com/raulk/go-watchdog v1.2.0 => github.com/status-im/go-watchdog
|
|||
require (
|
||||
github.com/anacrolix/torrent v1.41.0
|
||||
github.com/beevik/ntp v0.2.0
|
||||
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce
|
||||
github.com/cenkalti/backoff/v3 v3.2.2
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/deckarep/golang-set v1.8.0
|
||||
|
@ -104,7 +105,6 @@ require (
|
|||
github.com/bits-and-blooms/bitset v1.2.0 // indirect
|
||||
github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8 // indirect
|
||||
github.com/btcsuite/btcd v0.22.0-beta // indirect
|
||||
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.1 // indirect
|
||||
github.com/cheekybits/genny v1.0.0 // indirect
|
||||
github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327 // indirect
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"net"
|
||||
"time"
|
||||
|
@ -110,13 +111,8 @@ func PublicTLSCert() (string, error) {
|
|||
return globalPem, nil
|
||||
}
|
||||
|
||||
func GenerateCertFromKey(pk *ecdsa.PrivateKey, ttl time.Duration, hostname string) (tls.Certificate, []byte, error) {
|
||||
// TODO fix, this isn't deterministic,
|
||||
|
||||
notBefore := time.Now()
|
||||
notAfter := notBefore.Add(ttl)
|
||||
|
||||
cert := GenerateX509Cert(makeSerialNumberFromKey(pk), notBefore, notAfter, hostname)
|
||||
func GenerateCertFromKey(pk *ecdsa.PrivateKey, from time.Time, hostname string) (tls.Certificate, []byte, error) {
|
||||
cert := GenerateX509Cert(makeSerialNumberFromKey(pk), from, from.Add(time.Hour), hostname)
|
||||
certPem, keyPem, err := GenerateX509PEMs(cert, pk)
|
||||
if err != nil {
|
||||
return tls.Certificate{}, nil, err
|
||||
|
@ -127,6 +123,16 @@ func GenerateCertFromKey(pk *ecdsa.PrivateKey, ttl time.Duration, hostname strin
|
|||
return tls.Certificate{}, nil, err
|
||||
}
|
||||
|
||||
block, _ := pem.Decode(certPem)
|
||||
if block == nil {
|
||||
return tls.Certificate{}, nil, fmt.Errorf("failed to decode certPem")
|
||||
}
|
||||
leaf, err := x509.ParseCertificate(block.Bytes)
|
||||
if err != nil {
|
||||
return tls.Certificate{}, nil, err
|
||||
}
|
||||
tlsCert.Leaf = leaf
|
||||
|
||||
return tlsCert, certPem, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"math/big"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
@ -15,54 +12,19 @@ func TestCerts(t *testing.T) {
|
|||
suite.Run(t, new(CertsSuite))
|
||||
}
|
||||
|
||||
const (
|
||||
X = "7744735542292224619198421067303535767629647588258222392379329927711683109548"
|
||||
Y = "6855516769916529066379811647277920115118980625614889267697023742462401590771"
|
||||
D = "38564357061962143106230288374146033267100509055924181407058066820384455255240"
|
||||
DB58 = "6jpbvo2ucrtrnpXXF4DQYuysh697isH9ppd2aT8uSRDh"
|
||||
SN = "91849736469742262272885892667727604096707836853856473239722372976236128900962"
|
||||
)
|
||||
|
||||
type CertsSuite struct {
|
||||
suite.Suite
|
||||
|
||||
X *big.Int
|
||||
Y *big.Int
|
||||
D *big.Int
|
||||
DBytes []byte
|
||||
SN *big.Int
|
||||
TestKeyComponents
|
||||
TestCertComponents
|
||||
}
|
||||
|
||||
func (s *CertsSuite) SetupSuite() {
|
||||
var ok bool
|
||||
|
||||
s.X, ok = new(big.Int).SetString(X, 10)
|
||||
s.Require().True(ok)
|
||||
|
||||
s.Y, ok = new(big.Int).SetString(Y, 10)
|
||||
s.Require().True(ok)
|
||||
|
||||
s.D, ok = new(big.Int).SetString(D, 10)
|
||||
s.Require().True(ok)
|
||||
|
||||
s.DBytes = base58.Decode(DB58)
|
||||
s.Require().Exactly(s.D.Bytes(), s.DBytes)
|
||||
|
||||
s.SN, ok = new(big.Int).SetString(SN, 10)
|
||||
s.Require().True(ok)
|
||||
s.SetupKeyComponents(s.T())
|
||||
s.SetupCertComponents(s.T())
|
||||
}
|
||||
|
||||
func (s *CertsSuite) Test_makeSerialNumberFromKey() {
|
||||
pk := &ecdsa.PrivateKey{
|
||||
PublicKey: ecdsa.PublicKey{
|
||||
Curve: elliptic.P256(),
|
||||
X: s.X,
|
||||
Y: s.Y,
|
||||
},
|
||||
D: s.D,
|
||||
}
|
||||
|
||||
s.Require().Zero(makeSerialNumberFromKey(pk).Cmp(s.SN))
|
||||
s.Require().Zero(makeSerialNumberFromKey(s.PK).Cmp(s.SN))
|
||||
}
|
||||
|
||||
func (s *CertsSuite) TestToECDSA() {
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"encoding/asn1"
|
||||
"math/big"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcutil/base58"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
const (
|
||||
X = "7744735542292224619198421067303535767629647588258222392379329927711683109548"
|
||||
Y = "6855516769916529066379811647277920115118980625614889267697023742462401590771"
|
||||
D = "38564357061962143106230288374146033267100509055924181407058066820384455255240"
|
||||
DB58 = "6jpbvo2ucrtrnpXXF4DQYuysh697isH9ppd2aT8uSRDh"
|
||||
SN = "91849736469742262272885892667727604096707836853856473239722372976236128900962"
|
||||
CertTime = "eQUriVtGtkWhPJFeLZjF"
|
||||
)
|
||||
|
||||
type TestKeyComponents struct {
|
||||
X *big.Int
|
||||
Y *big.Int
|
||||
D *big.Int
|
||||
DBytes []byte
|
||||
PK *ecdsa.PrivateKey
|
||||
}
|
||||
|
||||
func (tk *TestKeyComponents) SetupKeyComponents(t *testing.T) {
|
||||
var ok bool
|
||||
|
||||
tk.X, ok = new(big.Int).SetString(X, 10)
|
||||
require.True(t, ok)
|
||||
|
||||
tk.Y, ok = new(big.Int).SetString(Y, 10)
|
||||
require.True(t, ok)
|
||||
|
||||
tk.D, ok = new(big.Int).SetString(D, 10)
|
||||
require.True(t, ok)
|
||||
|
||||
tk.DBytes = base58.Decode(DB58)
|
||||
require.Exactly(t, tk.D.Bytes(), tk.DBytes)
|
||||
|
||||
tk.PK = &ecdsa.PrivateKey{
|
||||
PublicKey: ecdsa.PublicKey{
|
||||
Curve: elliptic.P256(),
|
||||
X: tk.X,
|
||||
Y: tk.Y,
|
||||
},
|
||||
D: tk.D,
|
||||
}
|
||||
}
|
||||
|
||||
type TestCertComponents struct {
|
||||
NotBefore, NotAfter time.Time
|
||||
SN *big.Int
|
||||
}
|
||||
|
||||
func (tcc *TestCertComponents) SetupCertComponents(t *testing.T) {
|
||||
var ok bool
|
||||
|
||||
tcc.SN, ok = new(big.Int).SetString(SN, 10)
|
||||
require.True(t, ok)
|
||||
|
||||
_, err := asn1.Unmarshal(base58.Decode(CertTime), &tcc.NotBefore)
|
||||
require.NoError(t, err)
|
||||
|
||||
tcc.NotAfter = tcc.NotBefore.Add(time.Hour)
|
||||
}
|
|
@ -0,0 +1,196 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"encoding/asn1"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"net"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcutil/base58"
|
||||
)
|
||||
|
||||
type ConnectionParamVersion int
|
||||
type Mode int
|
||||
|
||||
const (
|
||||
Version1 ConnectionParamVersion = iota + 1
|
||||
)
|
||||
|
||||
const (
|
||||
Receiving Mode = iota + 1
|
||||
Sending
|
||||
)
|
||||
|
||||
type ConnectionParams struct {
|
||||
version ConnectionParamVersion
|
||||
netIP net.IP
|
||||
port int
|
||||
privateKey *ecdsa.PrivateKey
|
||||
notBefore time.Time
|
||||
serverMode Mode
|
||||
}
|
||||
|
||||
func NewConnectionParams(netIP net.IP, port int, privateKey *ecdsa.PrivateKey, notBefore time.Time, mode Mode) *ConnectionParams {
|
||||
cp := new(ConnectionParams)
|
||||
cp.version = Version1
|
||||
cp.netIP = netIP
|
||||
cp.port = port
|
||||
cp.privateKey = privateKey
|
||||
cp.notBefore = notBefore
|
||||
cp.serverMode = mode
|
||||
return cp
|
||||
}
|
||||
|
||||
// ToString generates a string required for generating a secure connection to another Status device.
|
||||
//
|
||||
// The returned string will look like below:
|
||||
// - "2:4FHRnp:H6G:6jpbvo2ucrtrnpXXF4DQYuysh697isH9ppd2aT8uSRDh:eQUriVtGtkWhPJFeLZjF:2"
|
||||
//
|
||||
// Format bytes encoded into a base58 string, delimited by ":"
|
||||
// - version
|
||||
// - net.IP
|
||||
// - port
|
||||
// - ecdsa.PrivateKey D field
|
||||
// - asn1.Marshal time.Time
|
||||
// - server mode
|
||||
func (cp *ConnectionParams) ToString() (string, error) {
|
||||
v := base58.Encode(new(big.Int).SetInt64(int64(cp.version)).Bytes())
|
||||
ip := base58.Encode(cp.netIP)
|
||||
p := base58.Encode(new(big.Int).SetInt64(int64(cp.port)).Bytes())
|
||||
k := base58.Encode(cp.privateKey.D.Bytes())
|
||||
tb, err := asn1.Marshal(cp.notBefore.UTC())
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
t := base58.Encode(tb)
|
||||
m := base58.Encode(new(big.Int).SetInt64(int64(cp.serverMode)).Bytes())
|
||||
|
||||
return fmt.Sprintf("%s:%s:%s:%s:%s:%s", v, ip, p, k, t, m), nil
|
||||
}
|
||||
|
||||
// FromString parses a connection params string required for to securely connect to another Status device.
|
||||
// This function parses a connection string generated by ToString
|
||||
func (cp *ConnectionParams) FromString(s string) error {
|
||||
requiredParams := 6
|
||||
|
||||
sData := strings.Split(s, ":")
|
||||
if len(sData) != requiredParams {
|
||||
return fmt.Errorf("expected data '%s' to have length of '%d', received '%d'", s, requiredParams, len(sData))
|
||||
}
|
||||
|
||||
cp.version = ConnectionParamVersion(new(big.Int).SetBytes(base58.Decode(sData[0])).Int64())
|
||||
cp.netIP = base58.Decode(sData[1])
|
||||
cp.port = int(new(big.Int).SetBytes(base58.Decode(sData[2])).Int64())
|
||||
cp.privateKey = ToECDSA(base58.Decode(sData[3]))
|
||||
|
||||
t := time.Time{}
|
||||
_, err := asn1.Unmarshal(base58.Decode(sData[4]), &t)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cp.notBefore = t
|
||||
cp.serverMode = Mode(new(big.Int).SetBytes(base58.Decode(sData[5])).Int64())
|
||||
|
||||
return cp.validate()
|
||||
}
|
||||
|
||||
func (cp *ConnectionParams) validate() error {
|
||||
err := cp.validateVersion()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = cp.validateNetIP()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = cp.validatePort()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = cp.validatePrivateKey()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = cp.validateNotBefore()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return cp.validateServerMode()
|
||||
}
|
||||
|
||||
func (cp *ConnectionParams) validateVersion() error {
|
||||
switch cp.version {
|
||||
case Version1:
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("unsupported version '%d'", cp.version)
|
||||
}
|
||||
}
|
||||
|
||||
func (cp *ConnectionParams) validateNetIP() error {
|
||||
if ok := net.ParseIP(cp.netIP.String()); ok == nil {
|
||||
return fmt.Errorf("invalid net ip '%s'", cp.netIP)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cp *ConnectionParams) validatePort() error {
|
||||
if cp.port > 0 && cp.port < 0x10000 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("port '%d' outside of bounds of 1 - 65535", cp.port)
|
||||
}
|
||||
|
||||
func (cp *ConnectionParams) validatePrivateKey() error {
|
||||
switch {
|
||||
case cp.privateKey.D == nil, cp.privateKey.D.Cmp(big.NewInt(0)) == 0:
|
||||
return fmt.Errorf("private key D not set")
|
||||
case cp.privateKey.PublicKey.X == nil, cp.privateKey.PublicKey.X.Cmp(big.NewInt(0)) == 0:
|
||||
return fmt.Errorf("public key X not set")
|
||||
case cp.privateKey.PublicKey.Y == nil, cp.privateKey.PublicKey.Y.Cmp(big.NewInt(0)) == 0:
|
||||
return fmt.Errorf("public key Y not set")
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (cp *ConnectionParams) validateNotBefore() error {
|
||||
if cp.notBefore.IsZero() {
|
||||
return fmt.Errorf("notBefore time is zero")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cp *ConnectionParams) validateServerMode() error {
|
||||
switch cp.serverMode {
|
||||
case Receiving, Sending:
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("invalid server mode '%d'", cp.serverMode)
|
||||
}
|
||||
}
|
||||
|
||||
// Generate returns a *url.URL and encoded pem.Block generated from ConnectionParams set fields
|
||||
func (cp *ConnectionParams) Generate() (*url.URL, []byte, error) {
|
||||
u := &url.URL{
|
||||
Scheme: "https",
|
||||
Host: fmt.Sprintf("%s:%d", cp.netIP, cp.port),
|
||||
}
|
||||
|
||||
_, pem, err := GenerateCertFromKey(cp.privateKey, cp.notBefore, cp.netIP.String())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return u, pem, nil
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
var (
|
||||
connectionString = "2:4FHRnp:Q4:6jpbvo2ucrtrnpXXF4DQYuysh697isH9ppd2aT8uSRDh:eQUriVtGtkWhPJFeLZjF:3"
|
||||
)
|
||||
|
||||
func TestConnectionParamsSuite(t *testing.T) {
|
||||
suite.Run(t, new(ConnectionParamsSuite))
|
||||
}
|
||||
|
||||
type ConnectionParamsSuite struct {
|
||||
suite.Suite
|
||||
TestKeyComponents
|
||||
TestCertComponents
|
||||
|
||||
server *PairingServer
|
||||
}
|
||||
|
||||
func (s *ConnectionParamsSuite) SetupSuite() {
|
||||
s.SetupKeyComponents(s.T())
|
||||
s.SetupCertComponents(s.T())
|
||||
|
||||
cert, _, err := GenerateCertFromKey(s.PK, s.NotBefore, defaultIP.String())
|
||||
s.Require().NoError(err)
|
||||
|
||||
bs := NewServer(&cert, defaultIP.String())
|
||||
bs.port = 1337
|
||||
|
||||
s.server = &PairingServer{
|
||||
Server: bs,
|
||||
pk: s.PK,
|
||||
mode: Sending,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ConnectionParamsSuite) TestConnectionParams_ToString() {
|
||||
cp, err := s.server.MakeConnectionParams()
|
||||
s.Require().NoError(err)
|
||||
|
||||
cps, err := cp.ToString()
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().Equal(connectionString, cps)
|
||||
}
|
||||
|
||||
func (s *ConnectionParamsSuite) TestConnectionParams_Generate() {
|
||||
cp := new(ConnectionParams)
|
||||
err := cp.FromString(connectionString)
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().Exactly(Sending, cp.serverMode)
|
||||
|
||||
u, c, err := cp.Generate()
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().Equal("https://127.0.0.1:1337", u.String())
|
||||
s.Require().Equal(defaultIP.String(), u.Hostname())
|
||||
s.Require().Equal("1337", u.Port())
|
||||
|
||||
// Parse cert PEM into x509 cert
|
||||
block, _ := pem.Decode(c)
|
||||
s.Require().NotNil(block)
|
||||
cert, err := x509.ParseCertificate(block.Bytes)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Compare cert values
|
||||
cl := s.server.cert.Leaf
|
||||
s.Require().NotEqual(cl.Signature, cert.Signature)
|
||||
s.Require().Zero(cl.PublicKey.(*ecdsa.PublicKey).X.Cmp(cert.PublicKey.(*ecdsa.PublicKey).X))
|
||||
s.Require().Zero(cl.PublicKey.(*ecdsa.PublicKey).Y.Cmp(cert.PublicKey.(*ecdsa.PublicKey).Y))
|
||||
s.Require().Equal(cl.Version, cert.Version)
|
||||
s.Require().Zero(cl.SerialNumber.Cmp(cert.SerialNumber))
|
||||
s.Require().Exactly(cl.NotBefore, cert.NotBefore)
|
||||
s.Require().Exactly(cl.NotAfter, cert.NotAfter)
|
||||
s.Require().Exactly(cl.IPAddresses, cert.IPAddresses)
|
||||
}
|
|
@ -12,7 +12,6 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
@ -31,25 +30,46 @@ func testHandler(t *testing.T) func(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func TestGetOutboundIPWithFullServerE2e(t *testing.T) {
|
||||
// Get 3 key components for tls.cert generation
|
||||
// 1) Ephemeral private key
|
||||
pk, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
require.NoError(t, err)
|
||||
|
||||
// 2) Device outbound IP address
|
||||
ip, err := GetOutboundIP()
|
||||
require.NoError(t, err)
|
||||
|
||||
cert, certPem, err := GenerateCertFromKey(pk, time.Hour, ip.String())
|
||||
// 3) NotBefore time
|
||||
certTime := time.Now()
|
||||
|
||||
// Generate tls.Certificate and Server
|
||||
cert, _, err := GenerateCertFromKey(pk, certTime, ip.String())
|
||||
require.NoError(t, err)
|
||||
|
||||
s := NewPairingServer(&Config{&cert, ip.String()})
|
||||
s := NewPairingServer(&Config{pk, &cert, ip.String(), Sending})
|
||||
|
||||
s.SetHandlers(HandlerPatternMap{"/hello": testHandler(t)})
|
||||
|
||||
err = s.Start()
|
||||
require.NoError(t, err)
|
||||
|
||||
// Give time for the sever to be ready, hacky I know
|
||||
// Give time for the sever to be ready, hacky I know, I'll iron this out
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
spew.Dump(s.MakeBaseURL().String())
|
||||
|
||||
// Server generates a QR code connection string
|
||||
cp, err := s.MakeConnectionParams()
|
||||
require.NoError(t, err)
|
||||
|
||||
qr, err := cp.ToString()
|
||||
require.NoError(t, err)
|
||||
|
||||
// Client reads QR code and parses the connection string
|
||||
ccp := new(ConnectionParams)
|
||||
err = ccp.FromString(qr)
|
||||
require.NoError(t, err)
|
||||
|
||||
u, certPem, err := ccp.Generate()
|
||||
require.NoError(t, err)
|
||||
|
||||
rootCAs, err := x509.SystemCertPool()
|
||||
require.NoError(t, err)
|
||||
|
@ -71,7 +91,7 @@ func TestGetOutboundIPWithFullServerE2e(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
thing := hex.EncodeToString(b)
|
||||
|
||||
response, err := client.Get(s.MakeBaseURL().String() + "/hello?say=" + thing)
|
||||
response, err := client.Get(u.String() + "/hello?say=" + thing)
|
||||
require.NoError(t, err)
|
||||
|
||||
defer response.Body.Close()
|
||||
|
|
|
@ -1,16 +1,24 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
)
|
||||
|
||||
type PairingServer struct {
|
||||
Server
|
||||
|
||||
pk *ecdsa.PrivateKey
|
||||
mode Mode
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
PK *ecdsa.PrivateKey
|
||||
Cert *tls.Certificate
|
||||
Hostname string
|
||||
Mode Mode
|
||||
}
|
||||
|
||||
// NewPairingServer returns a *NewPairingServer init from the given *Config
|
||||
|
@ -18,5 +26,35 @@ func NewPairingServer(config *Config) *PairingServer {
|
|||
return &PairingServer{Server: NewServer(
|
||||
config.Cert,
|
||||
config.Hostname,
|
||||
)}
|
||||
),
|
||||
pk: config.PK,
|
||||
mode: config.Mode}
|
||||
}
|
||||
|
||||
// MakeConnectionParams generates a *ConnectionParams based on the Server's current state
|
||||
func (s *PairingServer) MakeConnectionParams() (*ConnectionParams, error) {
|
||||
switch {
|
||||
case s.cert == nil:
|
||||
return nil, fmt.Errorf("server has no cert set")
|
||||
case s.cert.Leaf == nil:
|
||||
return nil, fmt.Errorf("server cert has no Leaf set")
|
||||
case s.cert.Leaf.NotBefore.IsZero():
|
||||
return nil, fmt.Errorf("server cert Leaf has a zero value NotBefore")
|
||||
}
|
||||
|
||||
netIP := net.ParseIP(s.hostname)
|
||||
if netIP == nil {
|
||||
return nil, fmt.Errorf("invalid ip address given '%s'", s.hostname)
|
||||
}
|
||||
|
||||
netIP4 := netIP.To4()
|
||||
if netIP4 != nil {
|
||||
netIP = netIP4
|
||||
}
|
||||
|
||||
if s.port == 0 {
|
||||
return nil, fmt.Errorf("port is 0, listener is not yet set")
|
||||
}
|
||||
|
||||
return NewConnectionParams(netIP, s.port, s.pk, s.cert.Leaf.NotBefore, s.mode), nil
|
||||
}
|
||||
|
|
|
@ -12,12 +12,16 @@ func TestServerURLSuite(t *testing.T) {
|
|||
|
||||
type ServerURLSuite struct {
|
||||
suite.Suite
|
||||
TestKeyComponents
|
||||
|
||||
server *MediaServer
|
||||
serverNoPort *MediaServer
|
||||
pairingServer *PairingServer
|
||||
}
|
||||
|
||||
func (s *ServerURLSuite) SetupSuite() {
|
||||
s.SetupKeyComponents(s.T())
|
||||
|
||||
s.server = &MediaServer{Server: Server{
|
||||
hostname: defaultIP.String(),
|
||||
port: 1337,
|
||||
|
|
Loading…
Reference in New Issue