I am playing with SSL in Java for the first time, trying to create an echo server. I have managed to get it working when only the server needs to authenticate, with (after setting the properties to point to the appropriate KeyStore and TrustStore):
Server side:
SSLServerSocketFactory serverSocketFactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
SSLServerSocket serverSocket = (SSLServerSocket) serverSocketFactory.createServerSocket(bancoPort);
String [] supported = serverSocketFactory.getSupportedCipherSuites();
serverSocket.setEnabledCipherSuites(supported);
serverSocket.setEnabledProtocols(new String[]{"TLSv1"});
SSLSocket s = (SSLSocket) serverSocket.accept();
Client side:
SSLSocketFactory socketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket bancoSocket = (SSLSocket) socketFactory.createSocket(bancoIP, bancoPort);
String[] suites = bancoSocket.getSupportedCipherSuites();
bancoSocket.setEnabledCipherSuites(suites);
Thanks to the debug mode I know the cipher suite used for authentication is TLS_ECDH_anon_WITH_AES_128_CBC_SHA:
main, READ: TLSv1 Handshake, length = 215
*** ClientHello, TLSv1
RandomCookie: GMT: 1399451465 bytes = { 177, 86, 70, 228, 7, 0, 109, 56, 245, 8, 243, 18, 122, 186, 159, 138, 76, 99, 65, 224, 21, 100, 1, 90, 20, 109, 241, 216 }
Session ID: {}
Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_RC4_128_SHA, TLS_ECDH_ECDSA_WITH_RC4_128_SHA, TLS_ECDH_RSA_WITH_RC4_128_SHA, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_RC4_128_MD5, TLS_EMPTY_RENEGOTIATION_INFO_SCSV, TLS_ECDH_anon_WITH_AES_128_CBC_SHA, TLS_DH_anon_WITH_AES_128_CBC_SHA, TLS_ECDH_anon_WITH_RC4_128_SHA, SSL_DH_anon_WITH_RC4_128_MD5, TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA, SSL_DH_anon_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_ECDSA_WITH_NULL_SHA, TLS_ECDHE_RSA_WITH_NULL_SHA, SSL_RSA_WITH_NULL_SHA, TLS_ECDH_ECDSA_WITH_NULL_SHA, TLS_ECDH_RSA_WITH_NULL_SHA, TLS_ECDH_anon_WITH_NULL_SHA, SSL_RSA_WITH_NULL_MD5, SSL_RSA_WITH_DES_CBC_SHA, SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_DH_anon_WITH_DES_CBC_SHA, SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_DH_anon_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA, TLS_KRB5_WITH_RC4_128_SHA, TLS_KRB5_WITH_RC4_128_MD5, TLS_KRB5_WITH_3DES_EDE_CBC_SHA, TLS_KRB5_WITH_3DES_EDE_CBC_MD5, TLS_KRB5_WITH_DES_CBC_SHA, TLS_KRB5_WITH_DES_CBC_MD5, TLS_KRB5_EXPORT_WITH_RC4_40_SHA, TLS_KRB5_EXPORT_WITH_RC4_40_MD5, TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA, TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5]
Compression Methods: { 0 }
Extension elliptic_curves, curve names: {secp256r1, sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1, sect193r1, sect193r2, secp224k1, sect239k1, secp256k1}
Extension ec_point_formats, formats: [uncompressed]
***
%% Initialized: [Session-1, SSL_NULL_WITH_NULL_NULL]
%% Negotiating: [Session-1, TLS_ECDH_anon_WITH_AES_128_CBC_SHA]
*** ServerHello, TLSv1
RandomCookie: GMT: 1399451466 bytes = { 252, 63, 206, 222, 115, 40, 143, 4, 55, 11, 88, 196, 5, 10, 114, 159, 76, 144, 181, 27, 73, 248, 196, 71, 169, 136, 228, 82 }
Session ID: {83, 106, 239, 74, 65, 85, 23, 110, 97, 151, 196, 61, 224, 79, 140, 15, 11, 132, 208, 66, 112, 216, 122, 85, 27, 159, 194, 255, 104, 171, 81, 220}
Cipher Suite: TLS_ECDH_anon_WITH_AES_128_CBC_SHA
Compression Method: 0
Extension renegotiation_info, renegotiated_connection: <empty>
***
Cipher suite: TLS_ECDH_anon_WITH_AES_128_CBC_SHA
If I add to the server code the line
serverSocket.setNeedClientAuth(true);
everything breaks down. The suite then used is TLS_KRB5_WITH_RC4_128_MD5, but the client is not apparently prepared to use Kerberos, since this is the error that pops up in the client when the first message to be echoed is sent:
may 08, 2014 3:31:30 AM echoclient.EchoClientSSL main
Grave: null
java.io.IOException: Invalid service principal name: host/desk-linux
at sun.security.ssl.krb5.KerberosClientKeyExchangeImpl.getServiceTicket(KerberosClientKeyExchangeImpl.java:307)
at sun.security.ssl.krb5.KerberosClientKeyExchangeImpl.init(KerberosClientKeyExchangeImpl.java:112)
at sun.security.ssl.KerberosClientKeyExchange.init(KerberosClientKeyExchange.java:122)
at sun.security.ssl.KerberosClientKeyExchange.<init>(KerberosClientKeyExchange.java:80)
at sun.security.ssl.ClientHandshaker.serverHelloDone(ClientHandshaker.java:873)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:285)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:868)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:804)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1016)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312)
at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:702)
at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:122)
at java.io.DataOutputStream.write(DataOutputStream.java:107)
at java.io.DataOutputStream.writeUTF(DataOutputStream.java:401)
at java.io.DataOutputStream.writeUTF(DataOutputStream.java:323)
at echoclient.EchoClientSSL.main(EchoClientSSL.java:45)
Caused by: KrbException: Cannot locate default realm
at sun.security.krb5.PrincipalName.<init>(PrincipalName.java:367)
at sun.security.ssl.krb5.KerberosClientKeyExchangeImpl.getServiceTicket(KerberosClientKeyExchangeImpl.java:302)
... 15 more
Caused by: KrbException: Cannot locate default realm
at sun.security.krb5.Config.getDefaultRealm(Config.java:1181)
at sun.security.krb5.PrincipalName.<init>(PrincipalName.java:365)
... 16 more
Caused by: KrbException: Generic error (description in e-text) (60) - Unable to locate Kerberos realm
at sun.security.krb5.Config.getRealmFromDNS(Config.java:1277)
at sun.security.krb5.Config.getDefaultRealm(Config.java:1162)
... 17 more
I have tried to setEnabledCipherSuites in the client to just the one I know that works (TLS_ECDH_anon_WITH_AES_128_CBC_SHA) instead of the whole allowed cipher suite, but if I do that I get the exception at the server "javax.net.ssl.SSLHandshakeException: no cipher suites in common". Log:
main, READ: TLSv1 Handshake, length = 114
*** ClientHello, TLSv1
RandomCookie: GMT: 1399451199 bytes = { 43, 248, 163, 155, 250, 241, 124, 194, 33, 46, 197, 27, 122, 1, 148, 254, 255, 71, 219, 220, 213, 91, 180, 178, 126, 242, 166, 82 }
Session ID: {}
Cipher Suites: [TLS_ECDH_anon_WITH_AES_128_CBC_SHA]
Compression Methods: { 0 }
Extension elliptic_curves, curve names: {secp256r1, sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1, sect193r1, sect193r2, secp224k1, sect239k1, secp256k1}
Extension ec_point_formats, formats: [uncompressed]
Extension renegotiation_info, renegotiated_connection: <empty>
***
%% Initialized: [Session-1, SSL_NULL_WITH_NULL_NULL]
%% Invalidated: [Session-1, SSL_NULL_WITH_NULL_NULL]
main, SEND TLSv1 ALERT: fatal, description = handshake_failure
main, WRITE: TLSv1 Alert, length = 2
main, called closeSocket()
main, handling exception: javax.net.ssl.SSLHandshakeException: no cipher suites in common
may 08, 2014 3:38:56 AM echoserver.EchoServerSSL main
Grave: null
javax.net.ssl.SSLHandshakeException: no cipher suites in common
Both server and client are running on the same machine, so I don't get how a cipher suite that works to authenticate the server fails when trying to authenticate the client.
As @EJP said, those lines were counter-productive and needed to be removed. The problem was not in the code but on how the certificates in the keystore and truststore were created.
Once I followed the instructions here everything worked fine.
and
Don't mess with the enabled cipher suites. Take that code out and retest. You've enabled the anonymous suites, via which there is no authentication at all in either direction.