1package verify
2
3import (
4	"crypto/x509"
5	"encoding/pem"
6	"io/ioutil"
7	"path/filepath"
8	"testing"
9)
10
11func TestVerify(t *testing.T) {
12	tests := []struct {
13		id         string
14		wantChains int
15	}{
16		{"1a", 1},
17		{"2a", 1},
18		{"2b", 0},
19		{"3a", 1},
20		{"3b", 0},
21		{"3c", 0},
22		{"3d", 0},
23		{"3e", 1},
24		{"4a", 2},
25		{"4b", 1},
26		{"4c", 1},
27		{"4d", 1},
28		{"4e", 1},
29		{"4f", 2},
30		{"4g", 1},
31		{"4h", 1},
32		{"5a", 2},
33		{"5b", 1},
34		{"5c", 1},
35		{"5d", 1},
36		{"5e", 1},
37		{"5f", 1},
38		{"5g", 2},
39		{"5h", 1},
40		{"5i", 1},
41		{"6a", 1},  // Expired root.
42		{"6b", 1},  // Expired root.
43		{"7a", 1},  // Expired root.
44		{"7b", 1},  // Expired root.
45		{"8a", 0},  // Expired leaf.
46		{"9a", 0},  // Expired intermediate.
47		{"10a", 1}, // Cross signed with expired intermediate.
48		{"10b", 1}, // Cross signed with expired intermediate.
49		{"11a", 1}, // Cross signed with expired intermediate.
50		{"11b", 1}, // Cross signed with expired intermediate.
51		{"12a", 1}, // Cross signed with expired intermediate.
52		{"13a", 1}, // Cross signed with expired root.
53	}
54
55	for _, test := range tests {
56		t.Run(test.id, func(t *testing.T) {
57			rootsPEM, err := ioutil.ReadFile(filepath.Join(test.id, "roots.pem"))
58			if err != nil {
59				t.Fatalf("Failed to read roots PEM: %v", err)
60			}
61			bundlePEM, err := ioutil.ReadFile(filepath.Join(test.id, "bundle.pem"))
62			if err != nil {
63				t.Fatalf("Failed to read bundle PEM: %v", err)
64			}
65
66			// Pull the leaf certificate off the top of the bundle.
67			block, intermediatesPEM := pem.Decode(bundlePEM)
68			if block == nil {
69				t.Fatal("Failed to parse leaf from bundle")
70			}
71			cert, err := x509.ParseCertificate(block.Bytes)
72			if err != nil {
73				t.Fatalf("Failed to parse certificate: %v", err)
74			}
75
76			roots := x509.NewCertPool()
77			if !roots.AppendCertsFromPEM(rootsPEM) {
78				t.Fatal("Failed to parse root certificates")
79			}
80			intermediates := x509.NewCertPool()
81			if len(intermediatesPEM) > 0 {
82				if !intermediates.AppendCertsFromPEM(intermediatesPEM) {
83					t.Fatal("Failed to parse intermediate certificates")
84				}
85			}
86
87			opts := x509.VerifyOptions{
88				Roots:         roots,
89				Intermediates: intermediates,
90			}
91
92			chains, err := cert.Verify(opts)
93			if err != nil {
94				if test.wantChains > 0 {
95					t.Errorf("Failed to verify certificate: %v", err)
96				}
97				return
98			}
99			t.Logf("Found %d chains", len(chains))
100			if got, want := len(chains), test.wantChains; got != want {
101				t.Errorf("Got %d chains, want %d", got, want)
102			}
103			for i, chain := range chains {
104				t.Logf("Chain %d\n", i)
105				for _, cert := range chain {
106					t.Logf("  %v\n", cert.Subject)
107				}
108			}
109		})
110	}
111}
112