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