1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with this 4 * work for additional information regarding copyright ownership. The ASF 5 * licenses this file to You under the Apache License, Version 2.0 (the 6 * "License"); you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 * License for the specific language governing permissions and limitations under 15 * the License. 16 */ 17 18 package tests.api.javax.net.ssl; 19 20 import java.io.ByteArrayInputStream; 21 import java.io.InputStream; 22 import java.net.URL; 23 import java.security.cert.CertificateFactory; 24 import java.security.cert.X509Certificate; 25 import javax.net.ssl.HostnameVerifier; 26 import javax.net.ssl.HttpsURLConnection; 27 import javax.net.ssl.SSLSession; 28 import javax.security.auth.x500.X500Principal; 29 import junit.framework.TestCase; 30 import org.apache.harmony.xnet.tests.support.mySSLSession; 31 32 /** 33 * Tests for <code>HostnameVerifier</code> class constructors and methods. 34 * 35 */ 36 public class HostnameVerifierTest extends TestCase implements 37 CertificatesToPlayWith { 38 39 /** 40 * javax.net.ssl.HostnameVerifier#verify(String hostname, SSLSession 41 * session) 42 */ test_verify()43 public final void test_verify() throws Exception { 44 mySSLSession session = new mySSLSession("localhost", 1080, null); 45 HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier(); 46 assertFalse(hv.verify("localhost", session)); 47 } 48 49 // copied and modified from apache http client test suite. testVerify()50 public void testVerify() throws Exception { 51 CertificateFactory cf = CertificateFactory.getInstance("X.509"); 52 InputStream in; 53 X509Certificate x509; 54 in = new ByteArrayInputStream(X509_FOO); 55 x509 = (X509Certificate) cf.generateCertificate(in); 56 mySSLSession session = new mySSLSession(new X509Certificate[] {x509}); 57 58 HostnameVerifier verifier = HttpsURLConnection.getDefaultHostnameVerifier(); 59 assertTrue(verifier.verify("foo.com", session)); 60 assertFalse(verifier.verify("a.foo.com", session)); 61 assertFalse(verifier.verify("bar.com", session)); 62 63 in = new ByteArrayInputStream(X509_HANAKO); 64 x509 = (X509Certificate) cf.generateCertificate(in); 65 session = new mySSLSession(new X509Certificate[] {x509}); 66 assertTrue(verifier.verify("\u82b1\u5b50.co.jp", session)); 67 assertFalse(verifier.verify("a.\u82b1\u5b50.co.jp", session)); 68 69 in = new ByteArrayInputStream(X509_FOO_BAR); 70 x509 = (X509Certificate) cf.generateCertificate(in); 71 session = new mySSLSession(new X509Certificate[] {x509}); 72 assertTrue(verifier.verify("foo.com", session)); 73 assertFalse(verifier.verify("a.foo.com", session)); 74 assertTrue(verifier.verify("bar.com", session)); 75 assertFalse(verifier.verify("a.bar.com", session)); 76 77 in = new ByteArrayInputStream(X509_FOO_BAR_HANAKO); 78 x509 = (X509Certificate) cf.generateCertificate(in); 79 session = new mySSLSession(new X509Certificate[] {x509}); 80 assertTrue(verifier.verify("foo.com", session)); 81 assertFalse(verifier.verify("a.foo.com", session)); 82 // these checks test alternative subjects. The test data contains an 83 // alternative subject starting with a japanese kanji character. This is 84 // not supported by Android because the underlying implementation from 85 // harmony follows the definition from rfc 1034 page 10 for alternative 86 // subject names. This causes the code to drop all alternative subjects. 87 // assertTrue(verifier.verify("bar.com", session)); 88 // assertFalse(verifier.verify("a.bar.com", session)); 89 // assertFalse(verifier.verify("a.\u82b1\u5b50.co.jp", session)); 90 91 in = new ByteArrayInputStream(X509_NO_CNS_FOO); 92 x509 = (X509Certificate) cf.generateCertificate(in); 93 session = new mySSLSession(new X509Certificate[] {x509}); 94 assertTrue(verifier.verify("foo.com", session)); 95 assertFalse(verifier.verify("a.foo.com", session)); 96 97 in = new ByteArrayInputStream(X509_NO_CNS_FOO); 98 x509 = (X509Certificate) cf.generateCertificate(in); 99 session = new mySSLSession(new X509Certificate[] {x509}); 100 assertTrue(verifier.verify("foo.com", session)); 101 assertFalse(verifier.verify("a.foo.com", session)); 102 103 in = new ByteArrayInputStream(X509_THREE_CNS_FOO_BAR_HANAKO); 104 x509 = (X509Certificate) cf.generateCertificate(in); 105 session = new mySSLSession(new X509Certificate[] {x509}); 106 assertFalse(verifier.verify("foo.com", session)); 107 assertFalse(verifier.verify("a.foo.com", session)); 108 assertFalse(verifier.verify("bar.com", session)); 109 assertFalse(verifier.verify("a.bar.com", session)); 110 assertTrue(verifier.verify("\u82b1\u5b50.co.jp", session)); 111 assertFalse(verifier.verify("a.\u82b1\u5b50.co.jp", session)); 112 113 in = new ByteArrayInputStream(X509_WILD_FOO); 114 x509 = (X509Certificate) cf.generateCertificate(in); 115 session = new mySSLSession(new X509Certificate[] {x509}); 116 assertFalse(verifier.verify("foo.com", session)); 117 assertTrue(verifier.verify("www.foo.com", session)); 118 assertTrue(verifier.verify("\u82b1\u5b50.foo.com", session)); 119 assertTrue(verifier.verify("a.b.foo.com", session)); 120 121 in = new ByteArrayInputStream(X509_WILD_CO_JP); 122 x509 = (X509Certificate) cf.generateCertificate(in); 123 session = new mySSLSession(new X509Certificate[] {x509}); 124 assertFalse(verifier.verify("foo.co.jp", session)); 125 assertFalse(verifier.verify("\u82b1\u5b50.co.jp", session)); 126 127 in = new ByteArrayInputStream(X509_WILD_FOO_BAR_HANAKO); 128 x509 = (X509Certificate) cf.generateCertificate(in); 129 session = new mySSLSession(new X509Certificate[] {x509}); 130 // try the foo.com variations 131 assertFalse(verifier.verify("foo.com", session)); 132 assertTrue(verifier.verify("www.foo.com", session)); 133 assertTrue(verifier.verify("\u82b1\u5b50.foo.com", session)); 134 assertTrue(verifier.verify("a.b.foo.com", session)); 135 // these checks test alternative subjects. The test data contains an 136 // alternative subject starting with a japanese kanji character. This is 137 // not supported by Android because the underlying implementation from 138 // harmony follows the definition from rfc 1034 page 10 for alternative 139 // subject names. This causes the code to drop all alternative subjects. 140 // assertFalse(verifier.verify("bar.com", session)); 141 // assertTrue(verifier.verify("www.bar.com", session)); 142 // assertTrue(verifier.verify("\u82b1\u5b50.bar.com", session)); 143 // assertTrue(verifier.verify("a.b.bar.com", session)); 144 } 145 testSubjectAlt()146 public void testSubjectAlt() throws Exception { 147 CertificateFactory cf = CertificateFactory.getInstance("X.509"); 148 InputStream in = new ByteArrayInputStream(X509_MULTIPLE_SUBJECT_ALT); 149 X509Certificate x509 = (X509Certificate) cf.generateCertificate(in); 150 mySSLSession session = new mySSLSession(new X509Certificate[] {x509}); 151 152 HostnameVerifier verifier = HttpsURLConnection.getDefaultHostnameVerifier(); 153 String expected = "CN=localhost,OU=Unknown,O=Unknown,L=Unknown,ST=Unknown,C=CH"; 154 assertEquals(new X500Principal(expected), 155 x509.getSubjectX500Principal()); 156 157 assertTrue(verifier.verify("localhost", session)); 158 assertTrue(verifier.verify("localhost.localdomain", session)); 159 assertFalse(verifier.verify("local.host", session)); 160 } 161 testVerifyIpAddress()162 public void testVerifyIpAddress() throws Exception { 163 CertificateFactory cf = CertificateFactory.getInstance("X.509"); 164 InputStream in = new ByteArrayInputStream(X509_MULTIPLE_SUBJECT_ALT); 165 X509Certificate x509 = (X509Certificate) cf.generateCertificate(in); 166 mySSLSession session = new mySSLSession(new X509Certificate[] { x509 }); 167 HostnameVerifier verifier = HttpsURLConnection.getDefaultHostnameVerifier(); 168 169 assertTrue(verifier.verify("127.0.0.1", session)); 170 assertFalse(verifier.verify("127.0.0.2", session)); 171 } 172 testWildcardsCannotMatchIpAddresses()173 public void testWildcardsCannotMatchIpAddresses() throws Exception { 174 // openssl req -x509 -nodes -days 36500 -subj '/CN=*.0.0.1' -newkey rsa:512 -out cert.pem 175 String cert = "-----BEGIN CERTIFICATE-----\n" 176 + "MIIBkjCCATygAwIBAgIJAMdemqOwd/BEMA0GCSqGSIb3DQEBBQUAMBIxEDAOBgNV\n" 177 + "BAMUByouMC4wLjEwIBcNMTAxMjIwMTY0NDI1WhgPMjExMDExMjYxNjQ0MjVaMBIx\n" 178 + "EDAOBgNVBAMUByouMC4wLjEwXDANBgkqhkiG9w0BAQEFAANLADBIAkEAqY8c9Qrt\n" 179 + "YPWCvb7lclI+aDHM6fgbJcHsS9Zg8nUOh5dWrS7AgeA25wyaokFl4plBbbHQe2j+\n" 180 + "cCjsRiJIcQo9HwIDAQABo3MwcTAdBgNVHQ4EFgQUJ436TZPJvwCBKklZZqIvt1Yt\n" 181 + "JjEwQgYDVR0jBDswOYAUJ436TZPJvwCBKklZZqIvt1YtJjGhFqQUMBIxEDAOBgNV\n" 182 + "BAMUByouMC4wLjGCCQDHXpqjsHfwRDAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEB\n" 183 + "BQUAA0EAk9i88xdjWoewqvE+iMC9tD2obMchgFDaHH0ogxxiRaIKeEly3g0uGxIt\n" 184 + "fl2WRY8hb4x+zRrwsFaLEpdEvqcjOQ==\n" 185 + "-----END CERTIFICATE-----"; 186 CertificateFactory cf = CertificateFactory.getInstance("X.509"); 187 InputStream in = new ByteArrayInputStream(cert.getBytes("UTF-8")); 188 X509Certificate x509 = (X509Certificate) cf.generateCertificate(in); 189 mySSLSession session = new mySSLSession(new X509Certificate[] { x509 }); 190 HostnameVerifier verifier = HttpsURLConnection.getDefaultHostnameVerifier(); 191 192 assertFalse(verifier.verify("127.0.0.1", session)); 193 } 194 testWildcardsMustHaveTwoDots()195 public void testWildcardsMustHaveTwoDots() throws Exception { 196 // openssl req -x509 -nodes -days 36500 -subj '/CN=*.com' -newkey rsa:512 -out cert.pem 197 String cert = "-----BEGIN CERTIFICATE-----\n" 198 + "MIIBjDCCATagAwIBAgIJAOVulXCSu6HuMA0GCSqGSIb3DQEBBQUAMBAxDjAMBgNV\n" 199 + "BAMUBSouY29tMCAXDTEwMTIyMDE2NDkzOFoYDzIxMTAxMTI2MTY0OTM4WjAQMQ4w\n" 200 + "DAYDVQQDFAUqLmNvbTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDJd8xqni+h7Iaz\n" 201 + "ypItivs9kPuiJUqVz+SuJ1C05SFc3PmlRCvwSIfhyD67fHcbMdl+A/LrIjhhKZJe\n" 202 + "1joO0+pFAgMBAAGjcTBvMB0GA1UdDgQWBBS4Iuzf5w8JdCp+EtBfdFNudf6+YzBA\n" 203 + "BgNVHSMEOTA3gBS4Iuzf5w8JdCp+EtBfdFNudf6+Y6EUpBIwEDEOMAwGA1UEAxQF\n" 204 + "Ki5jb22CCQDlbpVwkruh7jAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA0EA\n" 205 + "U6LFxmZr31lFyis2/T68PpjAppc0DpNQuA2m/Y7oTHBDi55Fw6HVHCw3lucuWZ5d\n" 206 + "qUYo4ES548JdpQtcLrW2sA==\n" 207 + "-----END CERTIFICATE-----"; 208 CertificateFactory cf = CertificateFactory.getInstance("X.509"); 209 InputStream in = new ByteArrayInputStream(cert.getBytes("UTF-8")); 210 X509Certificate x509 = (X509Certificate) cf.generateCertificate(in); 211 mySSLSession session = new mySSLSession(new X509Certificate[] { x509 }); 212 HostnameVerifier verifier = HttpsURLConnection.getDefaultHostnameVerifier(); 213 214 assertFalse(verifier.verify("google.com", session)); 215 } 216 testSubjectAltName()217 public void testSubjectAltName() throws Exception { 218 /* 219 * $ cat ./cert.cnf 220 * [req] 221 * distinguished_name=distinguished_name 222 * req_extensions=req_extensions 223 * x509_extensions=x509_extensions 224 * [distinguished_name] 225 * [req_extensions] 226 * [x509_extensions] 227 * subjectAltName=DNS:bar.com,DNS:baz.com 228 * 229 * $ openssl req -x509 -nodes -days 36500 -subj '/CN=foo.com' -config ./cert.cnf \ 230 * -newkey rsa:512 -out cert.pem 231 */ 232 String cert = "-----BEGIN CERTIFICATE-----\n" 233 + "MIIBPTCB6KADAgECAgkA7zoHaaqNGHQwDQYJKoZIhvcNAQEFBQAwEjEQMA4GA1UE\n" 234 + "AxMHZm9vLmNvbTAgFw0xMDEyMjAxODM5MzZaGA8yMTEwMTEyNjE4MzkzNlowEjEQ\n" 235 + "MA4GA1UEAxMHZm9vLmNvbTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQC+gmoSxF+8\n" 236 + "hbV+rgRQqHIJd50216OWQJbU3BvdlPbca779NYO4+UZWTFdBM8BdQqs3H4B5Agvp\n" 237 + "y7HeSff1F7XRAgMBAAGjHzAdMBsGA1UdEQQUMBKCB2Jhci5jb22CB2Jhei5jb20w\n" 238 + "DQYJKoZIhvcNAQEFBQADQQBXpZZPOY2Dy1lGG81JTr8L4or9jpKacD7n51eS8iqI\n" 239 + "oTznPNuXHU5bFN0AAGX2ij47f/EahqTpo5RdS95P4sVm\n" 240 + "-----END CERTIFICATE-----"; 241 CertificateFactory cf = CertificateFactory.getInstance("X.509"); 242 InputStream in = new ByteArrayInputStream(cert.getBytes("UTF-8")); 243 X509Certificate x509 = (X509Certificate) cf.generateCertificate(in); 244 mySSLSession session = new mySSLSession(new X509Certificate[] { x509 }); 245 HostnameVerifier verifier = HttpsURLConnection.getDefaultHostnameVerifier(); 246 247 assertTrue(verifier.verify("foo.com", session)); 248 assertTrue(verifier.verify("bar.com", session)); 249 assertTrue(verifier.verify("baz.com", session)); 250 assertFalse(verifier.verify("a.foo.com", session)); 251 assertFalse(verifier.verify("quux.com", session)); 252 } 253 testSubjectAltNameWithWildcard()254 public void testSubjectAltNameWithWildcard() throws Exception { 255 /* 256 * $ cat ./cert.cnf 257 * [req] 258 * distinguished_name=distinguished_name 259 * req_extensions=req_extensions 260 * x509_extensions=x509_extensions 261 * [distinguished_name] 262 * [req_extensions] 263 * [x509_extensions] 264 * subjectAltName=DNS:bar.com,DNS:*.baz.com 265 * 266 * $ openssl req -x509 -nodes -days 36500 -subj '/CN=foo.com' -config ./cert.cnf \ 267 * -newkey rsa:512 -out cert.pem 268 */ 269 String cert = "-----BEGIN CERTIFICATE-----\n" 270 + "MIIBPzCB6qADAgECAgkAnv/7Jv5r7pMwDQYJKoZIhvcNAQEFBQAwEjEQMA4GA1UE\n" 271 + "AxMHZm9vLmNvbTAgFw0xMDEyMjAxODQ2MDFaGA8yMTEwMTEyNjE4NDYwMVowEjEQ\n" 272 + "MA4GA1UEAxMHZm9vLmNvbTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDAz2YXnyog\n" 273 + "YdYLSFr/OEgSumtwqtZKJTB4wqTW/eKbBCEzxnyUMxWZIqUGu353PzwfOuWp2re3\n" 274 + "nvVV+QDYQlh9AgMBAAGjITAfMB0GA1UdEQQWMBSCB2Jhci5jb22CCSouYmF6LmNv\n" 275 + "bTANBgkqhkiG9w0BAQUFAANBAB8yrSl8zqy07i0SNYx2B/FnvQY734pxioaqFWfO\n" 276 + "Bqo1ZZl/9aPHEWIwBrxYNVB0SGu/kkbt/vxqOjzzrkXukmI=\n" 277 + "-----END CERTIFICATE-----"; 278 CertificateFactory cf = CertificateFactory.getInstance("X.509"); 279 InputStream in = new ByteArrayInputStream(cert.getBytes("UTF-8")); 280 X509Certificate x509 = (X509Certificate) cf.generateCertificate(in); 281 mySSLSession session = new mySSLSession(new X509Certificate[] { x509 }); 282 HostnameVerifier verifier = HttpsURLConnection.getDefaultHostnameVerifier(); 283 284 assertTrue(verifier.verify("foo.com", session)); 285 assertTrue(verifier.verify("bar.com", session)); 286 assertTrue(verifier.verify("a.baz.com", session)); 287 assertFalse(verifier.verify("baz.com", session)); 288 assertFalse(verifier.verify("a.foo.com", session)); 289 assertFalse(verifier.verify("a.bar.com", session)); 290 assertFalse(verifier.verify("quux.com", session)); 291 } 292 } 293