1 /* 2 * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.net.ssl.internal.www.protocol.https; 27 28 import java.net.URL; 29 import java.net.Proxy; 30 import java.io.IOException; 31 import java.util.Collection; 32 import java.util.List; 33 import java.util.Iterator; 34 35 import java.security.Principal; 36 import java.security.cert.*; 37 38 import javax.security.auth.x500.X500Principal; 39 40 import sun.security.util.HostnameChecker; 41 import sun.security.util.DerValue; 42 import sun.security.x509.X500Name; 43 44 import sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection; 45 46 /** 47 * This class was introduced to provide an additional level of 48 * abstraction between javax.net.ssl.HttpURLConnection and 49 * com.sun.net.ssl.HttpURLConnection objects. <p> 50 * 51 * javax.net.ssl.HttpURLConnection is used in the new sun.net version 52 * of protocol implementation (this one) 53 * com.sun.net.ssl.HttpURLConnection is used in the com.sun version. 54 * 55 */ 56 @Deprecated(since="9") 57 @SuppressWarnings("deprecation") // HttpsURLConnection is deprecated 58 public class DelegateHttpsURLConnection extends AbstractDelegateHttpsURLConnection { 59 60 // we need a reference to the HttpsURLConnection to get 61 // the properties set there 62 // we also need it to be public so that it can be referenced 63 // from sun.net.www.protocol.http.HttpURLConnection 64 // this is for ResponseCache.put(URI, URLConnection) 65 // second parameter needs to be cast to javax.net.ssl.HttpsURLConnection 66 // instead of AbstractDelegateHttpsURLConnection 67 68 public com.sun.net.ssl.HttpsURLConnection httpsURLConnection; 69 DelegateHttpsURLConnection(URL url, sun.net.www.protocol.http.Handler handler, com.sun.net.ssl.HttpsURLConnection httpsURLConnection)70 DelegateHttpsURLConnection(URL url, 71 sun.net.www.protocol.http.Handler handler, 72 com.sun.net.ssl.HttpsURLConnection httpsURLConnection) 73 throws IOException { 74 this(url, null, handler, httpsURLConnection); 75 } 76 DelegateHttpsURLConnection(URL url, Proxy p, sun.net.www.protocol.http.Handler handler, com.sun.net.ssl.HttpsURLConnection httpsURLConnection)77 DelegateHttpsURLConnection(URL url, Proxy p, 78 sun.net.www.protocol.http.Handler handler, 79 com.sun.net.ssl.HttpsURLConnection httpsURLConnection) 80 throws IOException { 81 super(url, p, handler); 82 this.httpsURLConnection = httpsURLConnection; 83 } 84 getSSLSocketFactory()85 protected javax.net.ssl.SSLSocketFactory getSSLSocketFactory() { 86 return httpsURLConnection.getSSLSocketFactory(); 87 } 88 getHostnameVerifier()89 protected javax.net.ssl.HostnameVerifier getHostnameVerifier() { 90 // note: getHostnameVerifier() never returns null 91 return new VerifierWrapper(httpsURLConnection.getHostnameVerifier()); 92 } 93 94 /* 95 * Called by layered delegator's finalize() method to handle closing 96 * the underlying object. 97 */ dispose()98 protected void dispose() throws Throwable { 99 super.finalize(); 100 } 101 } 102 103 class VerifierWrapper implements javax.net.ssl.HostnameVerifier { 104 @SuppressWarnings("deprecation") 105 private com.sun.net.ssl.HostnameVerifier verifier; 106 107 @SuppressWarnings("deprecation") VerifierWrapper(com.sun.net.ssl.HostnameVerifier verifier)108 VerifierWrapper(com.sun.net.ssl.HostnameVerifier verifier) { 109 this.verifier = verifier; 110 } 111 112 /* 113 * In com.sun.net.ssl.HostnameVerifier the method is defined 114 * as verify(String urlHostname, String certHostname). 115 * This means we need to extract the hostname from the X.509 certificate 116 * in this wrapper. 117 */ verify(String hostname, javax.net.ssl.SSLSession session)118 public boolean verify(String hostname, javax.net.ssl.SSLSession session) { 119 try { 120 Certificate[] serverChain = session.getPeerCertificates(); 121 if ((serverChain == null) || (serverChain.length == 0)) { 122 return false; 123 } 124 if (serverChain[0] instanceof X509Certificate == false) { 125 return false; 126 } 127 X509Certificate serverCert = (X509Certificate)serverChain[0]; 128 String serverName = getServername(serverCert); 129 if (serverName == null) { 130 return false; 131 } 132 return verifier.verify(hostname, serverName); 133 } catch (javax.net.ssl.SSLPeerUnverifiedException e) { 134 return false; 135 } 136 } 137 138 /* 139 * Extract the name of the SSL server from the certificate. 140 * 141 * Note this code is essentially a subset of the hostname extraction 142 * code in HostnameChecker. 143 */ getServername(X509Certificate peerCert)144 private static String getServername(X509Certificate peerCert) { 145 try { 146 // compare to subjectAltNames if dnsName is present 147 Collection<List<?>> subjAltNames = peerCert.getSubjectAlternativeNames(); 148 if (subjAltNames != null) { 149 for (Iterator<List<?>> itr = subjAltNames.iterator(); itr.hasNext(); ) { 150 List<?> next = itr.next(); 151 if (((Integer)next.get(0)).intValue() == 2) { 152 // compare dNSName with host in url 153 String dnsName = ((String)next.get(1)); 154 return dnsName; 155 } 156 } 157 } 158 159 // else check against common name in the subject field 160 X500Name subject = HostnameChecker.getSubjectX500Name(peerCert); 161 162 DerValue derValue = subject.findMostSpecificAttribute 163 (X500Name.commonName_oid); 164 if (derValue != null) { 165 try { 166 String name = derValue.getAsString(); 167 return name; 168 } catch (IOException e) { 169 // ignore 170 } 171 } 172 } catch (java.security.cert.CertificateException e) { 173 // ignore 174 } 175 return null; 176 } 177 178 } 179