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}