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}