1d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 2d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * $RCSfile$ 3d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * $Revision$ 4d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * $Date$ 5d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 6d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Copyright 2003-2005 Jive Software. 7d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 8d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); 9d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * you may not use this file except in compliance with the License. 10d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * You may obtain a copy of the License at 11d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 12d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * http://www.apache.org/licenses/LICENSE-2.0 13d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 14d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Unless required by applicable law or agreed to in writing, software 15d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * distributed under the License is distributed on an "AS IS" BASIS, 16d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * See the License for the specific language governing permissions and 18d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * limitations under the License. 19d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 20d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 21d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpackage org.jivesoftware.smack; 22d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 23d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport javax.net.ssl.X509TrustManager; 24d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 25d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.FileInputStream; 26d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.InputStream; 27d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.IOException; 28d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.security.*; 29d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.security.cert.CertificateException; 30d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.security.cert.CertificateParsingException; 31d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.security.cert.X509Certificate; 32d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.*; 33d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.regex.Matcher; 34d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.regex.Pattern; 35d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 36d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 37d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Trust manager that checks all certificates presented by the server. This class 38d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * is used during TLS negotiation. It is possible to disable/enable some or all checkings 39d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * by configuring the {@link ConnectionConfiguration}. The truststore file that contains 40d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * knows and trusted CA root certificates can also be configure in {@link ConnectionConfiguration}. 41d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 42d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @author Gaston Dombiak 43d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 44d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenclass ServerTrustManager implements X509TrustManager { 45d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 46d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private static Pattern cnPattern = Pattern.compile("(?i)(cn=)([^,]*)"); 47d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 48d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private ConnectionConfiguration configuration; 49d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 50d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 51d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Holds the domain of the remote server we are trying to connect 52d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 53d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private String server; 54d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private KeyStore trustStore; 55d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 56d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private static Map<KeyStoreOptions, KeyStore> stores = new HashMap<KeyStoreOptions, KeyStore>(); 57d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 58d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public ServerTrustManager(String server, ConnectionConfiguration configuration) { 59d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.configuration = configuration; 60d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.server = server; 61d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 62d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen InputStream in = null; 63d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen synchronized (stores) { 64d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen KeyStoreOptions options = new KeyStoreOptions(configuration.getTruststoreType(), 65d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen configuration.getTruststorePath(), configuration.getTruststorePassword()); 66d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (stores.containsKey(options)) { 67d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen trustStore = stores.get(options); 68d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else { 69d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 70d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen trustStore = KeyStore.getInstance(options.getType()); 71d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen in = new FileInputStream(options.getPath()); 72d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen trustStore.load(in, options.getPassword().toCharArray()); 73d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } catch (Exception e) { 74d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen trustStore = null; 75d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen e.printStackTrace(); 76d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } finally { 77d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (in != null) { 78d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 79d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen in.close(); 80d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } catch (IOException ioe) { 81d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Ignore. 82d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 83d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 84d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 85d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen stores.put(options, trustStore); 86d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 87d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (trustStore == null) 88d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Disable root CA checking 89d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen configuration.setVerifyRootCAEnabled(false); 90d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 91d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 92d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 93d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public X509Certificate[] getAcceptedIssuers() { 94d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return new X509Certificate[0]; 95d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 96d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 97d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void checkClientTrusted(X509Certificate[] arg0, String arg1) 98d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throws CertificateException { 99d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 100d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 101d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void checkServerTrusted(X509Certificate[] x509Certificates, String arg1) 102d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throws CertificateException { 103d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 104d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int nSize = x509Certificates.length; 105d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 106d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List<String> peerIdentities = getPeerIdentity(x509Certificates[0]); 107d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 108d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (configuration.isVerifyChainEnabled()) { 109d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Working down the chain, for every certificate in the chain, 110d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // verify that the subject of the certificate is the issuer of the 111d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // next certificate in the chain. 112d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Principal principalLast = null; 113d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int i = nSize -1; i >= 0 ; i--) { 114d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen X509Certificate x509certificate = x509Certificates[i]; 115d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Principal principalIssuer = x509certificate.getIssuerDN(); 116d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Principal principalSubject = x509certificate.getSubjectDN(); 117d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (principalLast != null) { 118d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (principalIssuer.equals(principalLast)) { 119d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 120d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PublicKey publickey = 121d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen x509Certificates[i + 1].getPublicKey(); 122d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen x509Certificates[i].verify(publickey); 123d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 124d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (GeneralSecurityException generalsecurityexception) { 125d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new CertificateException( 126d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen "signature verification failed of " + peerIdentities); 127d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 128d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 129d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else { 130d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new CertificateException( 131d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen "subject/issuer verification failed of " + peerIdentities); 132d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 133d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 134d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen principalLast = principalSubject; 135d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 136d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 137d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 138d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (configuration.isVerifyRootCAEnabled()) { 139d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Verify that the the last certificate in the chain was issued 140d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // by a third-party that the client trusts. 141d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen boolean trusted = false; 142d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 143d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen trusted = trustStore.getCertificateAlias(x509Certificates[nSize - 1]) != null; 144d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!trusted && nSize == 1 && configuration.isSelfSignedCertificateEnabled()) 145d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen { 146d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen System.out.println("Accepting self-signed certificate of remote server: " + 147d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen peerIdentities); 148d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen trusted = true; 149d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 150d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 151d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (KeyStoreException e) { 152d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen e.printStackTrace(); 153d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 154d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!trusted) { 155d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new CertificateException("root certificate not trusted of " + peerIdentities); 156d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 157d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 158d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 159d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (configuration.isNotMatchingDomainCheckEnabled()) { 160d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Verify that the first certificate in the chain corresponds to 161d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // the server we desire to authenticate. 162d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Check if the certificate uses a wildcard indicating that subdomains are valid 163d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (peerIdentities.size() == 1 && peerIdentities.get(0).startsWith("*.")) { 164d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Remove the wildcard 165d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String peerIdentity = peerIdentities.get(0).replace("*.", ""); 166d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Check if the requested subdomain matches the certified domain 167d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!server.endsWith(peerIdentity)) { 168d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new CertificateException("target verification failed of " + peerIdentities); 169d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 170d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 171d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else if (!peerIdentities.contains(server)) { 172d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new CertificateException("target verification failed of " + peerIdentities); 173d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 174d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 175d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 176d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (configuration.isExpiredCertificatesCheckEnabled()) { 177d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // For every certificate in the chain, verify that the certificate 178d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // is valid at the current time. 179d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Date date = new Date(); 180d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int i = 0; i < nSize; i++) { 181d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 182d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen x509Certificates[i].checkValidity(date); 183d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 184d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (GeneralSecurityException generalsecurityexception) { 185d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new CertificateException("invalid date of " + server); 186d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 187d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 188d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 189d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 190d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 191d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 192d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 193d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the identity of the remote server as defined in the specified certificate. The 194d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * identity is defined in the subjectDN of the certificate and it can also be defined in 195d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * the subjectAltName extension of type "xmpp". When the extension is being used then the 196d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * identity defined in the extension in going to be returned. Otherwise, the value stored in 197d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * the subjectDN is returned. 198d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 199d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param x509Certificate the certificate the holds the identity of the remote server. 200d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the identity of the remote server as defined in the specified certificate. 201d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 202d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public static List<String> getPeerIdentity(X509Certificate x509Certificate) { 203d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Look the identity in the subjectAltName extension if available 204d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List<String> names = getSubjectAlternativeNames(x509Certificate); 205d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (names.isEmpty()) { 206d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String name = x509Certificate.getSubjectDN().getName(); 207d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Matcher matcher = cnPattern.matcher(name); 208d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (matcher.find()) { 209d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen name = matcher.group(2); 210d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 211d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Create an array with the unique identity 212d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen names = new ArrayList<String>(); 213d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen names.add(name); 214d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 215d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return names; 216d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 217d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 218d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 219d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the JID representation of an XMPP entity contained as a SubjectAltName extension 220d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * in the certificate. If none was found then return <tt>null</tt>. 221d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 222d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param certificate the certificate presented by the remote entity. 223d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the JID representation of an XMPP entity contained as a SubjectAltName extension 224d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * in the certificate. If none was found then return <tt>null</tt>. 225d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 226d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private static List<String> getSubjectAlternativeNames(X509Certificate certificate) { 227d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List<String> identities = new ArrayList<String>(); 228d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 229d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Collection<List<?>> altNames = certificate.getSubjectAlternativeNames(); 230d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Check that the certificate includes the SubjectAltName extension 231d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (altNames == null) { 232d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return Collections.emptyList(); 233d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 234d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Use the type OtherName to search for the certified server name 235d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /*for (List item : altNames) { 236d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Integer type = (Integer) item.get(0); 237d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (type == 0) { 238d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Type OtherName found so return the associated value 239d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 240d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Value is encoded using ASN.1 so decode it to get the server's identity 241d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ASN1InputStream decoder = new ASN1InputStream((byte[]) item.toArray()[1]); 242d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen DEREncodable encoded = decoder.readObject(); 243d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen encoded = ((DERSequence) encoded).getObjectAt(1); 244d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen encoded = ((DERTaggedObject) encoded).getObject(); 245d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen encoded = ((DERTaggedObject) encoded).getObject(); 246d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String identity = ((DERUTF8String) encoded).getString(); 247d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Add the decoded server name to the list of identities 248d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen identities.add(identity); 249d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 250d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (UnsupportedEncodingException e) { 251d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Ignore 252d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 253d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (IOException e) { 254d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Ignore 255d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 256d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (Exception e) { 257d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen e.printStackTrace(); 258d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 259d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 260d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Other types are not good for XMPP so ignore them 261d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen System.out.println("SubjectAltName of invalid type found: " + certificate); 262d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen }*/ 263d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 264d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (CertificateParsingException e) { 265d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen e.printStackTrace(); 266d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 267d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return identities; 268d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 269d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 270d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private static class KeyStoreOptions { 271d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private final String type; 272d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private final String path; 273d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private final String password; 274d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 275d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public KeyStoreOptions(String type, String path, String password) { 276d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen super(); 277d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.type = type; 278d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.path = path; 279d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.password = password; 280d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 281d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 282d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String getType() { 283d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return type; 284d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 285d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 286d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String getPath() { 287d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return path; 288d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 289d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 290d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String getPassword() { 291d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return password; 292d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 293d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 294d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen @Override 295d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public int hashCode() { 296d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen final int prime = 31; 297d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int result = 1; 298d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen result = prime * result + ((password == null) ? 0 : password.hashCode()); 299d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen result = prime * result + ((path == null) ? 0 : path.hashCode()); 300d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen result = prime * result + ((type == null) ? 0 : type.hashCode()); 301d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return result; 302d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 303d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 304d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen @Override 305d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public boolean equals(Object obj) { 306d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (this == obj) 307d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return true; 308d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (obj == null) 309d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 310d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (getClass() != obj.getClass()) 311d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 312d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen KeyStoreOptions other = (KeyStoreOptions) obj; 313d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (password == null) { 314d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (other.password != null) 315d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 316d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else if (!password.equals(other.password)) 317d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 318d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (path == null) { 319d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (other.path != null) 320d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 321d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else if (!path.equals(other.path)) 322d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 323d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (type == null) { 324d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (other.type != null) 325d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 326d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else if (!type.equals(other.type)) 327d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 328d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return true; 329d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 330d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 331d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 332