github.com/letsencrypt/boulder@v0.20251208.0/grpc/creds/creds_test.go (about) 1 package creds 2 3 import ( 4 "context" 5 "crypto/ecdsa" 6 "crypto/elliptic" 7 "crypto/rand" 8 "crypto/tls" 9 "crypto/x509" 10 "math/big" 11 "net" 12 "net/http/httptest" 13 "testing" 14 "time" 15 16 "github.com/jmhodges/clock" 17 18 "github.com/letsencrypt/boulder/test" 19 ) 20 21 func TestServerTransportCredentials(t *testing.T) { 22 _, badCert := test.ThrowAwayCert(t, clock.New()) 23 goodCert := &x509.Certificate{ 24 DNSNames: []string{"creds-test"}, 25 IPAddresses: []net.IP{net.IPv4(127, 0, 0, 1)}, 26 } 27 acceptedSANs := map[string]struct{}{ 28 "creds-test": {}, 29 } 30 servTLSConfig := &tls.Config{} 31 32 // NewServerCredentials with a nil serverTLSConfig should return an error 33 _, err := NewServerCredentials(nil, acceptedSANs) 34 test.AssertEquals(t, err, ErrNilServerConfig) 35 36 // A creds with a nil acceptedSANs list should consider any peer valid 37 wrappedCreds, err := NewServerCredentials(servTLSConfig, nil) 38 test.AssertNotError(t, err, "NewServerCredentials failed with nil acceptedSANs") 39 bcreds := wrappedCreds.(*serverTransportCredentials) 40 err = bcreds.validateClient(tls.ConnectionState{}) 41 test.AssertNotError(t, err, "validateClient() errored for emptyState") 42 43 // A creds with a empty acceptedSANs list should consider any peer valid 44 wrappedCreds, err = NewServerCredentials(servTLSConfig, map[string]struct{}{}) 45 test.AssertNotError(t, err, "NewServerCredentials failed with empty acceptedSANs") 46 bcreds = wrappedCreds.(*serverTransportCredentials) 47 err = bcreds.validateClient(tls.ConnectionState{}) 48 test.AssertNotError(t, err, "validateClient() errored for emptyState") 49 50 // A properly-initialized creds should fail to verify an empty ConnectionState 51 bcreds = &serverTransportCredentials{servTLSConfig, acceptedSANs} 52 err = bcreds.validateClient(tls.ConnectionState{}) 53 test.AssertEquals(t, err, ErrEmptyPeerCerts) 54 55 // A creds should reject peers that don't have a leaf certificate with 56 // a SAN on the accepted list. 57 err = bcreds.validateClient(tls.ConnectionState{ 58 PeerCertificates: []*x509.Certificate{badCert}, 59 }) 60 var errSANNotAccepted ErrSANNotAccepted 61 test.AssertErrorWraps(t, err, &errSANNotAccepted) 62 63 // A creds should accept peers that have a leaf certificate with a SAN 64 // that is on the accepted list 65 err = bcreds.validateClient(tls.ConnectionState{ 66 PeerCertificates: []*x509.Certificate{goodCert}, 67 }) 68 test.AssertNotError(t, err, "validateClient(rightState) failed") 69 70 // A creds configured with an IP SAN in the accepted list should accept a peer 71 // that has a leaf certificate containing an IP address SAN present in the 72 // accepted list. 73 acceptedIPSans := map[string]struct{}{ 74 "127.0.0.1": {}, 75 } 76 bcreds = &serverTransportCredentials{servTLSConfig, acceptedIPSans} 77 err = bcreds.validateClient(tls.ConnectionState{ 78 PeerCertificates: []*x509.Certificate{goodCert}, 79 }) 80 test.AssertNotError(t, err, "validateClient(rightState) failed with an IP accepted SAN list") 81 } 82 83 func TestClientTransportCredentials(t *testing.T) { 84 priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 85 test.AssertNotError(t, err, "failed to generate test key") 86 87 temp := &x509.Certificate{ 88 SerialNumber: big.NewInt(1), 89 DNSNames: []string{"A"}, 90 NotBefore: time.Unix(1000, 0), 91 NotAfter: time.Now().AddDate(1, 0, 0), 92 BasicConstraintsValid: true, 93 IsCA: true, 94 } 95 derA, err := x509.CreateCertificate(rand.Reader, temp, temp, priv.Public(), priv) 96 test.AssertNotError(t, err, "x509.CreateCertificate failed") 97 certA, err := x509.ParseCertificate(derA) 98 test.AssertNotError(t, err, "x509.ParserCertificate failed") 99 temp.DNSNames[0] = "B" 100 derB, err := x509.CreateCertificate(rand.Reader, temp, temp, priv.Public(), priv) 101 test.AssertNotError(t, err, "x509.CreateCertificate failed") 102 certB, err := x509.ParseCertificate(derB) 103 test.AssertNotError(t, err, "x509.ParserCertificate failed") 104 roots := x509.NewCertPool() 105 roots.AddCert(certA) 106 roots.AddCert(certB) 107 108 serverA := httptest.NewUnstartedServer(nil) 109 serverA.TLS = &tls.Config{Certificates: []tls.Certificate{{Certificate: [][]byte{derA}, PrivateKey: priv}}} 110 serverB := httptest.NewUnstartedServer(nil) 111 serverB.TLS = &tls.Config{Certificates: []tls.Certificate{{Certificate: [][]byte{derB}, PrivateKey: priv}}} 112 113 tc := NewClientCredentials(roots, []tls.Certificate{}, "") 114 115 serverA.StartTLS() 116 defer serverA.Close() 117 addrA := serverA.Listener.Addr().String() 118 rawConnA, err := net.Dial("tcp", addrA) 119 test.AssertNotError(t, err, "net.Dial failed") 120 defer func() { 121 _ = rawConnA.Close() 122 }() 123 124 conn, _, err := tc.ClientHandshake(context.Background(), "A:2020", rawConnA) 125 test.AssertNotError(t, err, "tc.ClientHandshake failed") 126 test.Assert(t, conn != nil, "tc.ClientHandshake returned a nil net.Conn") 127 128 serverB.StartTLS() 129 defer serverB.Close() 130 addrB := serverB.Listener.Addr().String() 131 rawConnB, err := net.Dial("tcp", addrB) 132 test.AssertNotError(t, err, "net.Dial failed") 133 defer func() { 134 _ = rawConnB.Close() 135 }() 136 137 conn, _, err = tc.ClientHandshake(context.Background(), "B:3030", rawConnB) 138 test.AssertNotError(t, err, "tc.ClientHandshake failed") 139 test.Assert(t, conn != nil, "tc.ClientHandshake returned a nil net.Conn") 140 141 // Test timeout 142 ln, err := net.Listen("tcp", "127.0.0.1:0") 143 test.AssertNotError(t, err, "net.Listen failed") 144 defer func() { 145 _ = ln.Close() 146 }() 147 addrC := ln.Addr().String() 148 stop := make(chan struct{}, 1) 149 go func() { 150 for { 151 select { 152 case <-stop: 153 return 154 default: 155 _, _ = ln.Accept() 156 time.Sleep(2 * time.Millisecond) 157 } 158 } 159 }() 160 161 rawConnC, err := net.Dial("tcp", addrC) 162 test.AssertNotError(t, err, "net.Dial failed") 163 defer func() { 164 _ = rawConnB.Close() 165 }() 166 167 ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond) 168 defer cancel() 169 conn, _, err = tc.ClientHandshake(ctx, "A:2020", rawConnC) 170 test.AssertError(t, err, "tc.ClientHandshake didn't timeout") 171 test.AssertEquals(t, err.Error(), "context deadline exceeded") 172 test.Assert(t, conn == nil, "tc.ClientHandshake returned a non-nil net.Conn on failure") 173 174 stop <- struct{}{} 175 } 176 177 type brokenConn struct{} 178 179 func (bc *brokenConn) Read([]byte) (int, error) { 180 return 0, &net.OpError{} 181 } 182 183 func (bc *brokenConn) Write([]byte) (int, error) { 184 return 0, &net.OpError{} 185 } 186 187 func (bc *brokenConn) LocalAddr() net.Addr { return nil } 188 func (bc *brokenConn) RemoteAddr() net.Addr { return nil } 189 func (bc *brokenConn) Close() error { return nil } 190 func (bc *brokenConn) SetDeadline(time.Time) error { return nil } 191 func (bc *brokenConn) SetReadDeadline(time.Time) error { return nil } 192 func (bc *brokenConn) SetWriteDeadline(time.Time) error { return nil } 193 194 func TestClientReset(t *testing.T) { 195 tc := NewClientCredentials(nil, []tls.Certificate{}, "") 196 _, _, err := tc.ClientHandshake(context.Background(), "T:1010", &brokenConn{}) 197 test.AssertError(t, err, "ClientHandshake succeeded with brokenConn") 198 var netErr net.Error 199 test.AssertErrorWraps(t, err, &netErr) 200 }