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