@@ -21,6 +21,37 @@ import (
21
21
"time"
22
22
)
23
23
24
+ // This is the currently active LetsEncrypt IdenTrust cross-signed CA cert. It expires Mar 17, 2021.
25
+ const systemRootTrustedCert = `
26
+ -----BEGIN CERTIFICATE-----
27
+ MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/
28
+ MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
29
+ DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow
30
+ SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT
31
+ GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC
32
+ AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF
33
+ q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8
34
+ SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0
35
+ Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA
36
+ a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj
37
+ /PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T
38
+ AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG
39
+ CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv
40
+ bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k
41
+ c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw
42
+ VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC
43
+ ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz
44
+ MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu
45
+ Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF
46
+ AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo
47
+ uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/
48
+ wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu
49
+ X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG
50
+ PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6
51
+ KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
52
+ -----END CERTIFICATE-----
53
+ `
54
+
24
55
var certTemplate = x509.Certificate {
25
56
SerialNumber : big .NewInt (199999 ),
26
57
Subject : pkix.Name {
@@ -30,13 +61,19 @@ var certTemplate = x509.Certificate{
30
61
NotAfter : time .Now ().AddDate (1 , 1 , 1 ),
31
62
32
63
KeyUsage : x509 .KeyUsageKeyEncipherment | x509 .KeyUsageDigitalSignature ,
33
- ExtKeyUsage : []x509.ExtKeyUsage {x509 .ExtKeyUsageCodeSigning },
64
+ ExtKeyUsage : []x509.ExtKeyUsage {x509 .ExtKeyUsageCodeSigning , x509 . ExtKeyUsageAny },
34
65
35
66
BasicConstraintsValid : true ,
36
67
}
37
68
38
- func generateCertificate (t * testing.T , signer crypto.Signer , out io.Writer ) {
39
- derBytes , err := x509 .CreateCertificate (rand .Reader , & certTemplate , & certTemplate , signer .Public (), signer )
69
+ func generateCertificate (t * testing.T , signer crypto.Signer , out io.Writer , isCA bool ) {
70
+ template := certTemplate
71
+ template .IsCA = isCA
72
+ if isCA {
73
+ template .KeyUsage = template .KeyUsage | x509 .KeyUsageCertSign
74
+ template .MaxPathLen = 1
75
+ }
76
+ derBytes , err := x509 .CreateCertificate (rand .Reader , & template , & certTemplate , signer .Public (), signer )
40
77
if err != nil {
41
78
t .Fatal ("Unable to generate a certificate" , err .Error ())
42
79
}
@@ -46,7 +83,7 @@ func generateCertificate(t *testing.T, signer crypto.Signer, out io.Writer) {
46
83
}
47
84
}
48
85
49
- // generates a multiple-certificate file with both RSA and ECDSA certs and
86
+ // generates a multiple-certificate CA file with both RSA and ECDSA certs and
50
87
// returns the filename so that cleanup can be deferred.
51
88
func generateMultiCert (t * testing.T , tempDir string ) string {
52
89
certOut , err := os .Create (filepath .Join (tempDir , "multi" ))
@@ -65,7 +102,7 @@ func generateMultiCert(t *testing.T, tempDir string) string {
65
102
}
66
103
67
104
for _ , signer := range []crypto.Signer {rsaKey , ecKey } {
68
- generateCertificate (t , signer , certOut )
105
+ generateCertificate (t , signer , certOut , true )
69
106
}
70
107
71
108
return certOut .Name ()
@@ -96,7 +133,7 @@ func generateCertAndKey(t *testing.T, tempDir string) (string, string) {
96
133
}
97
134
defer certOut .Close ()
98
135
99
- generateCertificate (t , rsaKey , certOut )
136
+ generateCertificate (t , rsaKey , certOut , false )
100
137
101
138
return keyOut .Name (), certOut .Name ()
102
139
}
@@ -240,11 +277,106 @@ func TestConfigServerTLSClientCASet(t *testing.T) {
240
277
if tlsConfig .ClientAuth != tls .VerifyClientCertIfGiven {
241
278
t .Fatal ("ClientAuth was not set to what was in the options" )
242
279
}
243
- if tlsConfig .ClientCAs == nil || len (tlsConfig .ClientCAs .Subjects ()) != 2 {
280
+ basePool , err := SystemCertPool ()
281
+ if err != nil {
282
+ basePool = x509 .NewCertPool ()
283
+ }
284
+ // because we are not enabling `ExclusiveRootPools`, any root pool will also contain the system roots
285
+ if tlsConfig .ClientCAs == nil || len (tlsConfig .ClientCAs .Subjects ()) != len (basePool .Subjects ())+ 2 {
244
286
t .Fatalf ("Client CAs were never set correctly" )
245
287
}
246
288
}
247
289
290
+ // Exclusive root pools determines whether the CA pool will be a union of the system
291
+ // certificate pool and custom certs, or an exclusive or of the custom certs and system pool
292
+ func TestConfigServerExclusiveRootPools (t * testing.T ) {
293
+ tempDir := makeTempDir (t )
294
+ defer os .RemoveAll (tempDir )
295
+ key , cert := generateCertAndKey (t , tempDir )
296
+ ca := generateMultiCert (t , tempDir )
297
+
298
+ caBytes , err := ioutil .ReadFile (ca )
299
+ if err != nil {
300
+ t .Fatal ("Unable to read CA certs" , err )
301
+ }
302
+
303
+ var testCerts []* x509.Certificate
304
+ for _ , pemBytes := range [][]byte {caBytes , []byte (systemRootTrustedCert )} {
305
+ pemBlock , _ := pem .Decode (pemBytes )
306
+ if pemBlock == nil {
307
+ t .Fatal ("Malformed certificate" )
308
+ }
309
+ cert , err := x509 .ParseCertificate (pemBlock .Bytes )
310
+ if err != nil {
311
+ t .Fatal ("Unable to parse certificate" )
312
+ }
313
+ testCerts = append (testCerts , cert )
314
+ }
315
+
316
+ // ExclusiveRootPools not set, so should be able to verify both system-signed certs
317
+ // and custom CA-signed certs
318
+ tlsConfig , err := Server (Options {
319
+ CertFile : cert ,
320
+ KeyFile : key ,
321
+ ClientAuth : tls .VerifyClientCertIfGiven ,
322
+ CAFile : ca ,
323
+ })
324
+
325
+ if err != nil || tlsConfig == nil {
326
+ t .Fatal ("Unable to configure server TLS" , err )
327
+ }
328
+
329
+ for i , cert := range testCerts {
330
+ if _ , err := cert .Verify (x509.VerifyOptions {Roots : tlsConfig .ClientCAs }); err != nil {
331
+ t .Fatalf ("Unable to verify certificate %d: %v" , i , err )
332
+ }
333
+ }
334
+
335
+ // ExclusiveRootPools set and custom CA provided, so system certs should not be verifiable
336
+ // and custom CA-signed certs should be verifiable
337
+ tlsConfig , err = Server (Options {
338
+ CertFile : cert ,
339
+ KeyFile : key ,
340
+ ClientAuth : tls .VerifyClientCertIfGiven ,
341
+ CAFile : ca ,
342
+ ExclusiveRootPools : true ,
343
+ })
344
+
345
+ if err != nil || tlsConfig == nil {
346
+ t .Fatal ("Unable to configure server TLS" , err )
347
+ }
348
+
349
+ for i , cert := range testCerts {
350
+ _ , err := cert .Verify (x509.VerifyOptions {Roots : tlsConfig .ClientCAs })
351
+ switch {
352
+ case i == 0 && err != nil :
353
+ t .Fatal ("Unable to verify custom certificate, even though the root pool should have only the custom CA" , err )
354
+ case i == 1 && err == nil :
355
+ t .Fatal ("Successfully verified system root-signed certificate though the root pool should have only the cusotm CA" , err )
356
+ }
357
+ }
358
+
359
+ // No CA file provided, system cert should be verifiable only
360
+ tlsConfig , err = Server (Options {
361
+ CertFile : cert ,
362
+ KeyFile : key ,
363
+ })
364
+
365
+ if err != nil || tlsConfig == nil {
366
+ t .Fatal ("Unable to configure server TLS" , err )
367
+ }
368
+
369
+ for i , cert := range testCerts {
370
+ _ , err := cert .Verify (x509.VerifyOptions {Roots : tlsConfig .ClientCAs })
371
+ switch {
372
+ case i == 1 && err != nil :
373
+ t .Fatal ("Unable to verify system root-signed certificate, even though the root pool should be the system pool only" , err )
374
+ case i == 0 && err == nil :
375
+ t .Fatal ("Successfully verified custom certificate though the root pool should be the system pool only" , err )
376
+ }
377
+ }
378
+ }
379
+
248
380
// The root CA is never set if InsecureSkipBoolean is set to true, but the
249
381
// default client options are set
250
382
func TestConfigClientTLSNoVerify (t * testing.T ) {
@@ -310,8 +442,12 @@ func TestConfigClientTLSRootCAFileWithOneCert(t *testing.T) {
310
442
if err != nil || tlsConfig == nil {
311
443
t .Fatal ("Unable to configure client TLS" , err )
312
444
}
313
-
314
- if tlsConfig .RootCAs == nil || len (tlsConfig .RootCAs .Subjects ()) != 2 {
445
+ basePool , err := SystemCertPool ()
446
+ if err != nil {
447
+ basePool = x509 .NewCertPool ()
448
+ }
449
+ // because we are not enabling `ExclusiveRootPools`, any root pool will also contain the system roots
450
+ if tlsConfig .RootCAs == nil || len (tlsConfig .RootCAs .Subjects ()) != len (basePool .Subjects ())+ 2 {
315
451
t .Fatal ("Root CAs not set properly" , err )
316
452
}
317
453
if tlsConfig .Certificates != nil {
@@ -389,3 +525,81 @@ func TestConfigClientTLSValidClientCertAndKey(t *testing.T) {
389
525
t .Fatal ("Root CAs should not have been set" , err )
390
526
}
391
527
}
528
+
529
+ // Exclusive root pools determines whether the CA pool will be a union of the system
530
+ // certificate pool and custom certs, or an exclusive or of the custom certs and system pool
531
+ func TestConfigClientExclusiveRootPools (t * testing.T ) {
532
+ tempDir := makeTempDir (t )
533
+ defer os .RemoveAll (tempDir )
534
+ ca := generateMultiCert (t , tempDir )
535
+
536
+ caBytes , err := ioutil .ReadFile (ca )
537
+ if err != nil {
538
+ t .Fatal ("Unable to read CA certs" , err )
539
+ }
540
+
541
+ var testCerts []* x509.Certificate
542
+ for _ , pemBytes := range [][]byte {caBytes , []byte (systemRootTrustedCert )} {
543
+ pemBlock , _ := pem .Decode (pemBytes )
544
+ if pemBlock == nil {
545
+ t .Fatal ("Malformed certificate" )
546
+ }
547
+ cert , err := x509 .ParseCertificate (pemBlock .Bytes )
548
+ if err != nil {
549
+ t .Fatal ("Unable to parse certificate" )
550
+ }
551
+ testCerts = append (testCerts , cert )
552
+ }
553
+
554
+ // ExclusiveRootPools not set, so should be able to verify both system-signed certs
555
+ // and custom CA-signed certs
556
+ tlsConfig , err := Client (Options {CAFile : ca })
557
+
558
+ if err != nil || tlsConfig == nil {
559
+ t .Fatal ("Unable to configure client TLS" , err )
560
+ }
561
+
562
+ for i , cert := range testCerts {
563
+ if _ , err := cert .Verify (x509.VerifyOptions {Roots : tlsConfig .RootCAs }); err != nil {
564
+ t .Fatalf ("Unable to verify certificate %d: %v" , i , err )
565
+ }
566
+ }
567
+
568
+ // ExclusiveRootPools set and custom CA provided, so system certs should not be verifiable
569
+ // and custom CA-signed certs should be verifiable
570
+ tlsConfig , err = Client (Options {
571
+ CAFile : ca ,
572
+ ExclusiveRootPools : true ,
573
+ })
574
+
575
+ if err != nil || tlsConfig == nil {
576
+ t .Fatal ("Unable to configure client TLS" , err )
577
+ }
578
+
579
+ for i , cert := range testCerts {
580
+ _ , err := cert .Verify (x509.VerifyOptions {Roots : tlsConfig .RootCAs })
581
+ switch {
582
+ case i == 0 && err != nil :
583
+ t .Fatal ("Unable to verify custom certificate, even though the root pool should have only the custom CA" , err )
584
+ case i == 1 && err == nil :
585
+ t .Fatal ("Successfully verified system root-signed certificate though the root pool should have only the cusotm CA" , err )
586
+ }
587
+ }
588
+
589
+ // No CA file provided, system cert should be verifiable only
590
+ tlsConfig , err = Client (Options {})
591
+
592
+ if err != nil || tlsConfig == nil {
593
+ t .Fatal ("Unable to configure client TLS" , err )
594
+ }
595
+
596
+ for i , cert := range testCerts {
597
+ _ , err := cert .Verify (x509.VerifyOptions {Roots : tlsConfig .RootCAs })
598
+ switch {
599
+ case i == 1 && err != nil :
600
+ t .Fatal ("Unable to verify system root-signed certificate, even though the root pool should be the system pool only" , err )
601
+ case i == 0 && err == nil :
602
+ t .Fatal ("Successfully verified custom certificate though the root pool should be the system pool only" , err )
603
+ }
604
+ }
605
+ }
0 commit comments