github.com/hoffie/larasync@v0.0.0-20151025221940-0384d2bddcef/api/tls/fingerprintVerifier_test.go (about)

     1  package tls
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/ecdsa"
     6  	"crypto/elliptic"
     7  	"crypto/tls"
     8  	"crypto/x509"
     9  	"io/ioutil"
    10  	"math/big"
    11  	"net"
    12  	"strings"
    13  	"time"
    14  
    15  	. "gopkg.in/check.v1"
    16  )
    17  
    18  type FVTests struct{}
    19  
    20  var _ = Suite(&FVTests{})
    21  
    22  func (t *FVTests) TestAcceptPeerCertNoFpNoFunc(c *C) {
    23  	crt, _, _ := t.makeTestCert(c)
    24  	fpv := FingerprintVerifier{}
    25  	c.Assert(fpv.acceptPeerCert(crt), Equals, false)
    26  }
    27  
    28  func (t *FVTests) TestAcceptPeerCertAcceptFuncFail(c *C) {
    29  	crt, _, _ := t.makeTestCert(c)
    30  	fpv := FingerprintVerifier{
    31  		VerificationFunc: func(fp string) bool {
    32  			return false
    33  		},
    34  	}
    35  	c.Assert(fpv.acceptPeerCert(crt), Equals, false)
    36  	c.Assert(fpv.AcceptFingerprint, Equals, "")
    37  }
    38  
    39  func (t *FVTests) TestAcceptPeerCertAcceptFuncAccept(c *C) {
    40  	crt, _, _ := t.makeTestCert(c)
    41  	fpv := FingerprintVerifier{
    42  		VerificationFunc: func(fp string) bool {
    43  			return true
    44  		},
    45  	}
    46  	c.Assert(fpv.acceptPeerCert(crt), Equals, true)
    47  	c.Assert(fpv.AcceptFingerprint, Equals, testCertFp)
    48  	fpv.VerificationFunc = func(fp string) bool {
    49  		c.Fatal("unexpected call to verification func")
    50  		return false
    51  	}
    52  	c.Assert(fpv.acceptPeerCert(crt), Equals, true)
    53  }
    54  
    55  func (t *FVTests) TestAcceptPeerCertPreset(c *C) {
    56  	crt, _, _ := t.makeTestCert(c)
    57  	fpv := FingerprintVerifier{
    58  		AcceptFingerprint: testCertFp,
    59  	}
    60  	c.Assert(fpv.acceptPeerCert(crt), Equals, true)
    61  }
    62  
    63  func (t *FVTests) TestAcceptPeerCertPresetFail(c *C) {
    64  	crt, _, _ := t.makeTestCert(c)
    65  	fpv := FingerprintVerifier{
    66  		AcceptFingerprint: strings.Replace(testCertFp, "c", "d", 1),
    67  	}
    68  	c.Assert(fpv.acceptPeerCert(crt), Equals, false)
    69  }
    70  
    71  func (t *FVTests) TestAcceptPeerCertPresetFailNoCall(c *C) {
    72  	crt, _, _ := t.makeTestCert(c)
    73  	fpv := FingerprintVerifier{
    74  		AcceptFingerprint: strings.Replace(testCertFp, "c", "d", 1),
    75  		VerificationFunc: func(fp string) bool {
    76  			c.Fatal("verification called although unexpected")
    77  			return false
    78  		},
    79  	}
    80  	c.Assert(fpv.acceptPeerCert(crt), Equals, false)
    81  }
    82  
    83  func (t *FVTests) setupTLSServer(c *C) (string, net.Listener) {
    84  	l, err := net.Listen("tcp", "127.0.0.1:0")
    85  	c.Assert(err, IsNil)
    86  	_, derBytes, priv := t.makeTestCert(c)
    87  	myCert := tls.Certificate{
    88  		Certificate: [][]byte{derBytes},
    89  		PrivateKey:  priv,
    90  	}
    91  	tlsL := tls.NewListener(l, &tls.Config{
    92  		NextProtos:   []string{"http/1.1"},
    93  		Certificates: []tls.Certificate{myCert},
    94  	})
    95  	go func() {
    96  		conn, err := tlsL.Accept()
    97  		c.Assert(err, IsNil)
    98  		defer conn.Close()
    99  		_, err = conn.Write([]byte("test"))
   100  		c.Assert(err, IsNil)
   101  	}()
   102  	addr := tlsL.Addr().String()
   103  	return addr, l
   104  }
   105  
   106  func (t *FVTests) TestDialTLSReject(c *C) {
   107  	addr, l := t.setupTLSServer(c)
   108  	defer l.Close()
   109  	fpv := &FingerprintVerifier{}
   110  	_, err := fpv.DialTLS("tcp", addr)
   111  	c.Assert(err, Equals, ErrFingerprintRejected)
   112  }
   113  
   114  func (t *FVTests) TestDialTLSAccept(c *C) {
   115  	addr, l := t.setupTLSServer(c)
   116  	defer l.Close()
   117  	fpv := &FingerprintVerifier{AcceptFingerprint: testCertFp}
   118  	conn, err := fpv.DialTLS("tcp", addr)
   119  	c.Assert(err, IsNil)
   120  	r, err := ioutil.ReadAll(conn)
   121  	c.Assert(err, IsNil)
   122  	c.Assert(r, DeepEquals, []byte("test"))
   123  }
   124  
   125  const testCertFp = "9f79df7d821ea16d89c09e026074e81f89540aa7fbfda1b0b3f5ba7dcab88d71b944a49bb0c8a5c8abf42308d8ae060bf7437831e7a5f21b3c7718f04578680b"
   126  
   127  func (t *FVTests) makeTestCert(c *C) (*x509.Certificate, []byte, *ecdsa.PrivateKey) {
   128  	entropy := bytes.NewBufferString("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
   129  	priv, err := ecdsa.GenerateKey(elliptic.P521(), entropy)
   130  	c.Assert(err, IsNil)
   131  
   132  	template := x509.Certificate{
   133  		SerialNumber: big.NewInt(1),
   134  	}
   135  
   136  	derBytes, err := x509.CreateCertificate(entropy, &template, &template,
   137  		&priv.PublicKey, priv)
   138  	c.Assert(err, IsNil)
   139  	cert, err := x509.ParseCertificate(derBytes)
   140  	c.Assert(err, IsNil)
   141  	return cert, derBytes, priv
   142  }
   143  
   144  func (t *FVTests) TestNoConnection(c *C) {
   145  	fpv := &FingerprintVerifier{AcceptFingerprint: testCertFp}
   146  	_, err := fpv.DialTLS("tcp", "127.0.0.1:55543")
   147  	c.Assert(err, NotNil)
   148  }
   149  
   150  func (t *FVTests) TestTimeout(c *C) {
   151  	addr, l := t.setupTLSServer(c)
   152  	defer l.Close()
   153  	fpv := &FingerprintVerifier{AcceptFingerprint: testCertFp}
   154  	_, err := fpv.dialTLS("tcp", addr, 0*time.Minute)
   155  	c.Assert(err, NotNil)
   156  
   157  	c.Assert(err, FitsTypeOf, handshakeTimeoutError{})
   158  	timeoutError := err.(handshakeTimeoutError)
   159  	c.Check(len(timeoutError.Error()) > 1, Equals, true)
   160  	c.Check(timeoutError.Temporary(), Equals, true)
   161  	c.Check(timeoutError.Timeout(), Equals, true)
   162  }