View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  
28  package org.apache.hc.client5.http.ssl;
29  
30  import org.apache.hc.client5.http.psl.DomainType;
31  import org.apache.hc.client5.http.psl.PublicSuffixList;
32  import org.apache.hc.client5.http.psl.PublicSuffixListParser;
33  import org.apache.hc.client5.http.psl.PublicSuffixMatcher;
34  import org.junit.Assert;
35  import org.junit.Before;
36  import org.junit.Test;
37  
38  import javax.net.ssl.SSLException;
39  import java.io.ByteArrayInputStream;
40  import java.io.IOException;
41  import java.io.InputStream;
42  import java.io.InputStreamReader;
43  import java.nio.charset.StandardCharsets;
44  import java.security.cert.CertificateFactory;
45  import java.security.cert.X509Certificate;
46  import java.util.Collections;
47  import java.util.List;
48  
49  /**
50   * Unit tests for {@link org.apache.hc.client5.http.ssl.DefaultHostnameVerifier}.
51   */
52  public class TestDefaultHostnameVerifier {
53  
54      private DefaultHostnameVerifier impl;
55      private PublicSuffixMatcher publicSuffixMatcher;
56      private DefaultHostnameVerifier implWithPublicSuffixCheck;
57  
58      private static final String PUBLIC_SUFFIX_MATCHER_SOURCE_FILE = "suffixlistmatcher.txt";
59  
60      @Before
61      public void setup() throws IOException {
62          impl = new DefaultHostnameVerifier();
63  
64          // Load the test PublicSuffixMatcher
65          final ClassLoader classLoader = getClass().getClassLoader();
66          final InputStream in = classLoader.getResourceAsStream(PUBLIC_SUFFIX_MATCHER_SOURCE_FILE);
67          Assert.assertNotNull(in);
68          final List<PublicSuffixList> lists = new PublicSuffixListParser().parseByType(
69                  new InputStreamReader(in, StandardCharsets.UTF_8));
70          publicSuffixMatcher = new PublicSuffixMatcher(lists);
71  
72          implWithPublicSuffixCheck = new DefaultHostnameVerifier(publicSuffixMatcher);
73      }
74  
75      @Test
76      public void testVerify() throws Exception {
77          final CertificateFactory cf = CertificateFactory.getInstance("X.509");
78          InputStream in;
79          X509Certificate x509;
80          in = new ByteArrayInputStream(CertificatesToPlayWith.X509_FOO);
81          x509 = (X509Certificate) cf.generateCertificate(in);
82  
83          impl.verify("foo.com", x509);
84          exceptionPlease(impl, "a.foo.com", x509);
85          exceptionPlease(impl, "bar.com", x509);
86  
87          in = new ByteArrayInputStream(CertificatesToPlayWith.X509_HANAKO);
88          x509 = (X509Certificate) cf.generateCertificate(in);
89          impl.verify("\u82b1\u5b50.co.jp", x509);
90          exceptionPlease(impl, "a.\u82b1\u5b50.co.jp", x509);
91  
92          in = new ByteArrayInputStream(CertificatesToPlayWith.X509_FOO_BAR);
93          x509 = (X509Certificate) cf.generateCertificate(in);
94          exceptionPlease(impl, "foo.com", x509);
95          exceptionPlease(impl, "a.foo.com", x509);
96          impl.verify("bar.com", x509);
97          exceptionPlease(impl, "a.bar.com", x509);
98  
99          in = new ByteArrayInputStream(CertificatesToPlayWith.X509_FOO_BAR_HANAKO);
100         x509 = (X509Certificate) cf.generateCertificate(in);
101         exceptionPlease(impl, "foo.com", x509);
102         exceptionPlease(impl, "a.foo.com", x509);
103         impl.verify("bar.com", x509);
104         exceptionPlease(impl, "a.bar.com", x509);
105 
106         /*
107            Java isn't extracting international subjectAlts properly.  (Or
108            OpenSSL isn't storing them properly).
109         */
110         // DEFAULT.verify("\u82b1\u5b50.co.jp", x509 );
111         // impl.verify("\u82b1\u5b50.co.jp", x509 );
112         exceptionPlease(impl, "a.\u82b1\u5b50.co.jp", x509);
113 
114         in = new ByteArrayInputStream(CertificatesToPlayWith.X509_NO_CNS_FOO);
115         x509 = (X509Certificate) cf.generateCertificate(in);
116         impl.verify("foo.com", x509);
117         exceptionPlease(impl, "a.foo.com", x509);
118 
119         in = new ByteArrayInputStream(CertificatesToPlayWith.X509_NO_CNS_FOO);
120         x509 = (X509Certificate) cf.generateCertificate(in);
121         impl.verify("foo.com", x509);
122         exceptionPlease(impl, "a.foo.com", x509);
123 
124         in = new ByteArrayInputStream(CertificatesToPlayWith.X509_THREE_CNS_FOO_BAR_HANAKO);
125         x509 = (X509Certificate) cf.generateCertificate(in);
126         exceptionPlease(impl, "foo.com", x509);
127         exceptionPlease(impl, "a.foo.com", x509);
128         exceptionPlease(impl, "bar.com", x509);
129         exceptionPlease(impl, "a.bar.com", x509);
130         impl.verify("\u82b1\u5b50.co.jp", x509);
131         exceptionPlease(impl, "a.\u82b1\u5b50.co.jp", x509);
132 
133         in = new ByteArrayInputStream(CertificatesToPlayWith.X509_WILD_FOO);
134         x509 = (X509Certificate) cf.generateCertificate(in);
135         exceptionPlease(impl, "foo.com", x509);
136         impl.verify("www.foo.com", x509);
137         impl.verify("\u82b1\u5b50.foo.com", x509);
138         exceptionPlease(impl, "a.b.foo.com", x509);
139 
140         in = new ByteArrayInputStream(CertificatesToPlayWith.X509_WILD_CO_JP);
141         x509 = (X509Certificate) cf.generateCertificate(in);
142         // Silly test because no-one would ever be able to lookup an IP address
143         // using "*.co.jp".
144         impl.verify("*.co.jp", x509);
145         impl.verify("foo.co.jp", x509);
146         impl.verify("\u82b1\u5b50.co.jp", x509);
147 
148         exceptionPlease(implWithPublicSuffixCheck, "foo.co.jp", x509);
149         exceptionPlease(implWithPublicSuffixCheck, "\u82b1\u5b50.co.jp", x509);
150 
151         in = new ByteArrayInputStream(CertificatesToPlayWith.X509_WILD_FOO_BAR_HANAKO);
152         x509 = (X509Certificate) cf.generateCertificate(in);
153         // try the foo.com variations
154         exceptionPlease(impl, "foo.com", x509);
155         exceptionPlease(impl, "www.foo.com", x509);
156         exceptionPlease(impl, "\u82b1\u5b50.foo.com", x509);
157         exceptionPlease(impl, "a.b.foo.com", x509);
158         // try the bar.com variations
159         exceptionPlease(impl, "bar.com", x509);
160         impl.verify("www.bar.com", x509);
161         impl.verify("\u82b1\u5b50.bar.com", x509);
162         exceptionPlease(impl, "a.b.bar.com", x509);
163 
164         in = new ByteArrayInputStream(CertificatesToPlayWith.X509_MULTIPLE_VALUE_AVA);
165         x509 = (X509Certificate) cf.generateCertificate(in);
166         impl.verify("repository.infonotary.com", x509);
167 
168         in = new ByteArrayInputStream(CertificatesToPlayWith.S_GOOGLE_COM);
169         x509 = (X509Certificate) cf.generateCertificate(in);
170         impl.verify("*.google.com", x509);
171 
172         in = new ByteArrayInputStream(CertificatesToPlayWith.S_GOOGLE_COM);
173         x509 = (X509Certificate) cf.generateCertificate(in);
174         impl.verify("*.Google.com", x509);
175 
176         in = new ByteArrayInputStream(CertificatesToPlayWith.IP_1_1_1_1);
177         x509 = (X509Certificate) cf.generateCertificate(in);
178         impl.verify("1.1.1.1", x509);
179         impl.verify("dummy-value.com", x509);
180 
181         exceptionPlease(impl, "1.1.1.2", x509);
182         exceptionPlease(impl, "not-the-cn.com", x509);
183 
184         in = new ByteArrayInputStream(CertificatesToPlayWith.EMAIL_ALT_SUBJECT_NAME);
185         x509 = (X509Certificate) cf.generateCertificate(in);
186         impl.verify("www.company.com", x509);
187     }
188 
189     @Test
190     public void testSubjectAlt() throws Exception {
191         final CertificateFactory cf = CertificateFactory.getInstance("X.509");
192         final InputStream in = new ByteArrayInputStream(CertificatesToPlayWith.X509_MULTIPLE_SUBJECT_ALT);
193         final X509Certificate x509 = (X509Certificate) cf.generateCertificate(in);
194 
195         Assert.assertEquals("CN=localhost, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=CH",
196                 x509.getSubjectDN().getName());
197 
198         impl.verify("localhost.localdomain", x509);
199         impl.verify("127.0.0.1", x509);
200 
201         try {
202             impl.verify("localhost", x509);
203             Assert.fail("SSLException should have been thrown");
204         } catch (final SSLException ex) {
205             // expected
206         }
207         try {
208             impl.verify("local.host", x509);
209             Assert.fail("SSLException should have been thrown");
210         } catch (final SSLException ex) {
211             // expected
212         }
213         try {
214             impl.verify("127.0.0.2", x509);
215             Assert.fail("SSLException should have been thrown");
216         } catch (final SSLException ex) {
217             // expected
218         }
219     }
220 
221     public void exceptionPlease(final DefaultHostnameVerifier hv, final String host,
222                                 final X509Certificate x509) {
223         try {
224             hv.verify(host, x509);
225             Assert.fail("HostnameVerifier shouldn't allow [" + host + "]");
226         }
227         catch(final SSLException e) {
228             // whew!  we're okay!
229         }
230     }
231 
232     @Test
233     public void testDomainRootMatching() {
234 
235         Assert.assertFalse(DefaultHostnameVerifier.matchDomainRoot("a.b.c", null));
236         Assert.assertTrue(DefaultHostnameVerifier.matchDomainRoot("a.b.c", "a.b.c"));
237         Assert.assertFalse(DefaultHostnameVerifier.matchDomainRoot("aa.b.c", "a.b.c"));
238         Assert.assertFalse(DefaultHostnameVerifier.matchDomainRoot("a.b.c", "aa.b.c"));
239         Assert.assertTrue(DefaultHostnameVerifier.matchDomainRoot("a.a.b.c", "a.b.c"));
240     }
241 
242     @Test
243     public void testIdentityMatching() {
244 
245         Assert.assertTrue(DefaultHostnameVerifier.matchIdentity("a.b.c", "*.b.c"));
246         Assert.assertTrue(DefaultHostnameVerifier.matchIdentityStrict("a.b.c", "*.b.c"));
247 
248         Assert.assertTrue(DefaultHostnameVerifier.matchIdentity("s.a.b.c", "*.b.c"));
249         Assert.assertFalse(DefaultHostnameVerifier.matchIdentityStrict("s.a.b.c", "*.b.c")); // subdomain not OK
250 
251         Assert.assertFalse(DefaultHostnameVerifier.matchIdentity("a.gov.uk", "*.gov.uk", publicSuffixMatcher));
252         Assert.assertFalse(DefaultHostnameVerifier.matchIdentityStrict("a.gov.uk", "*.gov.uk", publicSuffixMatcher));  // Bad 2TLD
253 
254         Assert.assertTrue(DefaultHostnameVerifier.matchIdentity("s.a.gov.uk", "*.a.gov.uk", publicSuffixMatcher));
255         Assert.assertTrue(DefaultHostnameVerifier.matchIdentityStrict("s.a.gov.uk", "*.a.gov.uk", publicSuffixMatcher));
256 
257         Assert.assertFalse(DefaultHostnameVerifier.matchIdentity("s.a.gov.uk", "*.gov.uk", publicSuffixMatcher));
258         Assert.assertFalse(DefaultHostnameVerifier.matchIdentityStrict("s.a.gov.uk", "*.gov.uk", publicSuffixMatcher));  // BBad 2TLD/no subdomain allowed
259 
260         Assert.assertTrue(DefaultHostnameVerifier.matchIdentity("a.gov.com", "*.gov.com", publicSuffixMatcher));
261         Assert.assertTrue(DefaultHostnameVerifier.matchIdentityStrict("a.gov.com", "*.gov.com", publicSuffixMatcher));
262 
263         Assert.assertTrue(DefaultHostnameVerifier.matchIdentity("s.a.gov.com", "*.gov.com", publicSuffixMatcher));
264         Assert.assertFalse(DefaultHostnameVerifier.matchIdentityStrict("s.a.gov.com", "*.gov.com", publicSuffixMatcher)); // no subdomain allowed
265 
266         Assert.assertFalse(DefaultHostnameVerifier.matchIdentity("a.gov.uk", "a*.gov.uk", publicSuffixMatcher));
267         Assert.assertFalse(DefaultHostnameVerifier.matchIdentityStrict("a.gov.uk", "a*.gov.uk", publicSuffixMatcher)); // Bad 2TLD
268 
269         Assert.assertFalse(DefaultHostnameVerifier.matchIdentity("s.a.gov.uk", "a*.gov.uk", publicSuffixMatcher)); // Bad 2TLD
270         Assert.assertFalse(DefaultHostnameVerifier.matchIdentityStrict("s.a.gov.uk", "a*.gov.uk", publicSuffixMatcher)); // Bad 2TLD/no subdomain allowed
271 
272         Assert.assertFalse(DefaultHostnameVerifier.matchIdentity("a.b.c", "*.b.*"));
273         Assert.assertFalse(DefaultHostnameVerifier.matchIdentityStrict("a.b.c", "*.b.*"));
274 
275         Assert.assertFalse(DefaultHostnameVerifier.matchIdentity("a.b.c", "*.*.c"));
276         Assert.assertFalse(DefaultHostnameVerifier.matchIdentityStrict("a.b.c", "*.*.c"));
277     }
278 
279     @Test
280     public void testHTTPCLIENT_1097() {
281         Assert.assertTrue(DefaultHostnameVerifier.matchIdentity("a.b.c", "a*.b.c"));
282         Assert.assertTrue(DefaultHostnameVerifier.matchIdentityStrict("a.b.c", "a*.b.c"));
283 
284         Assert.assertTrue(DefaultHostnameVerifier.matchIdentity("a.a.b.c", "a*.b.c"));
285         Assert.assertFalse(DefaultHostnameVerifier.matchIdentityStrict("a.a.b.c", "a*.b.c"));
286     }
287 
288     @Test
289     public void testHTTPCLIENT_1255() {
290         Assert.assertTrue(DefaultHostnameVerifier.matchIdentity("mail.a.b.c.com", "m*.a.b.c.com"));
291         Assert.assertTrue(DefaultHostnameVerifier.matchIdentityStrict("mail.a.b.c.com", "m*.a.b.c.com"));
292     }
293 
294     @Test
295     public void testHTTPCLIENT_1997_ANY() { // Only True on all domains
296         String domain;
297         // Unknown
298         domain = "dev.b.cloud.a";
299         Assert.assertTrue(DefaultHostnameVerifier.matchIdentity(        "service.apps." + domain, "*.apps." + domain));
300         Assert.assertTrue(DefaultHostnameVerifier.matchIdentityStrict(  "service.apps." + domain, "*.apps." + domain));
301         Assert.assertTrue(DefaultHostnameVerifier.matchIdentity(        "service.apps." + domain, "*.apps." + domain, publicSuffixMatcher));
302         Assert.assertTrue(DefaultHostnameVerifier.matchIdentityStrict(  "service.apps." + domain, "*.apps." + domain, publicSuffixMatcher));
303 
304         // ICANN
305         domain = "dev.b.cloud.com";
306         Assert.assertTrue(DefaultHostnameVerifier.matchIdentity(        "service.apps." + domain, "*.apps." + domain));
307         Assert.assertTrue(DefaultHostnameVerifier.matchIdentityStrict(  "service.apps." + domain, "*.apps." + domain));
308         Assert.assertTrue(DefaultHostnameVerifier.matchIdentity(        "service.apps." + domain, "*.apps." + domain, publicSuffixMatcher));
309         Assert.assertTrue(DefaultHostnameVerifier.matchIdentityStrict(  "service.apps." + domain, "*.apps." + domain, publicSuffixMatcher));
310 
311         // PRIVATE
312         domain = "dev.b.cloud.lan";
313         Assert.assertTrue(DefaultHostnameVerifier.matchIdentity(        "service.apps." + domain, "*.apps." + domain));
314         Assert.assertTrue(DefaultHostnameVerifier.matchIdentityStrict(  "service.apps." + domain, "*.apps." + domain));
315         Assert.assertTrue(DefaultHostnameVerifier.matchIdentity(        "service.apps." + domain, "*.apps." + domain, publicSuffixMatcher));
316         Assert.assertTrue(DefaultHostnameVerifier.matchIdentityStrict(  "service.apps." + domain, "*.apps." + domain, publicSuffixMatcher));
317     }
318 
319     @Test
320     public void testHTTPCLIENT_1997_ICANN() { // Only True on ICANN domains
321         String domain;
322         // Unknown
323         domain = "dev.b.cloud.a";
324         Assert.assertFalse(DefaultHostnameVerifier.matchIdentity(        "service.apps." + domain, "*.apps." + domain, publicSuffixMatcher, DomainType.ICANN));
325         Assert.assertFalse(DefaultHostnameVerifier.matchIdentityStrict(  "service.apps." + domain, "*.apps." + domain, publicSuffixMatcher, DomainType.ICANN));
326 
327         // ICANN
328         domain = "dev.b.cloud.com";
329         Assert.assertTrue(DefaultHostnameVerifier.matchIdentity(        "service.apps." + domain, "*.apps." + domain, publicSuffixMatcher, DomainType.ICANN));
330         Assert.assertTrue(DefaultHostnameVerifier.matchIdentityStrict(  "service.apps." + domain, "*.apps." + domain, publicSuffixMatcher, DomainType.ICANN));
331 
332         // PRIVATE
333         domain = "dev.b.cloud.lan";
334         Assert.assertFalse(DefaultHostnameVerifier.matchIdentity(        "service.apps." + domain, "*.apps." + domain, publicSuffixMatcher, DomainType.ICANN));
335         Assert.assertFalse(DefaultHostnameVerifier.matchIdentityStrict(  "service.apps." + domain, "*.apps." + domain, publicSuffixMatcher, DomainType.ICANN));
336     }
337 
338     @Test
339     public void testHTTPCLIENT_1997_PRIVATE() { // Only True on PRIVATE domains
340         String domain;
341         // Unknown
342         domain = "dev.b.cloud.a";
343         Assert.assertFalse(DefaultHostnameVerifier.matchIdentity(        "service.apps." + domain, "*.apps." + domain, publicSuffixMatcher, DomainType.PRIVATE));
344         Assert.assertFalse(DefaultHostnameVerifier.matchIdentityStrict(  "service.apps." + domain, "*.apps." + domain, publicSuffixMatcher, DomainType.PRIVATE));
345 
346         // ICANN
347         domain = "dev.b.cloud.com";
348         Assert.assertFalse(DefaultHostnameVerifier.matchIdentity(        "service.apps." + domain, "*.apps." + domain, publicSuffixMatcher, DomainType.PRIVATE));
349         Assert.assertFalse(DefaultHostnameVerifier.matchIdentityStrict(  "service.apps." + domain, "*.apps." + domain, publicSuffixMatcher, DomainType.PRIVATE));
350 
351         // PRIVATE
352         domain = "dev.b.cloud.lan";
353         Assert.assertTrue(DefaultHostnameVerifier.matchIdentity(        "service.apps." + domain, "*.apps." + domain, publicSuffixMatcher, DomainType.PRIVATE));
354         Assert.assertTrue(DefaultHostnameVerifier.matchIdentityStrict(  "service.apps." + domain, "*.apps." + domain, publicSuffixMatcher, DomainType.PRIVATE));
355     }
356 
357     @Test
358     public void testHTTPCLIENT_1997_UNKNOWN() { // Only True on all domains (same as ANY)
359         String domain;
360         // Unknown
361         domain = "dev.b.cloud.a";
362         Assert.assertTrue(DefaultHostnameVerifier.matchIdentity(        "service.apps." + domain, "*.apps." + domain, publicSuffixMatcher, DomainType.UNKNOWN));
363         Assert.assertTrue(DefaultHostnameVerifier.matchIdentityStrict(  "service.apps." + domain, "*.apps." + domain, publicSuffixMatcher, DomainType.UNKNOWN));
364 
365         // ICANN
366         domain = "dev.b.cloud.com";
367         Assert.assertTrue(DefaultHostnameVerifier.matchIdentity(        "service.apps." + domain, "*.apps." + domain, publicSuffixMatcher, DomainType.UNKNOWN));
368         Assert.assertTrue(DefaultHostnameVerifier.matchIdentityStrict(  "service.apps." + domain, "*.apps." + domain, publicSuffixMatcher, DomainType.UNKNOWN));
369 
370         // PRIVATE
371         domain = "dev.b.cloud.lan";
372         Assert.assertTrue(DefaultHostnameVerifier.matchIdentity(        "service.apps." + domain, "*.apps." + domain, publicSuffixMatcher, DomainType.UNKNOWN));
373         Assert.assertTrue(DefaultHostnameVerifier.matchIdentityStrict(  "service.apps." + domain, "*.apps." + domain, publicSuffixMatcher, DomainType.UNKNOWN));
374     }
375 
376     @Test // Check compressed IPv6 hostname matching
377     public void testHTTPCLIENT_1316() throws Exception{
378         final String host1 = "2001:0db8:aaaa:bbbb:cccc:0:0:0001";
379         DefaultHostnameVerifier.matchIPv6Address(host1, Collections.singletonList(SubjectName.IP("2001:0db8:aaaa:bbbb:cccc:0:0:0001")));
380         DefaultHostnameVerifier.matchIPv6Address(host1, Collections.singletonList(SubjectName.IP("2001:0db8:aaaa:bbbb:cccc::1")));
381         try {
382             DefaultHostnameVerifier.matchIPv6Address(host1, Collections.singletonList(SubjectName.IP("2001:0db8:aaaa:bbbb:cccc::10")));
383             Assert.fail("SSLException expected");
384         } catch (final SSLException expected) {
385         }
386         final String host2 = "2001:0db8:aaaa:bbbb:cccc::1";
387         DefaultHostnameVerifier.matchIPv6Address(host2, Collections.singletonList(SubjectName.IP("2001:0db8:aaaa:bbbb:cccc:0:0:0001")));
388         DefaultHostnameVerifier.matchIPv6Address(host2, Collections.singletonList(SubjectName.IP("2001:0db8:aaaa:bbbb:cccc::1")));
389         try {
390             DefaultHostnameVerifier.matchIPv6Address(host2, Collections.singletonList(SubjectName.IP("2001:0db8:aaaa:bbbb:cccc::10")));
391             Assert.fail("SSLException expected");
392         } catch (final SSLException expected) {
393         }
394     }
395 
396     @Test
397     public void testHTTPCLIENT_2149() throws Exception {
398         final CertificateFactory cf = CertificateFactory.getInstance("X.509");
399         final InputStream in = new ByteArrayInputStream(CertificatesToPlayWith.SUBJECT_ALT_IP_ONLY);
400         final X509Certificate x509 = (X509Certificate) cf.generateCertificate(in);
401 
402         Assert.assertEquals("CN=www.foo.com", x509.getSubjectDN().getName());
403 
404         impl.verify("127.0.0.1", x509);
405         impl.verify("www.foo.com", x509);
406 
407         exceptionPlease(impl, "127.0.0.2", x509);
408         exceptionPlease(impl, "www.bar.com", x509);
409     }
410 
411     @Test
412     public void testExtractCN() throws Exception {
413         Assert.assertEquals("blah", DefaultHostnameVerifier.extractCN("cn=blah, ou=blah, o=blah"));
414         Assert.assertEquals("blah", DefaultHostnameVerifier.extractCN("cn=blah, cn=yada, cn=booh"));
415         Assert.assertEquals("blah", DefaultHostnameVerifier.extractCN("c = pampa ,  cn  =    blah    , ou = blah , o = blah"));
416         Assert.assertEquals("blah", DefaultHostnameVerifier.extractCN("cn=\"blah\", ou=blah, o=blah"));
417         Assert.assertEquals("blah  blah", DefaultHostnameVerifier.extractCN("cn=\"blah  blah\", ou=blah, o=blah"));
418         Assert.assertEquals("blah, blah", DefaultHostnameVerifier.extractCN("cn=\"blah, blah\", ou=blah, o=blah"));
419         Assert.assertEquals("blah, blah", DefaultHostnameVerifier.extractCN("cn=blah\\, blah, ou=blah, o=blah"));
420         Assert.assertEquals("blah", DefaultHostnameVerifier.extractCN("c = cn=uuh, cn=blah, ou=blah, o=blah"));
421         try {
422             DefaultHostnameVerifier.extractCN("blah,blah");
423             Assert.fail("SSLException expected");
424         } catch (final SSLException expected) {
425         }
426         try {
427             DefaultHostnameVerifier.extractCN("cn,o=blah");
428             Assert.fail("SSLException expected");
429         } catch (final SSLException expected) {
430         }
431     }
432 
433     @Test
434     public void testMatchDNSName() throws Exception {
435         DefaultHostnameVerifier.matchDNSName(
436                 "host.domain.com",
437                 Collections.singletonList(SubjectName.DNS("*.domain.com")),
438                 publicSuffixMatcher);
439         DefaultHostnameVerifier.matchDNSName(
440                 "host.xx",
441                 Collections.singletonList(SubjectName.DNS("*.xx")),
442                 publicSuffixMatcher);
443         DefaultHostnameVerifier.matchDNSName(
444                 "host.appspot.com",
445                 Collections.singletonList(SubjectName.DNS("*.appspot.com")),
446                 publicSuffixMatcher);
447         DefaultHostnameVerifier.matchDNSName(
448                 "demo-s3-bucket.s3.eu-central-1.amazonaws.com",
449                 Collections.singletonList(SubjectName.DNS("*.s3.eu-central-1.amazonaws.com")),
450                 publicSuffixMatcher);
451         DefaultHostnameVerifier.matchDNSName(
452                 "hostname-workspace-1.local",
453                 Collections.singletonList(SubjectName.DNS("hostname-workspace-1.local")),
454                 publicSuffixMatcher);
455 
456         try {
457             DefaultHostnameVerifier.matchDNSName(
458                 "host.domain.com",
459                 Collections.singletonList(SubjectName.DNS("some.other.com")),
460                 publicSuffixMatcher);
461             Assert.fail("SSLException should have been thrown");
462         } catch (final SSLException ex) {
463             // expected
464         }
465     }
466 
467 }