... | ... |
@@ -2,6 +2,7 @@ package login |
2 | 2 |
|
3 | 3 |
import ( |
4 | 4 |
"bytes" |
5 |
+ "crypto/x509" |
|
5 | 6 |
"fmt" |
6 | 7 |
"io" |
7 | 8 |
"net" |
... | ... |
@@ -80,10 +81,23 @@ func dialToServer(clientConfig restclient.Config) error { |
80 | 80 |
return nil |
81 | 81 |
} |
82 | 82 |
|
83 |
-func promptForInsecureTLS(reader io.Reader, out io.Writer) bool { |
|
83 |
+func promptForInsecureTLS(reader io.Reader, out io.Writer, reason error) bool { |
|
84 |
+ var insecureTLSRequestReason string |
|
85 |
+ if reason != nil { |
|
86 |
+ switch reason.(type) { |
|
87 |
+ case x509.UnknownAuthorityError: |
|
88 |
+ insecureTLSRequestReason = "The server uses a certificate signed by an unknown authority." |
|
89 |
+ case x509.HostnameError: |
|
90 |
+ insecureTLSRequestReason = fmt.Sprintf("The server is using a certificate that does not match its hostname: %s", reason.Error()) |
|
91 |
+ case x509.CertificateInvalidError: |
|
92 |
+ insecureTLSRequestReason = fmt.Sprintf("The server is using an invalid certificate: %s", reason.Error()) |
|
93 |
+ } |
|
94 |
+ } |
|
84 | 95 |
var input bool |
85 | 96 |
if term.IsTerminal(reader) { |
86 |
- fmt.Fprintln(out, "The server uses a certificate signed by an unknown authority.") |
|
97 |
+ if len(insecureTLSRequestReason) > 0 { |
|
98 |
+ fmt.Fprintln(out, insecureTLSRequestReason) |
|
99 |
+ } |
|
87 | 100 |
fmt.Fprintln(out, "You can bypass the certificate check, but any data you send to the server could be intercepted by others.") |
88 | 101 |
input = cmdutil.PromptForBool(os.Stdin, out, "Use insecure connections? (y/n): ") |
89 | 102 |
fmt.Fprintln(out) |
... | ... |
@@ -121,10 +121,10 @@ func (o *LoginOptions) getClientConfig() (*restclient.Config, error) { |
121 | 121 |
// certificate authority unknown, check or prompt if we want an insecure |
122 | 122 |
// connection or if we already have a cluster stanza that tells us to |
123 | 123 |
// connect to this particular server insecurely |
124 |
- case x509.UnknownAuthorityError: |
|
124 |
+ case x509.UnknownAuthorityError, x509.HostnameError, x509.CertificateInvalidError: |
|
125 | 125 |
if o.InsecureTLS || |
126 | 126 |
hasExistingInsecureCluster(*clientConfig, *o.StartingKubeConfig) || |
127 |
- promptForInsecureTLS(o.Reader, o.Out) { |
|
127 |
+ promptForInsecureTLS(o.Reader, o.Out, err) { |
|
128 | 128 |
clientConfig.Insecure = true |
129 | 129 |
clientConfig.CAFile = "" |
130 | 130 |
clientConfig.CAData = nil |
... | ... |
@@ -1,15 +1,21 @@ |
1 | 1 |
package login |
2 | 2 |
|
3 | 3 |
import ( |
4 |
+ "crypto/tls" |
|
5 |
+ "fmt" |
|
4 | 6 |
"net/http" |
5 | 7 |
"net/http/httptest" |
8 |
+ "regexp" |
|
6 | 9 |
"strings" |
7 | 10 |
"testing" |
8 | 11 |
|
12 |
+ "github.com/MakeNowJust/heredoc" |
|
13 |
+ |
|
9 | 14 |
"github.com/openshift/origin/pkg/cmd/cli/config" |
10 | 15 |
"github.com/openshift/origin/pkg/cmd/util/clientcmd" |
11 | 16 |
|
12 | 17 |
"k8s.io/kubernetes/pkg/client/restclient" |
18 |
+ kclientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api" |
|
13 | 19 |
) |
14 | 20 |
|
15 | 21 |
func TestNormalizeServerURL(t *testing.T) { |
... | ... |
@@ -55,6 +61,163 @@ func TestNormalizeServerURL(t *testing.T) { |
55 | 55 |
} |
56 | 56 |
} |
57 | 57 |
|
58 |
+func TestTLSWithCertificateNotMatchingHostname(t *testing.T) { |
|
59 |
+ // generated by 'go run src/crypto/tls/generate_cert.go --rsa-bits 1024 --host invalidhost.com,8.8.8.8 --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h' |
|
60 |
+ invalidHostCert := heredoc.Doc(` |
|
61 |
+ -----BEGIN CERTIFICATE----- |
|
62 |
+ MIICBjCCAW+gAwIBAgIRALOIWXyeLzunaiVkP2itHAEwDQYJKoZIhvcNAQELBQAw |
|
63 |
+ EjEQMA4GA1UEChMHQWNtZSBDbzAgFw03MDAxMDEwMDAwMDBaGA8yMDg0MDEyOTE2 |
|
64 |
+ MDAwMFowEjEQMA4GA1UEChMHQWNtZSBDbzCBnzANBgkqhkiG9w0BAQEFAAOBjQAw |
|
65 |
+ gYkCgYEAuKDlC4aMBbHaXgS+MFud5h3zeE4boSqKgFI6HceySF/a+qg0v+ID6EwQ |
|
66 |
+ DpJ2W5AdJGEBfixo+tym6q3oKWHJUX0hInkJ6dXIdUbVOeO5dIsGG0fZmRD7DDDx |
|
67 |
+ snkXrDB/E0JglHNckRbIh/jvznbDfbddIcdgZ7JVIfnNpigtHZECAwEAAaNaMFgw |
|
68 |
+ DgYDVR0PAQH/BAQDAgKkMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1UdEwEB/wQF |
|
69 |
+ MAMBAf8wIAYDVR0RBBkwF4IPaW52YWxpZGhvc3QuY29thwQICAgIMA0GCSqGSIb3 |
|
70 |
+ DQEBCwUAA4GBAAkPU044aFkBl4f/muwSh/oPGinnA4fp8ei0KMnLk+0/CjNb3Waa |
|
71 |
+ GtuRVIudRTK2M/RzdpUrwfWlVmkezV4BR1K/aOH9a29zqDTkEjnkIbWwe+piAs+w |
|
72 |
+ VxIxrTqM8rqq8qxeWS54AyF/OaLJgXzDpCFnCb7kY3iyHv6lcmCjluLW |
|
73 |
+ -----END CERTIFICATE-----`) |
|
74 |
+ invalidHostKey := heredoc.Doc(` |
|
75 |
+ -----BEGIN RSA PRIVATE KEY----- |
|
76 |
+ MIICXQIBAAKBgQC4oOULhowFsdpeBL4wW53mHfN4ThuhKoqAUjodx7JIX9r6qDS/ |
|
77 |
+ 4gPoTBAOknZbkB0kYQF+LGj63KbqregpYclRfSEieQnp1ch1RtU547l0iwYbR9mZ |
|
78 |
+ EPsMMPGyeResMH8TQmCUc1yRFsiH+O/OdsN9t10hx2BnslUh+c2mKC0dkQIDAQAB |
|
79 |
+ AoGAZ0ZAuNC7NFhHEL5QcJZe3aC1Vv9B/0XfkWXtckkJFejggcNjNk5D50Xc2Xnd |
|
80 |
+ 0NvtITNN9Xj8BA83IyDCM5uqUwDbOLIc6qYgAGWzxZZSDAQg1iOAAZoXmMTNS6Zf |
|
81 |
+ hQhNUIwB68ELGvbcq7cxQL7L9n4GfISz7PKOOUKTZp0Q8G0CQQD07K7NES340c3I |
|
82 |
+ QVkCW5/ygNK0GuQ8nTcG5yC8R5SDS47N8YzPp17Pajah8+wawYiemY1fUmD7P/bq |
|
83 |
+ Cjl2RtIHAkEAwPo1GzJubN7PSYgPir3TxUGtMJoyc3jfdjblXyGJHwTu2YxeRjd2 |
|
84 |
+ YUPVRpu9JvNjZc+GONvTbTZeNWCvy0JNpwJBAKEsi49JCd6eefOZBTDnCKd1nLKG |
|
85 |
+ q8Ezl/2D5WfhFtsbwrrFhOs1cc++Tnte3/VvfC8aTwz2UfmkyyCSX+P0kMsCQCIL |
|
86 |
+ glb7/LNEU7mbQXKurq+8OHu8mG36wyGt6aVw2yoXyrOiqfclTcM3HmdIjoRSqBSM |
|
87 |
+ Ghfp4FECKHiuSBVJ6z0CQQDF37CRpdQRDPnAedhyApLcIxSbYo1oUm7FxBLyVb7V |
|
88 |
+ HQjFvsOylsSCABXz0FyC7zXQxkEo6CiSahVI/PHz6Zta |
|
89 |
+ -----END RSA PRIVATE KEY-----`) |
|
90 |
+ |
|
91 |
+ server, err := newTLSServer(invalidHostCert, invalidHostKey) |
|
92 |
+ if err != nil { |
|
93 |
+ t.Errorf(err.Error()) |
|
94 |
+ } |
|
95 |
+ server.StartTLS() |
|
96 |
+ defer server.Close() |
|
97 |
+ |
|
98 |
+ testCases := map[string]struct { |
|
99 |
+ serverURL string |
|
100 |
+ skipTLSVerify bool |
|
101 |
+ expectedErrMsg *regexp.Regexp |
|
102 |
+ }{ |
|
103 |
+ "succeed skipping tls": { |
|
104 |
+ serverURL: server.URL, |
|
105 |
+ skipTLSVerify: true, |
|
106 |
+ }, |
|
107 |
+ "certificate hostname doesn't match": { |
|
108 |
+ serverURL: server.URL, |
|
109 |
+ expectedErrMsg: regexp.MustCompile(`The server is using a certificate that does not match its hostname(.*)is valid for 8\.8\.8\.8`), |
|
110 |
+ }, |
|
111 |
+ } |
|
112 |
+ |
|
113 |
+ for name, test := range testCases { |
|
114 |
+ t.Logf("evaluating test: %s", name) |
|
115 |
+ options := &LoginOptions{ |
|
116 |
+ Server: test.serverURL, |
|
117 |
+ InsecureTLS: test.skipTLSVerify, |
|
118 |
+ StartingKubeConfig: &kclientcmdapi.Config{}, |
|
119 |
+ } |
|
120 |
+ |
|
121 |
+ if _, err = options.getClientConfig(); err != nil { |
|
122 |
+ if !test.expectedErrMsg.MatchString(err.Error()) { |
|
123 |
+ t.Errorf("%s: expected error %q but got %q", name, test.expectedErrMsg, err) |
|
124 |
+ } |
|
125 |
+ if test.expectedErrMsg == nil { |
|
126 |
+ t.Errorf("%s: unexpected error: %v", name, err) |
|
127 |
+ } |
|
128 |
+ } else { |
|
129 |
+ if test.expectedErrMsg != nil { |
|
130 |
+ t.Errorf("%s: expected error but got nothing", name) |
|
131 |
+ } |
|
132 |
+ } |
|
133 |
+ } |
|
134 |
+} |
|
135 |
+ |
|
136 |
+func TestTLSWithExpiredCertificate(t *testing.T) { |
|
137 |
+ // generated by 'go run src/crypto/tls/generate_cert.go --rsa-bits 1024 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1h' |
|
138 |
+ expiredCert := heredoc.Doc(` |
|
139 |
+ -----BEGIN CERTIFICATE----- |
|
140 |
+ MIICEjCCAXugAwIBAgIRALf82bYpro/jQS8fP74dG5EwDQYJKoZIhvcNAQELBQAw |
|
141 |
+ EjEQMA4GA1UEChMHQWNtZSBDbzAeFw03MDAxMDEwMDAwMDBaFw03MDAxMDEwMTAw |
|
142 |
+ MDBaMBIxEDAOBgNVBAoTB0FjbWUgQ28wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ |
|
143 |
+ AoGBAONNgDXBk2Q1i/aJjTwt03KpQ3nQblMS3IX/H9JWw6ta6UublKBOaD/2o5Xt |
|
144 |
+ FM+Q7XDEnzYw88CK5KHdyejkJo5IBpUjQYJZFzUJ1BC8Lw7yy6dXWYBJboRR1S+1 |
|
145 |
+ JhkMJOtpPecv+4cTaynplYj0WMBjcQthg2RM7tdpyUYpsp2rAgMBAAGjaDBmMA4G |
|
146 |
+ A1UdDwEB/wQEAwICpDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTAD |
|
147 |
+ AQH/MC4GA1UdEQQnMCWCC2V4YW1wbGUuY29thwR/AAABhxAAAAAAAAAAAAAAAAAA |
|
148 |
+ AAABMA0GCSqGSIb3DQEBCwUAA4GBAFpdiiM5YAQQN0H5ZMNuHWGlprjp7qVilO8/ |
|
149 |
+ WFePZRWY2vQF8g7/c1cX4bPqG+qFJd+9j2UZNjhadNfMCxvu6BY7NCupOHVHmnRQ |
|
150 |
+ ocvkPoSqobE7qDPfiUuU1J+61Libu6b2IjV3/K9pvZkLiBrqn0YhoXXa0PG+rG1L |
|
151 |
+ 9X7+mb5z |
|
152 |
+ -----END CERTIFICATE-----`) |
|
153 |
+ expiredKey := heredoc.Doc(` |
|
154 |
+ -----BEGIN RSA PRIVATE KEY----- |
|
155 |
+ MIICXQIBAAKBgQDjTYA1wZNkNYv2iY08LdNyqUN50G5TEtyF/x/SVsOrWulLm5Sg |
|
156 |
+ Tmg/9qOV7RTPkO1wxJ82MPPAiuSh3cno5CaOSAaVI0GCWRc1CdQQvC8O8sunV1mA |
|
157 |
+ SW6EUdUvtSYZDCTraT3nL/uHE2sp6ZWI9FjAY3ELYYNkTO7XaclGKbKdqwIDAQAB |
|
158 |
+ AoGBAJPFWKqZ9CZboWhfuE/9Qs/yNonE9VRQmMkMOTXXblHCQpUCyjcFgkTDJUpc |
|
159 |
+ 3QCsKZD8Yr0qSe1M3qJUu+UKHf18LqwiL/ynnalYggxIFS5/SidWCngKvIuEfkLK |
|
160 |
+ VsnCK3jt5qx21iljGHU6bQZHnHB9IGEiBYcnQlvvw/WdvRDBAkEA8/KMpJVwnI1W |
|
161 |
+ 7fzcZ1+mbMeSJoAVIa9u7MgI+LIRZMokDRYeAMvEjm3GYpZDqA5l1dp7KochMep/ |
|
162 |
+ 0vSSTHt7ewJBAO6IbcUIDhXuh2qdxR/Xk5DdDCoxaD1o4ivyj9JsSlGa9JWD7kKN |
|
163 |
+ 6ZFFrn8i7uQuniC1Rwc/4yHhs6OqbiF695ECQQCBwVKzvFUwwDEr1yK4zXStSZ3g |
|
164 |
+ YqJaz4CV63RyK+z6ilaQq2H8FGaRR6yNBdYozre1/0ciAMxUS6H/6Fzk141/AkBe |
|
165 |
+ SguqIP8AaGObH3Z2mc65KsfOPe2IqNcOrDlx4mCWVXxtRdN+933mcPcDRpnMFSlo |
|
166 |
+ oH/NO9Ha6M8L2SjjjyohAkBJHU61+OWz/TAy1nxsMbFsISLn/JrdEZIf2uFORlDN |
|
167 |
+ Z3/XIQ+yeg4Jk1VbTMZ0/fHf9xMFR8acC/7n7jxnzQau |
|
168 |
+ -----END RSA PRIVATE KEY-----`) |
|
169 |
+ |
|
170 |
+ server, err := newTLSServer(expiredCert, expiredKey) |
|
171 |
+ if err != nil { |
|
172 |
+ t.Errorf(err.Error()) |
|
173 |
+ } |
|
174 |
+ server.StartTLS() |
|
175 |
+ defer server.Close() |
|
176 |
+ |
|
177 |
+ testCases := map[string]struct { |
|
178 |
+ serverURL string |
|
179 |
+ skipTLSVerify bool |
|
180 |
+ expectedErrMsg *regexp.Regexp |
|
181 |
+ }{ |
|
182 |
+ "succeed skipping tls": { |
|
183 |
+ serverURL: server.URL, |
|
184 |
+ skipTLSVerify: true, |
|
185 |
+ }, |
|
186 |
+ "certificate expired": { |
|
187 |
+ serverURL: server.URL, |
|
188 |
+ expectedErrMsg: regexp.MustCompile(`The server is using an invalid certificate(.*)has expired`), |
|
189 |
+ }, |
|
190 |
+ } |
|
191 |
+ |
|
192 |
+ for name, test := range testCases { |
|
193 |
+ t.Logf("evaluating test: %s", name) |
|
194 |
+ options := &LoginOptions{ |
|
195 |
+ Server: test.serverURL, |
|
196 |
+ InsecureTLS: test.skipTLSVerify, |
|
197 |
+ StartingKubeConfig: &kclientcmdapi.Config{}, |
|
198 |
+ } |
|
199 |
+ |
|
200 |
+ if _, err = options.getClientConfig(); err != nil { |
|
201 |
+ if !test.expectedErrMsg.MatchString(err.Error()) { |
|
202 |
+ t.Errorf("%s: expected error %q but got %q", name, test.expectedErrMsg, err) |
|
203 |
+ } |
|
204 |
+ if test.expectedErrMsg == nil { |
|
205 |
+ t.Errorf("%s: unexpected error: %v", name, err) |
|
206 |
+ } |
|
207 |
+ } else { |
|
208 |
+ if test.expectedErrMsg != nil { |
|
209 |
+ t.Errorf("%s: expected error but got nothing", name) |
|
210 |
+ } |
|
211 |
+ } |
|
212 |
+ } |
|
213 |
+} |
|
214 |
+ |
|
58 | 215 |
func TestDialToHTTPServer(t *testing.T) { |
59 | 216 |
invoked := make(chan struct{}, 1) |
60 | 217 |
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
... | ... |
@@ -92,3 +255,60 @@ func TestDialToHTTPServer(t *testing.T) { |
92 | 92 |
} |
93 | 93 |
} |
94 | 94 |
} |
95 |
+ |
|
96 |
+func TestDialToHTTPSServer(t *testing.T) { |
|
97 |
+ invoked := make(chan struct{}, 1) |
|
98 |
+ server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
99 |
+ invoked <- struct{}{} |
|
100 |
+ w.WriteHeader(http.StatusOK) |
|
101 |
+ })) |
|
102 |
+ defer server.Close() |
|
103 |
+ |
|
104 |
+ testCases := map[string]struct { |
|
105 |
+ serverURL string |
|
106 |
+ skipTLSVerify bool |
|
107 |
+ evalExpectedErr func(error) bool |
|
108 |
+ }{ |
|
109 |
+ "succeed dialing": { |
|
110 |
+ serverURL: server.URL, |
|
111 |
+ skipTLSVerify: true, |
|
112 |
+ }, |
|
113 |
+ "certificate unknown": { |
|
114 |
+ serverURL: server.URL, |
|
115 |
+ evalExpectedErr: clientcmd.IsCertificateAuthorityUnknown, |
|
116 |
+ }, |
|
117 |
+ } |
|
118 |
+ |
|
119 |
+ for name, test := range testCases { |
|
120 |
+ t.Logf("evaluating test: %s", name) |
|
121 |
+ clientConfig := &restclient.Config{ |
|
122 |
+ Host: test.serverURL, |
|
123 |
+ Insecure: test.skipTLSVerify, |
|
124 |
+ } |
|
125 |
+ if err := dialToServer(*clientConfig); err != nil { |
|
126 |
+ if test.evalExpectedErr == nil || !test.evalExpectedErr(err) { |
|
127 |
+ t.Errorf("%s: unexpected error: %v", name, err) |
|
128 |
+ } |
|
129 |
+ } else { |
|
130 |
+ if test.evalExpectedErr != nil { |
|
131 |
+ t.Errorf("%s: expected error but got nothing", name) |
|
132 |
+ } |
|
133 |
+ } |
|
134 |
+ } |
|
135 |
+} |
|
136 |
+ |
|
137 |
+func newTLSServer(certString, keyString string) (*httptest.Server, error) { |
|
138 |
+ invoked := make(chan struct{}, 1) |
|
139 |
+ server := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
140 |
+ invoked <- struct{}{} |
|
141 |
+ w.WriteHeader(http.StatusOK) |
|
142 |
+ })) |
|
143 |
+ cert, err := tls.X509KeyPair([]byte(certString), []byte(keyString)) |
|
144 |
+ if err != nil { |
|
145 |
+ return nil, fmt.Errorf("error configuring server cert: %s", err) |
|
146 |
+ } |
|
147 |
+ server.TLS = &tls.Config{ |
|
148 |
+ Certificates: []tls.Certificate{cert}, |
|
149 |
+ } |
|
150 |
+ return server, nil |
|
151 |
+} |
... | ... |
@@ -1,6 +1,7 @@ |
1 | 1 |
package clientcmd |
2 | 2 |
|
3 | 3 |
import ( |
4 |
+ "crypto/x509" |
|
4 | 5 |
"errors" |
5 | 6 |
"fmt" |
6 | 7 |
"strings" |
... | ... |
@@ -13,6 +14,8 @@ const ( |
13 | 13 |
unknownReason = iota |
14 | 14 |
noServerFoundReason |
15 | 15 |
certificateAuthorityUnknownReason |
16 |
+ certificateHostnameErrorReason |
|
17 |
+ certificateInvalidReason |
|
16 | 18 |
configurationInvalidReason |
17 | 19 |
tlsOversizedRecordReason |
18 | 20 |
|
... | ... |
@@ -50,6 +53,12 @@ func GetPrettyMessageForServer(err error, serverName string) string { |
50 | 50 |
serverName = "server" |
51 | 51 |
} |
52 | 52 |
return fmt.Sprintf(tlsOversizedRecordMsg, err, serverName) |
53 |
+ |
|
54 |
+ case certificateHostnameErrorReason: |
|
55 |
+ return fmt.Sprintf("The server is using a certificate that does not match its hostname: %s", err) |
|
56 |
+ |
|
57 |
+ case certificateInvalidReason: |
|
58 |
+ return fmt.Sprintf("The server is using an invalid certificate: %s", err) |
|
53 | 59 |
} |
54 | 60 |
|
55 | 61 |
return err.Error() |
... | ... |
@@ -91,6 +100,17 @@ func IsTLSOversizedRecord(err error) bool { |
91 | 91 |
return detectReason(err) == tlsOversizedRecordReason |
92 | 92 |
} |
93 | 93 |
|
94 |
+// IsCertificateHostnameError checks whether the set of authorized names doesn't match the requested name |
|
95 |
+func IsCertificateHostnameError(err error) bool { |
|
96 |
+ return detectReason(err) == certificateHostnameErrorReason |
|
97 |
+} |
|
98 |
+ |
|
99 |
+// IsCertificateInvalid checks whether the certificate is invalid for reasons like expired, CA not authorized |
|
100 |
+// to sign, there are too many cert intermediates, or the cert usage is not valid for the wanted purpose. |
|
101 |
+func IsCertificateInvalid(err error) bool { |
|
102 |
+ return detectReason(err) == certificateInvalidReason |
|
103 |
+} |
|
104 |
+ |
|
94 | 105 |
func detectReason(err error) int { |
95 | 106 |
if err != nil { |
96 | 107 |
switch { |
... | ... |
@@ -103,6 +123,14 @@ func detectReason(err error) int { |
103 | 103 |
case strings.Contains(err.Error(), "tls: oversized record received"): |
104 | 104 |
return tlsOversizedRecordReason |
105 | 105 |
} |
106 |
+ switch err.(type) { |
|
107 |
+ case x509.UnknownAuthorityError: |
|
108 |
+ return certificateAuthorityUnknownReason |
|
109 |
+ case x509.HostnameError: |
|
110 |
+ return certificateHostnameErrorReason |
|
111 |
+ case x509.CertificateInvalidError: |
|
112 |
+ return certificateInvalidReason |
|
113 |
+ } |
|
106 | 114 |
} |
107 | 115 |
return unknownReason |
108 | 116 |
} |