001package co.codewizards.cloudstore.rest.client.ssl;
002
003import static co.codewizards.cloudstore.core.util.Util.*;
004
005import java.io.File;
006import java.net.URL;
007import java.security.GeneralSecurityException;
008
009import javax.net.ssl.SSLContext;
010import javax.net.ssl.TrustManager;
011
012import co.codewizards.cloudstore.core.config.ConfigDir;
013
014public final class SSLContextBuilder {
015
016        private URL remoteURL;
017        private File trustStoreFile;
018        private DynamicX509TrustManagerCallback callback;
019
020        private SSLContextBuilder() { }
021
022        public static SSLContextBuilder create() {
023                return new SSLContextBuilder();
024        }
025
026        public DynamicX509TrustManagerCallback getCallback() {
027                return callback;
028        }
029        public void setCallback(DynamicX509TrustManagerCallback callback) {
030                this.callback = callback;
031        }
032        public SSLContextBuilder callback(DynamicX509TrustManagerCallback callback) {
033                setCallback(callback);
034                return this;
035        }
036
037        public URL getRemoteURL() {
038                return remoteURL;
039        }
040        public void setRemoteURL(URL remoteURL) {
041                this.remoteURL = remoteURL;
042        }
043        public SSLContextBuilder remoteURL(URL remoteURL) {
044                setRemoteURL(remoteURL);
045                return this;
046        }
047
048        public File getTrustStoreFile() {
049                return trustStoreFile;
050        }
051        public void setTrustStoreFile(File trustStoreFile) {
052                this.trustStoreFile = trustStoreFile;
053        }
054        public SSLContextBuilder trustStoreFile(File trustStoreFile) {
055                setTrustStoreFile(trustStoreFile);
056                return this;
057        }
058
059        public SSLContext build() throws GeneralSecurityException {
060                final File trustStoreFile = getTrustStoreFile();
061                if (trustStoreFile != null) {
062                        if (getRemoteURL() != null)
063                                throw new IllegalStateException("remoteURL and trustStoreFile are both set! Only one of these should be set!");
064
065                        return getSSLContext(trustStoreFile, getCallback());
066                }
067                else
068                        return getSSLContext(getRemoteURL(), getCallback());
069        }
070
071        private SSLContext getSSLContext(File trustStoreFile, DynamicX509TrustManagerCallback callback) throws GeneralSecurityException {
072                assertNotNull("trustStoreFile", trustStoreFile);
073                assertNotNull("callback", callback);
074                TrustManager[] trustManagers = new TrustManager[] {
075                                new DynamicX509TrustManager(trustStoreFile, callback)
076                };
077
078                // http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#SSLContext
079                // http://en.wikipedia.org/wiki/Secure_Sockets_Layer#Cipher
080                SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
081                sslContext.init(null, trustManagers, null);
082                return sslContext;
083        }
084
085        private SSLContext getSSLContext(URL remoteURL, DynamicX509TrustManagerCallback callback) throws GeneralSecurityException {
086                assertNotNull("remoteURL", remoteURL);
087                assertNotNull("callback", callback);
088
089                String trustStoreFileName = remoteURL.getHost();
090                if (remoteURL.getPort() >= 0)
091                        trustStoreFileName += "_" + remoteURL.getPort();
092
093                trustStoreFileName += ".truststore";
094
095                File sslClient = new File(ConfigDir.getInstance().getFile(), "ssl.client");
096
097                if (!sslClient.isDirectory())
098                        sslClient.mkdirs();
099
100                if (!sslClient.isDirectory())
101                        throw new IllegalStateException("Could not create directory (permissions?): " + sslClient);
102
103                return getSSLContext(new File(sslClient, trustStoreFileName), callback);
104        }
105}