/* * This file is part of the Haven & Hearth game client. * Copyright (C) 2009 Fredrik Tolf <fredrik@dolda2000.com>, and * Björn Johannessen <johannessen.bjorn@gmail.com> * * Redistribution and/or modification of this file is subject to the * terms of the GNU Lesser General Public License, version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * Other parts of this source tree adhere to other copying * rights. Please see the file `COPYING' in the root directory of the * source tree for details. * * A copy the GNU Lesser General Public License is distributed along * with the source tree of which this file is a part in the file * `doc/LPGL-3'. If it is missing for any reason, please see the Free * Software Foundation's website at <http://www.fsf.org/>, or write * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307 USA */ package haven; import java.io.IOException; import java.io.InputStream; import java.net.InetSocketAddress; import java.net.MalformedURLException; import java.net.Socket; import java.net.URL; import java.security.KeyManagementException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.UnrecoverableKeyException; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.KeyManager; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManagerFactory; public class SslHelper { private KeyStore creds, trusted; private SSLContext ctx = null; private SSLSocketFactory sfac = null; private int tserial = 0; private char[] pw; private HostnameVerifier ver = null; public SslHelper() { creds = null; try { trusted = KeyStore.getInstance(KeyStore.getDefaultType()); trusted.load(null, null); } catch (Exception e) { throw (new Error(e)); } } private synchronized SSLContext ctx() { if (ctx == null) { TrustManagerFactory tmf; KeyManagerFactory kmf; try { ctx = SSLContext.getInstance("TLS"); tmf = TrustManagerFactory.getInstance("PKIX"); kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); KeyManager[] kms = null; tmf.init(trusted); if (creds != null) { kmf.init(creds, pw); kms = kmf.getKeyManagers(); } ctx.init(kms, tmf.getTrustManagers(), new SecureRandom()); } catch (NoSuchAlgorithmException e) { throw (new Error(e)); } catch (KeyStoreException e) { throw (new RuntimeException(e)); } catch (UnrecoverableKeyException e) { /* * The key should be recoverable at this stage, since it was * loaded successfully. */ throw (new RuntimeException(e)); } catch (KeyManagementException e) { throw (new RuntimeException(e)); } } return (ctx); } private synchronized SSLSocketFactory sfac() { if (sfac == null) sfac = ctx().getSocketFactory(); return (sfac); } private void clear() { ctx = null; sfac = null; } public synchronized void trust(Certificate cert) { clear(); try { trusted.setCertificateEntry("cert-" + tserial++, cert); } catch (KeyStoreException e) { /* * The keystore should have been initialized and should not have the * generated alias, so this should not happen. */ throw (new RuntimeException(e)); } } public static Certificate loadX509(InputStream in) throws IOException, CertificateException { CertificateFactory fac = CertificateFactory.getInstance("X.509"); return (fac.generateCertificate(in)); } public synchronized void loadCredsPkcs12(InputStream in, char[] pw) throws IOException, CertificateException { clear(); try { creds = KeyStore.getInstance("PKCS12"); creds.load(in, pw); this.pw = pw; } catch (KeyStoreException e) { throw (new Error(e)); } catch (NoSuchAlgorithmException e) { throw (new Error(e)); } } public HttpsURLConnection connect(URL url) throws IOException { if (!url.getProtocol().equals("https")) throw (new MalformedURLException("Can only be used to connect to HTTPS servers")); HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); conn.setSSLSocketFactory(sfac()); if (ver != null) conn.setHostnameVerifier(ver); return (conn); } public HttpsURLConnection connect(String url) throws IOException { return (connect(new URL(url))); } public void ignoreName() { ver = new HostnameVerifier() { public boolean verify(String hostname, SSLSession sess) { return (true); } }; } public SSLSocket connect(Socket sk, String host, int port, boolean autoclose) throws IOException { return ((SSLSocket) sfac().createSocket(sk, host, port, autoclose)); } public SSLSocket connect(String host, int port) throws IOException { Socket sk = new HackSocket(); sk.connect(new InetSocketAddress(host, port)); return (connect(sk, host, port, true)); } public boolean hasCreds() { return (creds != null); } }