From 887173352bfa94e963af8000b395562364c7e8ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alen=20Vre=C4=8Dko?= <332217+avrecko@users.noreply.github.com> Date: Sat, 21 Dec 2024 21:37:35 +0100 Subject: [PATCH 1/2] Support for setting ciphersuites. --- src/one/nio/net/JavaSslClientContext.java | 5 +++++ src/one/nio/net/NativeSslContext.java | 3 +++ src/one/nio/net/SslConfig.java | 3 +++ src/one/nio/net/SslContext.java | 2 ++ src/one/nio/net/native/ssl.c | 14 ++++++++++++++ 5 files changed, 27 insertions(+) diff --git a/src/one/nio/net/JavaSslClientContext.java b/src/one/nio/net/JavaSslClientContext.java index ede9167..ad87165 100644 --- a/src/one/nio/net/JavaSslClientContext.java +++ b/src/one/nio/net/JavaSslClientContext.java @@ -64,6 +64,11 @@ public void setCiphers(String ciphers) throws SSLException { parameters.setCipherSuites(ciphers.split(":")); } + @Override + public void setCiphersuites(String ciphersuites) throws SSLException { + // Ignore + } + @Override public void setCurve(String curve) throws SSLException { // Ignore diff --git a/src/one/nio/net/NativeSslContext.java b/src/one/nio/net/NativeSslContext.java index a8a15f3..6b90564 100755 --- a/src/one/nio/net/NativeSslContext.java +++ b/src/one/nio/net/NativeSslContext.java @@ -199,6 +199,9 @@ public void setSessionCache(String mode, int size) throws SSLException { @Override public native void setCiphers(String ciphers) throws SSLException; + @Override + public native void setCiphersuites(String ciphersuites) throws SSLException; + /** * Sets the curve used for ECDH temporary keys used during key exchange. * Use openssl ecparam -list_curves to get list of supported curves. diff --git a/src/one/nio/net/SslConfig.java b/src/one/nio/net/SslConfig.java index 7056621..fbab00f 100644 --- a/src/one/nio/net/SslConfig.java +++ b/src/one/nio/net/SslConfig.java @@ -25,6 +25,7 @@ public class SslConfig { // Conservative ciphersuite according to https://wiki.mozilla.org/Security/Server_Side_TLS static final String DEFAULT_CIPHERS = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA"; + static final String DEFAULT_CIPHERSUITES = "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256"; static final String DEFAULT_CACHE_MODE = "internal"; static final int DEFAULT_CACHE_SIZE = 262144; static final long DEFAULT_TIMEOUT_SEC = 300; @@ -34,6 +35,7 @@ public class SslConfig { public boolean rdrand; public String protocols; public String ciphers; + public String ciphersuites; public String curve; public String[] certFile; public String[] privateKeyFile; @@ -65,6 +67,7 @@ public static SslConfig from(Properties props) { SslConfig config = new SslConfig(); config.protocols = props.getProperty("one.nio.ssl.protocols"); config.ciphers = props.getProperty("one.nio.ssl.ciphers"); + config.ciphersuites = props.getProperty("one.nio.ssl.ciphersuites"); config.curve = props.getProperty("one.nio.ssl.curve"); config.certFile = toArray(props.getProperty("one.nio.ssl.certFile")); config.privateKeyFile = toArray(props.getProperty("one.nio.ssl.privateKeyFile")); diff --git a/src/one/nio/net/SslContext.java b/src/one/nio/net/SslContext.java index f50e6c7..e4bb052 100755 --- a/src/one/nio/net/SslContext.java +++ b/src/one/nio/net/SslContext.java @@ -84,6 +84,7 @@ public synchronized SslContext configure(SslConfig config) throws IOException { } setCiphers(config.ciphers != null ? config.ciphers : SslConfig.DEFAULT_CIPHERS); + setCiphersuites(config.ciphersuites != null ? config.ciphersuites : SslConfig.DEFAULT_CIPHERSUITES); // with null the curve will be auto-selected by openssl setCurve(config.curve); @@ -307,6 +308,7 @@ void refresh() { public abstract void setRdrand(boolean rdrand) throws SSLException; public abstract void setProtocols(String protocols) throws SSLException; public abstract void setCiphers(String ciphers) throws SSLException; + public abstract void setCiphersuites(String ciphersuites) throws SSLException; public abstract void setCurve(String curve) throws SSLException; public abstract void setCertificate(String certFile) throws SSLException; public abstract void setPrivateKey(String privateKeyFile) throws SSLException; diff --git a/src/one/nio/net/native/ssl.c b/src/one/nio/net/native/ssl.c index 434d5d0..c047cca 100755 --- a/src/one/nio/net/native/ssl.c +++ b/src/one/nio/net/native/ssl.c @@ -709,6 +709,20 @@ Java_one_nio_net_NativeSslContext_setCiphers(JNIEnv* env, jobject self, jstring } } +JNIEXPORT void JNICALL +Java_one_nio_net_NativeSslContext_setCiphersuites(JNIEnv* env, jobject self, jstring ciphersuites) { + SSL_CTX* ctx = (SSL_CTX*)(intptr_t)(*env)->GetLongField(env, self, f_ctx); + + if (ciphersuites != NULL) { + const char* value = (*env)->GetStringUTFChars(env, ciphersuites, NULL); + int result = SSL_CTX_set_ciphersuites(ctx, value); + (*env)->ReleaseStringUTFChars(env, ciphersuites, value); + if (result <= 0) { + throw_ssl_exception(env); + } + } +} + JNIEXPORT void JNICALL Java_one_nio_net_NativeSslContext_setCurve(JNIEnv* env, jobject self, jstring curve) { SSL_CTX* ctx = (SSL_CTX*)(intptr_t)(*env)->GetLongField(env, self, f_ctx); From 17c9b357a173bd935263d7d3ce9c3f8d2f70e96a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alen=20Vre=C4=8Dko?= <332217+avrecko@users.noreply.github.com> Date: Sat, 21 Dec 2024 21:40:33 +0100 Subject: [PATCH 2/2] Support for setting SNI extension on ssl socket handshake. Need this to support virtual host ssl servers. --- src/one/nio/net/NativeSslSocket.java | 2 +- src/one/nio/net/Socket.java | 2 +- src/one/nio/net/native/ssl.c | 21 ++++++++++++++++++++- src/one/nio/pool/SocketPool.java | 2 +- 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/one/nio/net/NativeSslSocket.java b/src/one/nio/net/NativeSslSocket.java index c460e01..049d5be 100755 --- a/src/one/nio/net/NativeSslSocket.java +++ b/src/one/nio/net/NativeSslSocket.java @@ -92,7 +92,7 @@ public Object getSslOption(SslOption option) { return null; } @Override - public synchronized native void handshake() throws IOException; + public synchronized native void handshake(String sniHostName) throws IOException; @Override public synchronized native int writeRaw(long buf, int count, int flags) throws IOException; diff --git a/src/one/nio/net/Socket.java b/src/one/nio/net/Socket.java index 30621cf..f0b0833 100755 --- a/src/one/nio/net/Socket.java +++ b/src/one/nio/net/Socket.java @@ -174,7 +174,7 @@ public int send(ByteBuffer data, int flags, String host, int port) throws IOExce return send(data, flags, InetAddress.getByName(host), port); } - public void handshake() throws IOException { + public void handshake(String sniHostname) throws IOException { // Only for SSL sockets } diff --git a/src/one/nio/net/native/ssl.c b/src/one/nio/net/native/ssl.c index c047cca..8e850f1 100755 --- a/src/one/nio/net/native/ssl.c +++ b/src/one/nio/net/native/ssl.c @@ -1109,12 +1109,31 @@ Java_one_nio_net_NativeSslSocket_sslFree(JNIEnv* env, jclass cls, jlong sslptr) SSL_free(ssl); } +static void set_tlsext_host_name(JNIEnv* env, SSL* ssl, jstring hostName) { + if (hostName != NULL) { + struct in_addr ipv4; + struct in6_addr ipv6; + const char *value = (*env) -> GetStringUTFChars(env, hostName, NULL); + // set sni if hostname not ipv4/ipv6 + if (inet_pton(AF_INET, value, &ipv4) != 1 && inet_pton(AF_INET6, value, &ipv6) != 1) { + int result = SSL_set_tlsext_host_name(ssl, value); + (*env)->ReleaseStringUTFChars(env, hostName, value); + if (result <= 0) { + check_ssl_error(env, ssl, result); + } + } else { + (*env)->ReleaseStringUTFChars(env, hostName, value); + } + } +} + JNIEXPORT void JNICALL -Java_one_nio_net_NativeSslSocket_handshake(JNIEnv* env, jobject self) { +Java_one_nio_net_NativeSslSocket_handshake(JNIEnv* env, jobject self, jstring hostName) { SSL* ssl = (SSL*)(intptr_t) (*env)->GetLongField(env, self, f_ssl); if (ssl == NULL) { throw_socket_closed(env); } else { + set_tlsext_host_name(env, ssl, hostName); int result = SSL_do_handshake(ssl); if (result <= 0) { check_ssl_error(env, ssl, result); diff --git a/src/one/nio/pool/SocketPool.java b/src/one/nio/pool/SocketPool.java index bc23db5..4a7378b 100755 --- a/src/one/nio/pool/SocketPool.java +++ b/src/one/nio/pool/SocketPool.java @@ -177,7 +177,7 @@ public Socket createObject() throws PoolException { if (sslContext != null) { socket = socket.sslWrap(sslContext); - socket.handshake(); + socket.handshake(host); } return socket;