Author: brandonwilliams Date: Tue Nov 29 16:41:23 2011 New Revision: 1207958
URL: http://svn.apache.org/viewvc?rev=1207958&view=rev Log: Filter out unavailable cipher suites when using encryption. Patch by Vijay, reviewed by brandonwilliams for CASSANDRA-3278 Modified: cassandra/branches/cassandra-1.0/CHANGES.txt cassandra/branches/cassandra-1.0/conf/cassandra.yaml cassandra/branches/cassandra-1.0/src/java/org/apache/cassandra/config/EncryptionOptions.java cassandra/branches/cassandra-1.0/src/java/org/apache/cassandra/security/SSLFactory.java Modified: cassandra/branches/cassandra-1.0/CHANGES.txt URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-1.0/CHANGES.txt?rev=1207958&r1=1207957&r2=1207958&view=diff ============================================================================== --- cassandra/branches/cassandra-1.0/CHANGES.txt (original) +++ cassandra/branches/cassandra-1.0/CHANGES.txt Tue Nov 29 16:41:23 2011 @@ -1,6 +1,6 @@ 1.0.5 * add command to stop compactions (CASSANDRA-1740) - + * filter out unavailable cipher suites when using encryption (CASSANDRA-3178) 1.0.4 * fix self-hinting of timed out read repair updates and make hinted handoff Modified: cassandra/branches/cassandra-1.0/conf/cassandra.yaml URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-1.0/conf/cassandra.yaml?rev=1207958&r1=1207957&r2=1207958&view=diff ============================================================================== --- cassandra/branches/cassandra-1.0/conf/cassandra.yaml (original) +++ cassandra/branches/cassandra-1.0/conf/cassandra.yaml Tue Nov 29 16:41:23 2011 @@ -415,9 +415,15 @@ index_interval: 128 # The passwords used in these options must match the passwords used when generating # the keystore and truststore. For instructions on generating these files, see: # http://download.oracle.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html#CreateKeystore +# encryption_options: internode_encryption: none keystore: conf/.keystore keystore_password: cassandra truststore: conf/.truststore truststore_password: cassandra + # More advanced defaults below: + # protocol: TLS + # algorithm: SunX509 + # store_type: JKS + # cipher_suites: [TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA] Modified: cassandra/branches/cassandra-1.0/src/java/org/apache/cassandra/config/EncryptionOptions.java URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-1.0/src/java/org/apache/cassandra/config/EncryptionOptions.java?rev=1207958&r1=1207957&r2=1207958&view=diff ============================================================================== --- cassandra/branches/cassandra-1.0/src/java/org/apache/cassandra/config/EncryptionOptions.java (original) +++ cassandra/branches/cassandra-1.0/src/java/org/apache/cassandra/config/EncryptionOptions.java Tue Nov 29 16:41:23 2011 @@ -28,7 +28,11 @@ public class EncryptionOptions public String keystore_password = "cassandra"; public String truststore = "conf/.truststore"; public String truststore_password = "cassandra"; - public String[] cipherSuites = {"TLS_RSA_WITH_AES_128_CBC_SHA", "TLS_RSA_WITH_AES_256_CBC_SHA"}; + public String[] cipher_suites = {"TLS_RSA_WITH_AES_128_CBC_SHA", "TLS_RSA_WITH_AES_256_CBC_SHA"}; + public String protocol = "TLS"; + public String algorithm = "SunX509"; + public String store_type = "JKS"; + public static enum InternodeEncryption { Modified: cassandra/branches/cassandra-1.0/src/java/org/apache/cassandra/security/SSLFactory.java URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-1.0/src/java/org/apache/cassandra/security/SSLFactory.java?rev=1207958&r1=1207957&r2=1207958&view=diff ============================================================================== --- cassandra/branches/cassandra-1.0/src/java/org/apache/cassandra/security/SSLFactory.java (original) +++ cassandra/branches/cassandra-1.0/src/java/org/apache/cassandra/security/SSLFactory.java Tue Nov 29 16:41:23 2011 @@ -26,6 +26,7 @@ import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.security.KeyStore; +import java.util.Set; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; @@ -35,6 +36,11 @@ import javax.net.ssl.TrustManagerFactory import org.apache.cassandra.config.EncryptionOptions; import org.apache.cassandra.io.util.FileUtils; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.Sets; /** * A Factory for providing and setting up Client and Server SSL wrapped @@ -42,16 +48,15 @@ import org.apache.cassandra.io.util.File */ public final class SSLFactory { - private static final String PROTOCOL = "TLS"; - private static final String ALGORITHM = "SunX509"; - private static final String STORE_TYPE = "JKS"; + private static final Logger logger_ = LoggerFactory.getLogger(SSLFactory.class); public static SSLServerSocket getServerSocket(EncryptionOptions options, InetAddress address, int port) throws IOException { SSLContext ctx = createSSLContext(options); SSLServerSocket serverSocket = (SSLServerSocket)ctx.getServerSocketFactory().createServerSocket(); serverSocket.setReuseAddress(true); - serverSocket.setEnabledCipherSuites(options.cipherSuites); + String[] suits = filterCipherSuites(serverSocket.getSupportedCipherSuites(), options.cipher_suites); + serverSocket.setEnabledCipherSuites(suits); serverSocket.bind(new InetSocketAddress(address, port), 100); return serverSocket; } @@ -61,7 +66,8 @@ public final class SSLFactory { SSLContext ctx = createSSLContext(options); SSLSocket socket = (SSLSocket) ctx.getSocketFactory().createSocket(address, port, localAddress, localPort); - socket.setEnabledCipherSuites(options.cipherSuites); + String[] suits = filterCipherSuites(socket.getSupportedCipherSuites(), options.cipher_suites); + socket.setEnabledCipherSuites(suits); return socket; } @@ -70,7 +76,8 @@ public final class SSLFactory { SSLContext ctx = createSSLContext(options); SSLSocket socket = (SSLSocket) ctx.getSocketFactory().createSocket(); - socket.setEnabledCipherSuites(options.cipherSuites); + String[] suits = filterCipherSuites(socket.getSupportedCipherSuites(), options.cipher_suites); + socket.setEnabledCipherSuites(suits); return socket; } @@ -81,17 +88,17 @@ public final class SSLFactory SSLContext ctx; try { - ctx = SSLContext.getInstance(PROTOCOL); + ctx = SSLContext.getInstance(options.protocol); TrustManagerFactory tmf; KeyManagerFactory kmf; - tmf = TrustManagerFactory.getInstance(ALGORITHM); - KeyStore ts = KeyStore.getInstance(STORE_TYPE); + tmf = TrustManagerFactory.getInstance(options.algorithm); + KeyStore ts = KeyStore.getInstance(options.store_type); ts.load(tsf, options.truststore_password.toCharArray()); tmf.init(ts); - kmf = KeyManagerFactory.getInstance(ALGORITHM); - KeyStore ks = KeyStore.getInstance(STORE_TYPE); + kmf = KeyManagerFactory.getInstance(options.algorithm); + KeyStore ks = KeyStore.getInstance(options.store_type); ks.load(ksf, options.keystore_password.toCharArray()); kmf.init(ks, options.keystore_password.toCharArray()); @@ -109,4 +116,13 @@ public final class SSLFactory } return ctx; } + + private static String[] filterCipherSuites(String[] supported, String[] desired) + { + Set<String> des = Sets.newHashSet(desired); + Set<String> return_ = Sets.intersection(Sets.newHashSet(supported), des); + if (des.size() > return_.size()) + logger_.warn("Filtering out {} as it isnt supported by the socket", StringUtils.join(Sets.difference(des, return_), ",")); + return return_.toArray(new String[return_.size()]); + } }