Skip to content
Commits on Source (5)
......@@ -29,3 +29,11 @@
# Do not include stuff in the static modules as this is generated during the build
*-static/src
# exclude mainframer files
mainframer
.mainframer
# exclude cmake related files
CMakeLists.txt
cmake-*
......@@ -19,7 +19,7 @@
<parent>
<groupId>io.netty</groupId>
<artifactId>netty-tcnative-parent</artifactId>
<version>2.0.15.Final</version>
<version>2.0.20.Final</version>
</parent>
<artifactId>netty-tcnative-boringssl-static</artifactId>
<packaging>jar</packaging>
......@@ -89,6 +89,24 @@
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${generatedSourcesDir}/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<!-- Add the commit ID and branch to the manifest. -->
<plugin>
<groupId>org.apache.felix</groupId>
......@@ -126,7 +144,7 @@
<!-- Build the BoringSSL static libs -->
<execution>
<id>build-boringssl</id>
<phase>generate-sources</phase>
<phase>compile</phase>
<goals>
<goal>run</goal>
</goals>
......@@ -135,6 +153,14 @@
<!-- Add the ant tasks from ant-contrib -->
<taskdef resource="net/sf/antcontrib/antcontrib.properties" />
<if>
<available file="${boringsslBuildDir}" />
<then>
<echo message="BoringSSL was already build, skipping the build step." />
</then>
<else>
<echo message="Building BoringSSL" />
<mkdir dir="${boringsslBuildDir}" />
<if>
......@@ -171,6 +197,8 @@
<arg value=".." />
</exec>
<exec executable="ninja" failonerror="true" dir="${boringsslBuildDir}" resolveexecutable="true" />
</else>
</if>
</target>
</configuration>
</execution>
......@@ -230,7 +258,8 @@
<phase>compile</phase>
<configuration>
<name>netty_tcnative</name>
<nativeSourceDirectory>${project.basedir}/src/main/c</nativeSourceDirectory>
<nativeSourceDirectory>${generatedSourcesDir}/c</nativeSourceDirectory>
<customPackageDirectory>${generatedSourcesDir}/native-package</customPackageDirectory>
<libDirectory>${nativeLibOnlyDir}</libDirectory>
<forceAutogen>${forceAutogen}</forceAutogen>
<forceConfigure>${forceConfigure}</forceConfigure>
......
......@@ -19,7 +19,7 @@
<parent>
<groupId>io.netty</groupId>
<artifactId>netty-tcnative-parent</artifactId>
<version>2.0.15.Final</version>
<version>2.0.20.Final</version>
</parent>
<artifactId>netty-tcnative-libressl-static</artifactId>
<packaging>jar</packaging>
......@@ -41,34 +41,6 @@
<build>
<plugins>
<!-- Configure the distribution statically linked against OpenSSL and APR -->
<plugin>
<groupId>org.fusesource.hawtjni</groupId>
<artifactId>maven-hawtjni-plugin</artifactId>
<executions>
<execution>
<id>build-native-lib</id>
<goals>
<goal>generate</goal>
<goal>build</goal>
</goals>
<phase>compile</phase>
<configuration>
<name>netty_tcnative</name>
<nativeSourceDirectory>${project.basedir}/src/main/c</nativeSourceDirectory>
<libDirectory>${nativeLibOnlyDir}</libDirectory>
<forceAutogen>${forceAutogen}</forceAutogen>
<forceConfigure>${forceConfigure}</forceConfigure>
<windowsBuildTool>msbuild</windowsBuildTool>
<configureArgs>
<configureArg>--with-ssl=${sslHome}</configureArg>
<configureArg>--with-apr=${aprHome}</configureArg>
<configureArg>--with-static-libs</configureArg>
</configureArgs>
</configuration>
</execution>
</executions>
</plugin>
<!-- Add the LibreSSL version to the manifest. -->
<plugin>
......@@ -82,6 +54,24 @@
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${generatedSourcesDir}/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
......@@ -108,6 +98,36 @@
</execution>
</executions>
</plugin>
<!-- Configure the distribution statically linked against OpenSSL and APR -->
<plugin>
<groupId>org.fusesource.hawtjni</groupId>
<artifactId>maven-hawtjni-plugin</artifactId>
<executions>
<execution>
<id>build-native-lib</id>
<goals>
<goal>generate</goal>
<goal>build</goal>
</goals>
<phase>compile</phase>
<configuration>
<name>netty_tcnative</name>
<nativeSourceDirectory>${generatedSourcesDir}/c</nativeSourceDirectory>
<customPackageDirectory>${generatedSourcesDir}/native-package</customPackageDirectory>
<libDirectory>${nativeLibOnlyDir}</libDirectory>
<forceAutogen>${forceAutogen}</forceAutogen>
<forceConfigure>${forceConfigure}</forceConfigure>
<windowsBuildTool>msbuild</windowsBuildTool>
<configureArgs>
<configureArg>--with-ssl=${sslHome}</configureArg>
<configureArg>--with-apr=${aprHome}</configureArg>
<configureArg>--with-static-libs</configureArg>
</configureArgs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
......@@ -165,19 +185,53 @@
<executions>
<!-- Download and build LibreSSL -->
<execution>
<id>build-libressl-non-windows</id>
<id>source-libressl-non-windows</id>
<phase>generate-sources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<!-- Add the ant tasks from ant-contrib -->
<taskdef resource="net/sf/antcontrib/antcontrib.properties" />
<if>
<available file="${libresslCheckoutDir}" />
<then>
<echo message="LibreSSL was already downloaded, skipping the build step." />
</then>
<else>
<echo message="Downloading LibreSSL" />
<get src="http://ftp.openbsd.org/pub/OpenBSD/LibreSSL/${libresslArchive}" dest="${project.build.directory}/${libresslArchive}" verbose="on" />
<checksum file="${project.build.directory}/${libresslArchive}" algorithm="SHA-256" property="${libresslSha256}" verifyProperty="isEqual" />
<exec executable="tar" failonerror="true" dir="${project.build.directory}/" resolveexecutable="true">
<arg value="xfv" />
<arg value="${libresslArchive}" />
</exec>
</else>
</if>
</target>
</configuration>
</execution>
<execution>
<id>build-libressl-non-windows</id>
<phase>compile</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<!-- Add the ant tasks from ant-contrib -->
<taskdef resource="net/sf/antcontrib/antcontrib.properties" />
<if>
<available file="${sslHome}" />
<then>
<echo message="LibreSSL was already build, skipping the build step." />
</then>
<else>
<echo message="Building LibreSSL" />
<mkdir dir="${sslHome}" />
<exec executable="configure" failonerror="true" dir="${libresslCheckoutDir}" resolveexecutable="true">
<arg line="--disable-shared --prefix=${sslHome} CFLAGS='-O3 -fno-omit-frame-pointer -fPIC'" />
......@@ -186,6 +240,8 @@
<exec executable="make" failonerror="true" dir="${libresslCheckoutDir}" resolveexecutable="true">
<arg line="install" />
</exec>
</else>
</if>
</target>
</configuration>
</execution>
......
......@@ -19,7 +19,7 @@
<parent>
<groupId>io.netty</groupId>
<artifactId>netty-tcnative-parent</artifactId>
<version>2.0.15.Final</version>
<version>2.0.20.Final</version>
</parent>
<artifactId>netty-tcnative</artifactId>
<packaging>jar</packaging>
......
......@@ -42,6 +42,10 @@ TCN_IMPLEMENT_CALL(jint, NativeStaticallyReferencedJniMethods, sslOpNoTLSv12)(TC
return SSL_OP_NO_TLSv1_2;
}
TCN_IMPLEMENT_CALL(jint, NativeStaticallyReferencedJniMethods, sslOpNoTLSv13)(TCN_STDARGS) {
return SSL_OP_NO_TLSv1_3;
}
TCN_IMPLEMENT_CALL(jint, NativeStaticallyReferencedJniMethods, sslOpNoTicket)(TCN_STDARGS) {
return SSL_OP_NO_TICKET;
}
......@@ -484,6 +488,7 @@ static const JNINativeMethod method_table[] = {
{ TCN_METHOD_TABLE_ENTRY(sslOpNoTLSv1, ()I, NativeStaticallyReferencedJniMethods) },
{ TCN_METHOD_TABLE_ENTRY(sslOpNoTLSv11, ()I, NativeStaticallyReferencedJniMethods) },
{ TCN_METHOD_TABLE_ENTRY(sslOpNoTLSv12, ()I, NativeStaticallyReferencedJniMethods) },
{ TCN_METHOD_TABLE_ENTRY(sslOpNoTLSv13, ()I, NativeStaticallyReferencedJniMethods) },
{ TCN_METHOD_TABLE_ENTRY(sslOpNoTicket, ()I, NativeStaticallyReferencedJniMethods) },
{ TCN_METHOD_TABLE_ENTRY(sslOpNoCompression, ()I, NativeStaticallyReferencedJniMethods) },
{ TCN_METHOD_TABLE_ENTRY(sslSessCacheOff, ()I, NativeStaticallyReferencedJniMethods) },
......
......@@ -1559,27 +1559,50 @@ TCN_IMPLEMENT_CALL(jobjectArray, SSL, getCiphers)(TCN_STDARGS, jlong ssl)
}
TCN_IMPLEMENT_CALL(jboolean, SSL, setCipherSuites)(TCN_STDARGS, jlong ssl,
jstring ciphers)
jstring ciphers, jboolean tlsv13)
{
jboolean rv = JNI_TRUE;
TCN_ALLOC_CSTRING(ciphers);
SSL *ssl_ = J2P(ssl, SSL *);
TCN_CHECK_NULL(ssl_, ssl, JNI_FALSE);
UNREFERENCED(o);
#ifdef OPENSSL_NO_TLS1_3
if (tlsv13 == JNI_TRUE) {
tcn_Throw(e, "TLSv1.3 not supported");
return JNI_FALSE;
}
#endif
if (ciphers == NULL || (*e)->GetStringUTFLength(e, ciphers) == 0) {
return JNI_FALSE;
}
TCN_ALLOC_CSTRING(ciphers);
UNREFERENCED(o);
if (!J2S(ciphers)) {
return JNI_FALSE;
}
if (!SSL_set_cipher_list(ssl_, J2S(ciphers))) {
char err[ERR_LEN];
#ifdef OPENSSL_NO_TLS1_3
rv = SSL_set_cipher_list(ssl_, J2S(ciphers)) == 0 ? JNI_FALSE : JNI_TRUE;
#else
if (tlsv13 == JNI_TRUE) {
#ifdef OPENSSL_IS_BORINGSSL
// BoringSSL does not support setting TLSv1.3 cipher suites explicit for now.
rv = JNI_TRUE;
#else
rv = SSL_set_ciphersuites(ssl_, J2S(ciphers)) == 0 ? JNI_FALSE : JNI_TRUE;
#endif // OPENSSL_IS_BORINGSSL
} else {
rv = SSL_set_cipher_list(ssl_, J2S(ciphers)) == 0 ? JNI_FALSE : JNI_TRUE;
}
#endif // OPENSSL_NO_TLS1_3
if (rv == JNI_FALSE) {
char err[256];
ERR_error_string(ERR_get_error(), err);
tcn_Throw(e, "Unable to configure permitted SSL ciphers (%s)", err);
rv = JNI_FALSE;
}
TCN_FREE_CSTRING(ciphers);
return rv;
}
......@@ -1632,7 +1655,7 @@ TCN_IMPLEMENT_CALL(void, SSL, clearError)(TCN_STDARGS)
ERR_clear_error();
}
TCN_IMPLEMENT_CALL(void, SSL, setTlsExtHostName)(TCN_STDARGS, jlong ssl, jstring hostname) {
TCN_IMPLEMENT_CALL(void, SSL, setTlsExtHostName0)(TCN_STDARGS, jlong ssl, jstring hostname) {
SSL *ssl_ = J2P(ssl, SSL *);
TCN_CHECK_NULL(ssl_, ssl, /* void */);
......@@ -1708,7 +1731,7 @@ TCN_IMPLEMENT_CALL(jobjectArray, SSL, authenticationMethods)(TCN_STDARGS, jlong
for (i = 0; i < len; i++) {
(*e)->SetObjectArrayElement(e, array, i,
(*e)->NewStringUTF(e, tcn_SSL_cipher_authentication_method((SSL_CIPHER*) sk_value((_STACK*) ciphers, i))));
(*e)->NewStringUTF(e, tcn_SSL_cipher_authentication_method(sk_SSL_CIPHER_value(ciphers, i))));
}
return array;
}
......@@ -1910,7 +1933,7 @@ TCN_IMPLEMENT_CALL(void, SSL, freeX509Chain)(TCN_STDARGS, jlong x509Chain)
sk_X509_pop_free(chain, X509_free);
}
TCN_IMPLEMENT_CALL(void, SSL, setKeyMaterialServerSide)(TCN_STDARGS, jlong ssl, jlong chain, jlong key)
TCN_IMPLEMENT_CALL(void, SSL, setKeyMaterial)(TCN_STDARGS, jlong ssl, jlong chain, jlong key)
{
#if defined(LIBRESSL_VERSION_NUMBER)
tcn_Throw(e, "Not supported with LibreSSL");
......@@ -2196,6 +2219,95 @@ TCN_IMPLEMENT_CALL(void, SSL, fipsModeSet)(TCN_STDARGS, jint mode)
#endif
}
TCN_IMPLEMENT_CALL(jstring, SSL, getSniHostname)(TCN_STDARGS, jlong ssl)
{
SSL *ssl_ = J2P(ssl, SSL *);
TCN_CHECK_NULL(ssl_, ssl, 0);
const char *servername = SSL_get_servername(ssl_, TLSEXT_NAMETYPE_host_name);
if (servername == NULL) {
return NULL;
}
return tcn_new_string(e, servername);
}
TCN_IMPLEMENT_CALL(jobjectArray, SSL, getSigAlgs)(TCN_STDARGS, jlong ssl) {
SSL *ssl_ = J2P(ssl, SSL *);
TCN_CHECK_NULL(ssl_, ssl, NULL);
// Not supported in LibreSSL
#if defined(LIBRESSL_VERSION_NUMBER)
return NULL;
#elif defined(OPENSSL_IS_BORINGSSL)
// Using a different API in BoringSSL
// https://boringssl.googlesource.com/boringssl/+/ba16a1e405c617f4179bd780ad15522fb25b0a65%5E%21/
int i;
jobjectArray array;
jstring algString;
const uint16_t *peer_sigalgs;
size_t num_peer_sigalgs = SSL_get0_peer_verify_algorithms(ssl_, &peer_sigalgs);
if (num_peer_sigalgs <= 0) {
return NULL;
}
array = (*e)->NewObjectArray(e, num_peer_sigalgs, tcn_get_string_class(), NULL);
if (array == NULL) {
return NULL;
}
for (i = 0; i < num_peer_sigalgs; i++) {
algString = (*e)->NewStringUTF(e, SSL_get_signature_algorithm_name(peer_sigalgs[i], SSL_version(ssl_) != TLS1_2_VERSION));
if (algString == NULL) {
// something is wrong we should better just return here
return NULL;
}
(*e)->SetObjectArrayElement(e, array, i, algString);
}
return array;
#else
// Use weak linking with GCC as this will alow us to run the same packaged version with multiple
// version of openssl.
#if defined(__GNUC__) || defined(__GNUG__)
if (!SSL_get_sigalgs) {
UNREFERENCED(o);
return NULL;
}
#endif
// We can only support it when either use openssl version >= 1.0.2 or GCC as this way we can use weak linking
#if OPENSSL_VERSION_NUMBER >= 0x10002000L || defined(__GNUC__) || defined(__GNUG__)
int i;
int nsig;
int psignhash;
jobjectArray array;
jstring algString;
UNREFERENCED(o);
nsig = SSL_get_sigalgs(ssl_, 0, NULL, NULL, NULL, NULL, NULL);
if (nsig <= 0) {
return NULL;
}
array = (*e)->NewObjectArray(e, nsig, tcn_get_string_class(), NULL);
if (array == NULL) {
return NULL;
}
for (i = 0; i < nsig; i++) {
SSL_get_sigalgs(ssl_, i, NULL, NULL, &psignhash, NULL, NULL);
algString = (*e)->NewStringUTF(e, OBJ_nid2ln(psignhash));
if (algString == NULL) {
// something is wrong we should better just return here
return NULL;
}
(*e)->SetObjectArrayElement(e, array, i, algString);
}
return array;
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L || defined(__GNUC__) || defined(__GNUG__)
#endif // defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
}
// JNI Method Registration Table Begin
static const JNINativeMethod method_table[] = {
......@@ -2243,11 +2355,11 @@ static const JNINativeMethod method_table[] = {
{ TCN_METHOD_TABLE_ENTRY(getMode, (J)I, SSL) },
{ TCN_METHOD_TABLE_ENTRY(getMaxWrapOverhead, (J)I, SSL) },
{ TCN_METHOD_TABLE_ENTRY(getCiphers, (J)[Ljava/lang/String;, SSL) },
{ TCN_METHOD_TABLE_ENTRY(setCipherSuites, (JLjava/lang/String;)Z, SSL) },
{ TCN_METHOD_TABLE_ENTRY(setCipherSuites, (JLjava/lang/String;Z)Z, SSL) },
{ TCN_METHOD_TABLE_ENTRY(getSessionId, (J)[B, SSL) },
{ TCN_METHOD_TABLE_ENTRY(getHandshakeCount, (J)I, SSL) },
{ TCN_METHOD_TABLE_ENTRY(clearError, ()V, SSL) },
{ TCN_METHOD_TABLE_ENTRY(setTlsExtHostName, (JLjava/lang/String;)V, SSL) },
{ TCN_METHOD_TABLE_ENTRY(setTlsExtHostName0, (JLjava/lang/String;)V, SSL) },
{ TCN_METHOD_TABLE_ENTRY(setHostNameValidation, (JILjava/lang/String;)V, SSL) },
{ TCN_METHOD_TABLE_ENTRY(authenticationMethods, (J)[Ljava/lang/String;, SSL) },
{ TCN_METHOD_TABLE_ENTRY(setCertificateBio, (JJJLjava/lang/String;)V, SSL) },
......@@ -2257,12 +2369,14 @@ static const JNINativeMethod method_table[] = {
{ TCN_METHOD_TABLE_ENTRY(freePrivateKey, (J)V, SSL) },
{ TCN_METHOD_TABLE_ENTRY(parseX509Chain, (J)J, SSL) },
{ TCN_METHOD_TABLE_ENTRY(freeX509Chain, (J)V, SSL) },
{ TCN_METHOD_TABLE_ENTRY(setKeyMaterialServerSide, (JJJ)V, SSL) },
{ TCN_METHOD_TABLE_ENTRY(setKeyMaterial, (JJJ)V, SSL) },
{ TCN_METHOD_TABLE_ENTRY(setKeyMaterialClientSide, (JJJJJ)V, SSL) },
{ TCN_METHOD_TABLE_ENTRY(enableOcsp, (J)V, SSL) },
{ TCN_METHOD_TABLE_ENTRY(setOcspResponse, (J[B)V, SSL) },
{ TCN_METHOD_TABLE_ENTRY(getOcspResponse, (J)[B, SSL) },
{ TCN_METHOD_TABLE_ENTRY(fipsModeSet, (I)V, SSL) }
{ TCN_METHOD_TABLE_ENTRY(fipsModeSet, (I)V, SSL) },
{ TCN_METHOD_TABLE_ENTRY(getSniHostname, (J)Ljava/lang/String;, SSL) },
{ TCN_METHOD_TABLE_ENTRY(getSigAlgs, (J)[Ljava/lang/String;, SSL) }
};
static const jint method_table_size = sizeof(method_table) / sizeof(method_table[0]);
......
......@@ -131,6 +131,15 @@ extern const char* TCN_UNKNOWN_AUTH_METHOD;
#define TLS1_3_VERSION 0x0304
#endif
#ifndef SSL_OP_NO_TLSv1_3
// TLSV1_3 is not really supported by the underlying OPENSSL version
#ifndef OPENSSL_NO_TLS1_3
#define OPENSSL_NO_TLS1_3
#endif // OPENSSL_NO_TLS1_3
#define SSL_OP_NO_TLSv1_3 0x00000000U
#endif // SSL_OP_NO_TLSv1_3
/* OpenSSL 1.0.2 compatibility */
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
#define TLS_method SSLv23_method
......@@ -224,6 +233,9 @@ struct tcn_ssl_ctxt_t {
jobject cert_requested_callback;
jmethodID cert_requested_callback_method;
jobject certificate_callback;
jmethodID certificate_callback_method;
jobject sni_hostname_matcher;
jmethodID sni_hostname_matcher_method;
......@@ -317,6 +329,9 @@ const char *tcn_SSL_cipher_authentication_method(const SSL_CIPHER *);
extern X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl) __attribute__((weak));
extern void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param, unsigned int flags) __attribute__((weak));
extern int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param, const char *name, size_t namelen) __attribute__((weak));
extern int SSL_get_sigalgs(SSL *s, int idx, int *psign, int *phash, int *psignhash, unsigned char *rsig, unsigned char *rhash) __attribute__((weak));
extern void SSL_CTX_set_cert_cb(SSL_CTX *c, int (*cert_cb)(SSL *ssl, void *arg), void *arg) __attribute__((weak));
#endif
#endif /* SSL_PRIVATE_H */
......@@ -63,6 +63,13 @@ static apr_status_t ssl_context_cleanup(void *data)
}
c->cert_requested_callback_method = NULL;
if (c->certificate_callback != NULL) {
tcn_get_java_env(&e);
(*e)->DeleteGlobalRef(e, c->certificate_callback);
c->certificate_callback = NULL;
}
c->certificate_callback_method = NULL;
if (c->sni_hostname_matcher != NULL) {
tcn_get_java_env(&e);
(*e)->DeleteGlobalRef(e, c->sni_hostname_matcher);
......@@ -118,6 +125,14 @@ TCN_IMPLEMENT_CALL(jlong, SSLContext, make)(TCN_STDARGS, jint protocol, jint mod
ctx = SSL_CTX_new(TLS_server_method());
else
ctx = SSL_CTX_new(TLS_method());
// Needed in BoringSSL to be able to use TLSv1.3
//
// See http://hg.nginx.org/nginx/rev/7ad0f4ace359
#if defined(OPENSSL_IS_BORINGSSL)
SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION);
#endif
#else
switch (protocol) {
case SSL_PROTOCOL_TLS:
......@@ -415,24 +430,50 @@ TCN_IMPLEMENT_CALL(void, SSLContext, clearOptions)(TCN_STDARGS, jlong ctx,
}
TCN_IMPLEMENT_CALL(jboolean, SSLContext, setCipherSuite)(TCN_STDARGS, jlong ctx,
jstring ciphers)
jstring ciphers, jboolean tlsv13)
{
tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
jboolean rv = JNI_TRUE;
TCN_CHECK_NULL(c, ctx, JNI_FALSE);
TCN_ALLOC_CSTRING(ciphers);
#ifdef OPENSSL_NO_TLS1_3
if (tlsv13 == JNI_TRUE) {
tcn_Throw(e, "TLSv1.3 not supported");
return JNI_FALSE;
}
#endif
if (ciphers == NULL || (*e)->GetStringUTFLength(e, ciphers) == 0) {
return JNI_FALSE;
}
TCN_ALLOC_CSTRING(ciphers);
UNREFERENCED(o);
if (!J2S(ciphers))
if (!J2S(ciphers)) {
return JNI_FALSE;
}
#ifdef OPENSSL_NO_TLS1_3
rv = SSL_CTX_set_cipher_list(c->ctx, J2S(ciphers)) == 0 ? JNI_FALSE : JNI_TRUE;
#else
if (tlsv13 == JNI_TRUE) {
#ifdef OPENSSL_IS_BORINGSSL
// BoringSSL does not support setting TLSv1.3 cipher suites explicit for now.
rv = JNI_TRUE;
#else
rv = SSL_CTX_set_ciphersuites(c->ctx, J2S(ciphers)) == 0 ? JNI_FALSE : JNI_TRUE;
#endif // OPENSSL_IS_BORINGSSL
if (!SSL_CTX_set_cipher_list(c->ctx, J2S(ciphers))) {
} else {
rv = SSL_CTX_set_cipher_list(c->ctx, J2S(ciphers)) == 0 ? JNI_FALSE : JNI_TRUE;
}
#endif // OPENSSL_NO_TLS1_3
if (rv == JNI_FALSE) {
char err[256];
ERR_error_string(ERR_get_error(), err);
tcn_Throw(e, "Unable to configure permitted SSL ciphers (%s)", err);
rv = JNI_FALSE;
}
TCN_FREE_CSTRING(ciphers);
return rv;
......@@ -1427,6 +1468,22 @@ TCN_IMPLEMENT_CALL(void, SSLContext, setCertVerifyCallback)(TCN_STDARGS, jlong c
}
}
static jbyteArray keyTypes(JNIEnv* e, SSL* ssl) {
jbyte* ctype_bytes;
jbyteArray types;
int ctype_num = tcn_SSL_get0_certificate_types(ssl, (const uint8_t **) &ctype_bytes);
if (ctype_num <= 0) {
// No idea what we should use... Let the caller handle it.
return NULL;
}
types = (*e)->NewByteArray(e, ctype_num);
if (types == NULL) {
return NULL;
}
(*e)->SetByteArrayRegion(e, types, 0, ctype_num, ctype_bytes);
return types;
}
/**
* Returns an array containing all the X500 principal's bytes.
*
......@@ -1495,31 +1552,18 @@ static int cert_requested(SSL* ssl, X509** x509Out, EVP_PKEY** pkeyOut) {
#endif // OPENSSL_IS_BORINGSSL
tcn_ssl_ctxt_t *c = tcn_SSL_get_app_data2(ssl);
int ctype_num;
jbyte* ctype_bytes;
jobjectArray issuers;
JNIEnv *e;
jbyteArray keyTypes;
jbyteArray types;
tcn_get_java_env(&e);
ctype_num = tcn_SSL_get0_certificate_types(ssl, (const uint8_t **) &ctype_bytes);
if (ctype_num <= 0) {
// Use no certificate
return 0;
}
keyTypes = (*e)->NewByteArray(e, ctype_num);
if (keyTypes == NULL) {
// Something went seriously wrong, bail out!
return -1;
}
(*e)->SetByteArrayRegion(e, keyTypes, 0, ctype_num, ctype_bytes);
types = keyTypes(e, ssl);
issuers = principalBytes(e, SSL_get_client_CA_list(ssl));
// Execute the java callback
(*e)->CallVoidMethod(e, c->cert_requested_callback, c->cert_requested_callback_method,
P2J(ssl), P2J(x509Out), P2J(pkeyOut), keyTypes, issuers);
P2J(ssl), P2J(x509Out), P2J(pkeyOut), types, issuers);
// Check if java threw an exception and if so signal back that we should not continue with the handshake.
if ((*e)->ExceptionCheck(e)) {
......@@ -1564,6 +1608,101 @@ TCN_IMPLEMENT_CALL(void, SSLContext, setCertRequestedCallback)(TCN_STDARGS, jlon
}
}
static int certificate_cb(SSL* ssl, void* arg) {
#if defined(LIBRESSL_VERSION_NUMBER)
// Not supported with LibreSSL
return -1;
#else
#ifndef OPENSSL_IS_BORINGSSL
if (OpenSSL_version_num() < 0x10002000L) {
// Only supported on openssl 1.0.2+
return -1;
}
#endif // OPENSSL_IS_BORINGSSL
tcn_ssl_ctxt_t *c = tcn_SSL_get_app_data2(ssl);
TCN_ASSERT(c != NULL);
jobjectArray issuers;
JNIEnv *e;
jbyteArray types;
tcn_get_java_env(&e);
if (c->mode == SSL_MODE_SERVER) {
// TODO: Consider filling these somehow.
types = NULL;
issuers = NULL;
} else {
types = keyTypes(e, ssl);
issuers = principalBytes(e, SSL_get_client_CA_list(ssl));
}
// Execute the java callback
(*e)->CallVoidMethod(e, c->certificate_callback, c->certificate_callback_method,
P2J(ssl), types, issuers);
// Check if java threw an exception and if so signal back that we should not continue with the handshake.
if ((*e)->ExceptionCheck(e)) {
return -1;
}
// Everything good...
return 1;
#endif /* defined(LIBRESSL_VERSION_NUMBER) */
}
TCN_IMPLEMENT_CALL(void, SSLContext, setCertificateCallback)(TCN_STDARGS, jlong ctx, jobject callback)
{
tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
TCN_CHECK_NULL(c, ctx, /* void */);
#if defined(LIBRESSL_VERSION_NUMBER)
tcn_Throw(e, "Not supported with LibreSSL");
#else
UNREFERENCED(o);
// Use weak linking with GCC as this will alow us to run the same packaged version with multiple
// version of openssl.
#if defined(__GNUC__) || defined(__GNUG__)
if (!SSL_CTX_set_cert_cb) {
UNREFERENCED(o);
tcn_ThrowException(e, "Requires OpenSSL 1.0.2+");
}
#endif // defined(__GNUC__) || defined(__GNUG__)
// We can only support it when either use openssl version >= 1.0.2 or GCC as this way we can use weak linking
#if OPENSSL_VERSION_NUMBER >= 0x10002000L || defined(__GNUC__) || defined(__GNUG__)
if (callback == NULL) {
SSL_CTX_set_cert_cb(c->ctx, NULL, NULL);
} else {
jclass callback_class = (*e)->GetObjectClass(e, callback);
if (callback_class == NULL) {
tcn_Throw(e, "Unable to retrieve callback class");
return;
}
jmethodID method = (*e)->GetMethodID(e, callback_class, "handle", "(J[B[[B)V");
if (method == NULL) {
tcn_Throw(e, "Unable to retrieve callback method");
return;
}
if (c->certificate_callback != NULL) {
(*e)->DeleteGlobalRef(e, c->certificate_callback);
}
c->certificate_callback = (*e)->NewGlobalRef(e, callback);
c->certificate_callback_method = method;
SSL_CTX_set_cert_cb(c->ctx, certificate_cb, NULL);
}
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L || defined(__GNUC__) || defined(__GNUG__)
#endif // defined(LIBRESSL_VERSION_NUMBER)
}
static int ssl_servername_cb(SSL *ssl, int *ad, void *arg)
{
JNIEnv *e = NULL;
......@@ -1674,6 +1813,15 @@ TCN_IMPLEMENT_CALL(jint, SSLContext, getMode)(TCN_STDARGS, jlong ctx)
return (jint) SSL_CTX_get_mode(c->ctx);
}
TCN_IMPLEMENT_CALL(jlong, SSLContext, getSslCtx)(TCN_STDARGS, jlong ctx)
{
tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
TCN_CHECK_NULL(c, ctx, 0);
return P2J(c->ctx);
}
#if !defined(OPENSSL_NO_OCSP) && !defined(TCN_OCSP_NOT_SUPPORTED) && !defined(OPENSSL_IS_BORINGSSL)
static const int OCSP_CLIENT_ACK = 1;
......@@ -1755,7 +1903,7 @@ static const JNINativeMethod fixed_method_table[] = {
{ TCN_METHOD_TABLE_ENTRY(setOptions, (JI)V, SSLContext) },
{ TCN_METHOD_TABLE_ENTRY(getOptions, (J)I, SSLContext) },
{ TCN_METHOD_TABLE_ENTRY(clearOptions, (JI)V, SSLContext) },
{ TCN_METHOD_TABLE_ENTRY(setCipherSuite, (JLjava/lang/String;)Z, SSLContext) },
{ TCN_METHOD_TABLE_ENTRY(setCipherSuite, (JLjava/lang/String;Z)Z, SSLContext) },
{ TCN_METHOD_TABLE_ENTRY(setCertificateChainFile, (JLjava/lang/String;Z)Z, SSLContext) },
{ TCN_METHOD_TABLE_ENTRY(setCertificateChainBio, (JJZ)Z, SSLContext) },
{ TCN_METHOD_TABLE_ENTRY(setCACertificateBio, (JJ)Z, SSLContext) },
......@@ -1791,19 +1939,21 @@ static const JNINativeMethod fixed_method_table[] = {
// setCertVerifyCallback -> needs dynamic method table
// setCertRequestedCallback -> needs dynamic method table
// setCertificateCallback -> needs dynamic method table
// setSniHostnameMatcher -> needs dynamic method table
{ TCN_METHOD_TABLE_ENTRY(setSessionIdContext, (J[B)Z, SSLContext) },
{ TCN_METHOD_TABLE_ENTRY(setMode, (JI)I, SSLContext) },
{ TCN_METHOD_TABLE_ENTRY(getMode, (J)I, SSLContext) },
{ TCN_METHOD_TABLE_ENTRY(enableOcsp, (JZ)V, SSLContext) },
{ TCN_METHOD_TABLE_ENTRY(disableOcsp, (J)V, SSLContext) }
{ TCN_METHOD_TABLE_ENTRY(disableOcsp, (J)V, SSLContext) },
{ TCN_METHOD_TABLE_ENTRY(getSslCtx, (J)J, SSLContext) }
};
static const jint fixed_method_table_size = sizeof(fixed_method_table) / sizeof(fixed_method_table[0]);
static jint dynamicMethodsTableSize() {
return fixed_method_table_size + 3;
return fixed_method_table_size + 4;
}
static JNINativeMethod* createDynamicMethodsTable(const char* packagePrefix) {
......@@ -1823,8 +1973,15 @@ static JNINativeMethod* createDynamicMethodsTable(const char* packagePrefix) {
dynamicMethod->fnPtr = (void *) TCN_FUNCTION_NAME(SSLContext, setCertRequestedCallback);
free(dynamicTypeName);
dynamicTypeName = netty_internal_tcnative_util_prepend(packagePrefix, "io/netty/internal/tcnative/SniHostNameMatcher;)V");
dynamicTypeName = netty_internal_tcnative_util_prepend(packagePrefix, "io/netty/internal/tcnative/CertificateCallback;)V");
dynamicMethod = &dynamicMethods[fixed_method_table_size + 2];
dynamicMethod->name = "setCertificateCallback";
dynamicMethod->signature = netty_internal_tcnative_util_prepend("(JL", dynamicTypeName);
dynamicMethod->fnPtr = (void *) TCN_FUNCTION_NAME(SSLContext, setCertificateCallback);
free(dynamicTypeName);
dynamicTypeName = netty_internal_tcnative_util_prepend(packagePrefix, "io/netty/internal/tcnative/SniHostNameMatcher;)V");
dynamicMethod = &dynamicMethods[fixed_method_table_size + 3];
dynamicMethod->name = "setSniHostnameMatcher";
dynamicMethod->signature = netty_internal_tcnative_util_prepend("(JL", dynamicTypeName);
dynamicMethod->fnPtr = (void *) TCN_FUNCTION_NAME(SSLContext, setSniHostnameMatcher);
......
......@@ -106,6 +106,12 @@ const char* tcn_SSL_cipher_authentication_method(const SSL_CIPHER* cipher){
default:
return TCN_UNKNOWN_AUTH_METHOD;
}
#ifndef OPENSSL_NO_TLS1_3
case NID_kx_any:
// Let us just pick one as we could use whatever we want.
// See https://www.openssl.org/docs/man1.1.1/man3/SSL_CIPHER_get_kx_nid.html
return "ECDHE_" SSL_TXT_RSA;
#endif
default:
return TCN_UNKNOWN_AUTH_METHOD;
}
......
/*
* Copyright 2018 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.internal.tcnative;
/**
* Is called during handshake and hooked into openssl via {@code SSL_CTX_set_cert_cb}.
*
* IMPORTANT: Implementations of this interface should be static as it is stored as a global reference via JNI. This
* means if you use an inner / anonymous class to implement this and also depend on the finalizer of the
* class to free up the SSLContext the finalizer will never run as the object is never GC, due the hard
* reference to the enclosing class. This will most likely result in a memory leak.
*/
public interface CertificateCallback {
/**
* The types contained in the {@code keyTypeBytes} array.
*/
// Extracted from https://github.com/openssl/openssl/blob/master/include/openssl/tls1.h
byte TLS_CT_RSA_SIGN = 1;
byte TLS_CT_DSS_SIGN = 2;
byte TLS_CT_RSA_FIXED_DH = 3;
byte TLS_CT_DSS_FIXED_DH = 4;
byte TLS_CT_ECDSA_SIGN = 64;
byte TLS_CT_RSA_FIXED_ECDH = 65;
byte TLS_CT_ECDSA_FIXED_ECDH = 66;
/**
* Called during cert selection. If a certificate chain / key should be used
* {@link SSL#setKeyMaterial(long, long, long)} must be called from this callback after
* all preparations / validations were completed.
*
* @param ssl the SSL instance
* @param keyTypeBytes an array of the key types on client-mode or {@code null} on server-mode.
* @param asn1DerEncodedPrincipals the principals or {@code null}.
*
*/
void handle(long ssl, byte[] keyTypeBytes, byte[][] asn1DerEncodedPrincipals) throws Exception;
}
......@@ -21,21 +21,24 @@ package io.netty.internal.tcnative;
* IMPORTANT: Implementations of this interface should be static as it is stored as a global reference via JNI. This
* means if you use an inner / anonymous class to implement this and also depend on the finalizer of the
* class to free up the SSLContext the finalizer will never run as the object is never GC, due the hard
* reference to the enclosing class. This will most likely result in a memory leak.
* reference to the enclosing class. This will most likely result in a memory leak.+
*
* @deprecated use {@link CertificateCallback}
*/
@Deprecated
public interface CertificateRequestedCallback {
/**
* The types contained in the {@code keyTypeBytes} array.
*/
// Extracted from https://github.com/openssl/openssl/blob/master/include/openssl/tls1.h
byte TLS_CT_RSA_SIGN = 1;
byte TLS_CT_DSS_SIGN = 2;
byte TLS_CT_RSA_FIXED_DH = 3;
byte TLS_CT_DSS_FIXED_DH = 4;
byte TLS_CT_ECDSA_SIGN = 64;
byte TLS_CT_RSA_FIXED_ECDH = 65;
byte TLS_CT_ECDSA_FIXED_ECDH = 66;
byte TLS_CT_RSA_SIGN = CertificateCallback.TLS_CT_RSA_SIGN;
byte TLS_CT_DSS_SIGN = CertificateCallback.TLS_CT_DSS_SIGN;
byte TLS_CT_RSA_FIXED_DH = CertificateCallback.TLS_CT_RSA_FIXED_DH;
byte TLS_CT_DSS_FIXED_DH = CertificateCallback.TLS_CT_DSS_FIXED_DH;
byte TLS_CT_ECDSA_SIGN = CertificateCallback.TLS_CT_ECDSA_SIGN;
byte TLS_CT_RSA_FIXED_ECDH = CertificateCallback.TLS_CT_RSA_FIXED_ECDH;
byte TLS_CT_ECDSA_FIXED_ECDH = CertificateCallback.TLS_CT_ECDSA_FIXED_ECDH;
/**
* Called during cert selection. If a certificate chain / key should be used
......
......@@ -40,6 +40,7 @@ final class NativeStaticallyReferencedJniMethods {
static native int sslOpNoTLSv1();
static native int sslOpNoTLSv11();
static native int sslOpNoTLSv12();
static native int sslOpNoTLSv13();
static native int sslOpNoTicket();
/**
......
......@@ -50,9 +50,10 @@ public final class SSL {
public static final int SSL_PROTOCOL_TLSV1 = (1<<2);
public static final int SSL_PROTOCOL_TLSV1_1 = (1<<3);
public static final int SSL_PROTOCOL_TLSV1_2 = (1<<4);
public static final int SSL_PROTOCOL_TLSV1_3 = (1<<5);
/** TLS_*method according to <a href="https://www.openssl.org/docs/man1.0.2/ssl/SSL_CTX_new.html">SSL_CTX_new</a> */
public static final int SSL_PROTOCOL_TLS = (SSL_PROTOCOL_SSLV3 | SSL_PROTOCOL_TLSV1 | SSL_PROTOCOL_TLSV1_1 | SSL_PROTOCOL_TLSV1_2);
public static final int SSL_PROTOCOL_TLS = (SSL_PROTOCOL_SSLV3 | SSL_PROTOCOL_TLSV1 | SSL_PROTOCOL_TLSV1_1 | SSL_PROTOCOL_TLSV1_2 | SSL_PROTOCOL_TLSV1_3);
public static final int SSL_PROTOCOL_ALL = (SSL_PROTOCOL_SSLV2 | SSL_PROTOCOL_TLS);
/*
......@@ -69,6 +70,7 @@ public final class SSL {
public static final int SSL_OP_NO_TLSv1 = sslOpNoTLSv1();
public static final int SSL_OP_NO_TLSv1_1 = sslOpNoTLSv11();
public static final int SSL_OP_NO_TLSv1_2 = sslOpNoTLSv12();
public static final int SSL_OP_NO_TLSv1_3 = sslOpNoTLSv13();
public static final int SSL_OP_NO_TICKET = sslOpNoTicket();
public static final int SSL_OP_NO_COMPRESSION = sslOpNoCompression();
......@@ -500,10 +502,33 @@ public final class SSL {
* @param ciphers an SSL cipher specification
* @return {@code true} if successful
* @throws Exception if an error happened
* @deprecated Use {@link #setCipherSuites(long, String, boolean)}
*/
public static native boolean setCipherSuites(long ssl, String ciphers)
throws Exception;
@Deprecated
public static boolean setCipherSuites(long ssl, String ciphers)
throws Exception {
return setCipherSuites(ssl, ciphers, false);
}
/**
* Returns the cipher suites available for negotiation in SSL handshake.
* <p>
* This complex directive uses a colon-separated cipher-spec string consisting
* of OpenSSL cipher specifications to configure the Cipher Suite the client
* is permitted to negotiate in the SSL handshake phase. Notice that this
* directive can be used both in per-server and per-directory context.
* In per-server context it applies to the standard SSL handshake when a
* connection is established. In per-directory context it forces a SSL
* renegotiation with the reconfigured Cipher Suite after the HTTP request
* was read but before the HTTP response is sent.
* @param ssl the SSL instance (SSL *)
* @param ciphers an SSL cipher specification
* @param tlsv13 {@code true} if the ciphers are for TLSv1.3
* @return {@code true} if successful
* @throws Exception if an error happened
*/
public static native boolean setCipherSuites(long ssl, String ciphers, boolean tlsv13)
throws Exception;
/**
* Returns the ID of the session as byte array representation.
*
......@@ -531,7 +556,16 @@ public final class SSL {
* @param ssl the SSL instance (SSL *)
* @param hostname the hostname
*/
public static native void setTlsExtHostName(long ssl, String hostname);
public static void setTlsExtHostName(long ssl, String hostname) {
if (hostname != null && hostname.endsWith(".")) {
// Strip trailing dot if included.
// See https://github.com/netty/netty-tcnative/issues/400
hostname = hostname.substring(0, hostname.length() - 1);
}
setTlsExtHostName0(ssl, hostname);
}
private static native void setTlsExtHostName0(long ssl, String hostname);
/**
* Explicitly control <a href="https://wiki.openssl.org/index.php/Hostname_validation">hostname validation</a>
......@@ -678,15 +712,31 @@ public final class SSL {
* {@link #parseX509Chain(long)} and {@link #parsePrivateKey(long, String)}. It's important to note that the caller
* of the method is responsible to free the passed in chain and key in any case as this method will increment the
* reference count of the chain and key.
*
* @deprecated use {@link #setKeyMaterial(long, long, long)}
*/
@Deprecated
public static void setKeyMaterialServerSide(long ssl, long chain, long key) throws Exception {
setKeyMaterial(ssl, chain, key);
}
/**
* Sets the keymaterial to be used. The passed in chain and key needs to be generated via
* {@link #parseX509Chain(long)} and {@link #parsePrivateKey(long, String)}. It's important to note that the caller
* of the method is responsible to free the passed in chain and key in any case as this method will increment the
* reference count of the chain and key.
*/
public static native void setKeyMaterialServerSide(long ssl, long chain, long key) throws Exception;
public static native void setKeyMaterial(long ssl, long chain, long key) throws Exception;
/**
* Sets the keymaterial to be used for the client side. The passed in chain and key needs to be generated via
* {@link #parseX509Chain(long)} and {@link #parsePrivateKey(long, String)}. It's important to note that the caller
* of the method is responsible to free the passed in chain and key in any case as this method will increment the
* reference count of the chain and key.
*
* @deprecated use {@link #setKeyMaterial(long, long, long)}
*/
@Deprecated
public static native void setKeyMaterialClientSide(long ssl, long x509Out, long pkeyOut, long chain, long key) throws Exception;
/**
......@@ -722,4 +772,21 @@ public final class SSL {
* @throws Exception throws if setting the fips mode failed.
*/
public static native void fipsModeSet(int mode) throws Exception;
/**
* Return the SNI hostname that was sent as part of the SSL Hello.
* @param ssl the SSL instance (SSL *)
* @return the SNI hostname or {@code null} if none was used.
*/
public static native String getSniHostname(long ssl);
/**
* Return the signature algorithms that the remote peer supports or {@code null} if none are supported.
* See <a href="https://www.openssl.org/docs/man1.1.0/ssl/SSL_get_sigalgs.html"> man SSL_get_sigalgs</a> for more details.
* The returned names are generated using {@code OBJ_nid2ln} with the {@code psignhash} as parameter.
*
* @param ssl the SSL instance (SSL *)
* @return the signature algorithms or {@code null}.
*/
public static native String[] getSigAlgs(long ssl);
}
......@@ -110,8 +110,31 @@ public final class SSLContext {
* @param ciphers An SSL cipher specification.
* @return {@code true} if successful
* @throws Exception if an error happened
* @deprecated Use {@link #setCipherSuite(long, String, boolean)}.
*/
public static native boolean setCipherSuite(long ctx, String ciphers) throws Exception;
@Deprecated
public static boolean setCipherSuite(long ctx, String ciphers) throws Exception {
return setCipherSuite(ctx, ciphers, false);
}
/**
* Cipher Suite available for negotiation in SSL handshake.
* <br>
* This complex directive uses a colon-separated cipher-spec string consisting
* of OpenSSL cipher specifications to configure the Cipher Suite the client
* is permitted to negotiate in the SSL handshake phase. Notice that this
* directive can be used both in per-server and per-directory context.
* In per-server context it applies to the standard SSL handshake when a
* connection is established. In per-directory context it forces a SSL
* renegotiation with the reconfigured Cipher Suite after the HTTP request
* was read but before the HTTP response is sent.
* @param ctx Server or Client context to use.
* @param ciphers An SSL cipher specification.
* @param tlsv13 {@code true} if the ciphers are for TLSv1.3
* @return {@code true} if successful
* @throws Exception if an error happened
*/
public static native boolean setCipherSuite(long ctx, String ciphers, boolean tlsv13) throws Exception;
/**
* Set File of PEM-encoded Server CA Certificates
......@@ -486,6 +509,15 @@ public final class SSLContext {
*/
public static native void setCertRequestedCallback(long ctx, CertificateRequestedCallback callback);
/**
* Allow to hook {@link CertificateCallback} into the certificate choosing process.
* This will call {@code SSL_CTX_set_cert_cb} and so replace the default verification
* callback used by openssl
* @param ctx Server or Client context to use.
* @param callback the callback to call during certificate selection.
*/
public static native void setCertificateCallback(long ctx, CertificateCallback callback);
/**
* Allow to hook {@link SniHostNameMatcher} into the sni processing.
* This will call {@code SSL_CTX_set_tlsext_servername_callback} and so replace the default
......@@ -565,4 +597,9 @@ public final class SSLContext {
* <p><a href="https://commondatastorage.googleapis.com/chromium-boringssl-docs/ssl.h.html">Search for OCSP</a>
*/
public static native void disableOcsp(long ctx);
/**
* Returns the {@code SSL_CTX}.
*/
public static native long getSslCtx(long ctx);
}
......@@ -19,7 +19,7 @@
<parent>
<groupId>io.netty</groupId>
<artifactId>netty-tcnative-parent</artifactId>
<version>2.0.15.Final</version>
<version>2.0.20.Final</version>
</parent>
<artifactId>netty-tcnative-openssl-static</artifactId>
<packaging>jar</packaging>
......@@ -51,30 +51,19 @@
</configuration>
</plugin>
<!-- Configure the distribution statically linked against OpenSSL and APR -->
<plugin>
<groupId>org.fusesource.hawtjni</groupId>
<artifactId>maven-hawtjni-plugin</artifactId>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>build-native-lib</id>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
<goal>build</goal>
<goal>add-source</goal>
</goals>
<phase>compile</phase>
<configuration>
<name>netty_tcnative</name>
<nativeSourceDirectory>${project.basedir}/src/main/c</nativeSourceDirectory>
<libDirectory>${nativeLibOnlyDir}</libDirectory>
<forceAutogen>${forceAutogen}</forceAutogen>
<forceConfigure>${forceConfigure}</forceConfigure>
<windowsBuildTool>msbuild</windowsBuildTool>
<configureArgs>
<configureArg>--with-ssl=${sslHome}</configureArg>
<configureArg>--with-apr=${aprHome}</configureArg>
<configureArg>--with-static-libs</configureArg>
</configureArgs>
<sources>
<source>${generatedSourcesDir}/java</source>
</sources>
</configuration>
</execution>
</executions>
......@@ -106,6 +95,36 @@
</execution>
</executions>
</plugin>
<!-- Configure the distribution statically linked against OpenSSL and APR -->
<plugin>
<groupId>org.fusesource.hawtjni</groupId>
<artifactId>maven-hawtjni-plugin</artifactId>
<executions>
<execution>
<id>build-native-lib</id>
<goals>
<goal>generate</goal>
<goal>build</goal>
</goals>
<phase>compile</phase>
<configuration>
<name>netty_tcnative</name>
<nativeSourceDirectory>${generatedSourcesDir}/c</nativeSourceDirectory>
<customPackageDirectory>${generatedSourcesDir}/native-package</customPackageDirectory>
<libDirectory>${nativeLibOnlyDir}</libDirectory>
<forceAutogen>${forceAutogen}</forceAutogen>
<forceConfigure>${forceConfigure}</forceConfigure>
<windowsBuildTool>msbuild</windowsBuildTool>
<configureArgs>
<configureArg>--with-ssl=${sslHome}</configureArg>
<configureArg>--with-apr=${aprHome}</configureArg>
<configureArg>--with-static-libs</configureArg>
</configureArgs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
......@@ -123,7 +142,7 @@
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>build-openssl</id>
<id>source-openssl</id>
<phase>generate-sources</phase>
<goals>
<goal>run</goal>
......@@ -133,6 +152,14 @@
<!-- Add the ant tasks from ant-contrib -->
<taskdef resource="net/sf/antcontrib/antcontrib.properties" />
<if>
<available file="${opensslBuildDir}" />
<then>
<echo message="OpenSSL was already downloaded, skipping the build step." />
</then>
<else>
<echo message="Downloading OpenSSL" />
<!-- Download the openssl source. -->
<ftp action="get" server="ftp.openssl.org" remotedir="source" userid="anonymous" password="anonymous" passive="yes" verbose="yes">
<fileset dir="${project.build.directory}">
......@@ -149,6 +176,30 @@
<checksum file="${project.build.directory}/openssl-${opensslVersion}.tar.gz" algorithm="SHA-256" property="${opensslSha256}" verifyProperty="isEqual" />
<gunzip src="${project.build.directory}/openssl-${opensslVersion}.tar.gz" dest="${project.build.directory}/" />
<untar src="${project.build.directory}/openssl-${opensslVersion}.tar" dest="${project.build.directory}/" />
</else>
</if>
</target>
</configuration>
</execution>
<execution>
<id>build-openssl</id>
<phase>compile</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<!-- Add the ant tasks from ant-contrib -->
<taskdef resource="net/sf/antcontrib/antcontrib.properties" />
<if>
<available file="${sslHome}" />
<then>
<echo message="OpenSSL was already build, skipping the build step." />
</then>
<else>
<echo message="Building OpenSSL" />
<!-- Build for the correct platform -->
<pathconvert property="sslHomePath" targetos="windows">
......@@ -175,6 +226,8 @@
</exec>
</else>
</if>
</else>
</if>
</target>
</configuration>
</execution>
......@@ -196,7 +249,7 @@
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>build-openssl</id>
<id>source-openssl</id>
<phase>generate-sources</phase>
<goals>
<goal>run</goal>
......@@ -206,6 +259,14 @@
<!-- Add the ant tasks from ant-contrib -->
<taskdef resource="net/sf/antcontrib/antcontrib.properties" />
<if>
<available file="${opensslBuildDir}" />
<then>
<echo message="OpenSSL was already downloaded, skipping the build step." />
</then>
<else>
<echo message="Downloading OpenSSL" />
<!-- Download the openssl source. -->
<ftp action="get" server="ftp.openssl.org" remotedir="source" userid="anonymous" password="anonymous" passive="yes" verbose="yes">
<fileset dir="${project.build.directory}">
......@@ -223,7 +284,30 @@
<exec executable="tar" failonerror="true" dir="${project.build.directory}/" resolveexecutable="true">
<arg line="xfvz openssl-${opensslVersion}.tar.gz" />
</exec>
</else>
</if>
</target>
</configuration>
</execution>
<execution>
<id>build-openssl</id>
<phase>compile</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<!-- Add the ant tasks from ant-contrib -->
<taskdef resource="net/sf/antcontrib/antcontrib.properties" />
<if>
<available file="${sslHome}" />
<then>
<echo message="OpenSSL was already build, skipping the build step." />
</then>
<else>
<echo message="Building OpenSSL" />
<mkdir dir="${sslHome}" />
<exec executable="config" failonerror="true" dir="${opensslBuildDir}" resolveexecutable="true">
<arg line="-O3 -fno-omit-frame-pointer -fPIC no-ssl2 no-ssl3 no-shared no-comp -DOPENSSL_NO_HEARTBEATS --prefix=${sslHome} --openssldir=${sslHome}" />
......@@ -233,8 +317,11 @@
</exec>
<exec executable="make" failonerror="true" dir="${opensslBuildDir}" resolveexecutable="true" />
<exec executable="make" failonerror="true" dir="${opensslBuildDir}" resolveexecutable="true">
<arg value="install" />
<!-- Don't install manpages to make things as fast a possible -->
<arg value="install_sw" />
</exec>
</else>
</if>
</target>
</configuration>
</execution>
......@@ -256,7 +343,7 @@
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>build-openssl</id>
<id>source-openssl</id>
<phase>generate-sources</phase>
<goals>
<goal>run</goal>
......@@ -266,6 +353,14 @@
<!-- Add the ant tasks from ant-contrib -->
<taskdef resource="net/sf/antcontrib/antcontrib.properties" />
<if>
<available file="${opensslBuildDir}" />
<then>
<echo message="OpenSSL was already downloaded, skipping the build step." />
</then>
<else>
<echo message="Downloading OpenSSL" />
<!-- Download the openssl source. -->
<ftp action="get" server="ftp.openssl.org" remotedir="source" userid="anonymous" password="anonymous" passive="yes" verbose="yes">
<fileset dir="${project.build.directory}">
......@@ -283,7 +378,29 @@
<exec executable="tar" failonerror="true" dir="${project.build.directory}/" resolveexecutable="true">
<arg line="xfvz openssl-${opensslVersion}.tar.gz" />
</exec>
</else>
</if>
</target>
</configuration>
</execution>
<execution>
<id>build-openssl</id>
<phase>compile</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<!-- Add the ant tasks from ant-contrib -->
<taskdef resource="net/sf/antcontrib/antcontrib.properties" />
<if>
<available file="${sslHome}" />
<then>
<echo message="OpenSSL was already build, skipping the build step." />
</then>
<else>
<echo message="Building OpenSSL" />
<mkdir dir="${sslHome}" />
<exec executable="Configure" failonerror="true" dir="${opensslBuildDir}" resolveexecutable="true">
<arg line="darwin64-x86_64-cc -O3 -fno-omit-frame-pointer -fPIC no-ssl2 no-ssl3 no-shared no-comp -DOPENSSL_NO_HEARTBEATS --prefix=${sslHome} --openssldir=${sslHome}" />
......@@ -293,8 +410,11 @@
</exec>
<exec executable="make" failonerror="true" dir="${opensslBuildDir}" resolveexecutable="true" />
<exec executable="make" failonerror="true" dir="${opensslBuildDir}" resolveexecutable="true">
<arg value="install" />
<!-- Don't install manpages to make things as fast a possible -->
<arg value="install_sw" />
</exec>
</else>
</if>
</target>
</configuration>
</execution>
......
......@@ -19,10 +19,10 @@
<parent>
<groupId>io.netty</groupId>
<artifactId>netty-parent</artifactId>
<version>4.0.18.Final</version>
<version>4.0.29.Final</version>
</parent>
<artifactId>netty-tcnative-parent</artifactId>
<version>2.0.15.Final</version>
<version>2.0.20.Final</version>
<packaging>pom</packaging>
<name>Netty/TomcatNative [Parent]</name>
......@@ -35,11 +35,15 @@
<url>https://github.com/netty/netty-tcnative</url>
<connection>scm:git:git://github.com/netty/netty-tcnative.git</connection>
<developerConnection>scm:git:ssh://git@github.com/netty/netty-tcnative.git</developerConnection>
<tag>netty-tcnative-parent-2.0.15.Final</tag>
<tag>netty-tcnative-parent-2.0.20.Final</tag>
</scm>
<properties>
<checkstyle.skip>true</checkstyle.skip>
<enforcer.plugin.version>1.4.1</enforcer.plugin.version>
<maven.compiler.source>1.6</maven.compiler.source>
<maven.compiler.target>1.6</maven.compiler.target>
<netty.build.version>22</netty.build.version>
<animal.sniffer.skip>true</animal.sniffer.skip>
<forceAutogen>false</forceAutogen>
<forceConfigure>false</forceConfigure>
......@@ -49,8 +53,8 @@
<nativeJarFile>${project.build.directory}/${project.build.finalName}-${os.detected.classifier}.jar</nativeJarFile>
<nativeLibOnlyDir>${project.build.directory}/native-lib-only</nativeLibOnlyDir>
<nativeJarWorkdir>${project.build.directory}/native-jar-work</nativeJarWorkdir>
<aprVersion>1.6.3</aprVersion>
<aprMd5>57c6cc26a31fe420c546ad2234f22db4</aprMd5>
<aprVersion>1.6.5</aprVersion>
<aprSha256>70dcf9102066a2ff2ffc47e93c289c8e54c95d8dda23b503f9e61bb0cbd2d105</aprSha256>
<boringsslBranch>chromium-stable</boringsslBranch>
<libresslVersion>2.7.4</libresslVersion>
<!--
......@@ -65,10 +69,10 @@
- Record the sha256: sha1sum -a 256 libressl-{libresslVersion}.tar.gz (shasum on osx)
-->
<libresslSha256>1e3a9fada06c1c060011470ad0ff960de28f9a0515277d7336f7e09362517da6</libresslSha256>
<opensslMinorVersion>1.1.0</opensslMinorVersion>
<opensslPatchVersion>i</opensslPatchVersion>
<opensslMinorVersion>1.1.1</opensslMinorVersion>
<opensslPatchVersion />
<opensslVersion>${opensslMinorVersion}${opensslPatchVersion}</opensslVersion>
<opensslSha256>50a98e07b1a89eb8f6a99477f262df71c6fa7bef77df4dc83025a2845c827d00</opensslSha256>
<opensslSha256>2836875a0f89c03d0fdf483941512613a50cfb421d6fd94b9f41d7279d586a3d</opensslSha256>
<aprHome>${project.build.directory}/apr</aprHome>
<aprBuildDir>${project.build.directory}/apr-${aprVersion}</aprBuildDir>
<archBits>64</archBits>
......@@ -78,6 +82,7 @@
<msvcSslLibDirs>${sslHome}/lib</msvcSslLibDirs>
<msvcSslLibs>libssl.lib;libcrypto.lib</msvcSslLibs>
<strip.skip>false</strip.skip>
<generatedSourcesDir>${project.build.directory}/generated-sources</generatedSourcesDir>
</properties>
<build>
......@@ -146,12 +151,34 @@
</pluginManagement>
<plugins>
<!-- Recent tcnative requires JDK 1.7 to build -->
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration combine.self="override">
<includes>
<include>**/*Test*.java</include>
<include>**/*Benchmark*.java</include>
</includes>
<excludes>
<exclude>**/Abstract*</exclude>
<exclude>**/*TestUtil*</exclude>
</excludes>
<runOrder>random</runOrder>
<properties>
<property>
<name>listener</name>
<value>io.netty.build.junit.TimedOutTestsListener</value>
</property>
</properties>
<!-- Ensure the whole stacktrace is preserved when an exception is thrown. See https://issues.apache.org/jira/browse/SUREFIRE-1457 -->
<trimStackTrace>false</trimStackTrace>
</configuration>
</plugin>
......@@ -170,8 +197,8 @@
<!-- Copy all of the code from the dynamic module -->
<delete dir="src" quiet="true" />
<mkdir dir="src" />
<copy todir="${basedir}/src" verbose="true">
<fileset dir="${opensslDynamicDir}/src" />
<copy todir="${generatedSourcesDir}" verbose="true">
<fileset dir="${opensslDynamicDir}/src/main" />
</copy>
<!-- Convert the paths to windows format -->
......@@ -199,7 +226,7 @@
<filter token="SSL_INCLUDE_DIRS" value="${sslIncludeDirsWindowsPath}" />
<filter token="SSL_LIB_DIR" value="${sslLibDirsWindowsPath}" />
<filter token="SSL_LIBS" value="${msvcSslLibs}" />
<copy file="${vsStaticTemplateFile}" tofile="src/main/native-package/vs2010.vcxproj" filtering="true" overwrite="true" verbose="true" />
<copy file="${vsStaticTemplateFile}" tofile="${generatedSourcesDir}/native-package/vs2010.vcxproj" filtering="true" overwrite="true" verbose="true" />
</target>
</configuration>
</execution>
......@@ -270,6 +297,7 @@
<plugin>
<artifactId>maven-enforcer-plugin</artifactId>
<version>${enforcer.plugin.version}</version>
<executions>
<execution>
<id>enforce-tools</id>
......@@ -289,6 +317,14 @@
</plugins>
</build>
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-build</artifactId>
<version>${netty.build.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<profiles>
<profile>
<id>disable-autogen-windows</id>
......@@ -313,19 +349,57 @@
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>build-apr</id>
<id>source-apr</id>
<phase>generate-sources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target name="build-apr" if="${linkStatic}">
<target if="${linkStatic}">
<!-- Add the ant tasks from ant-contrib -->
<taskdef resource="net/sf/antcontrib/antcontrib.properties" />
<if>
<available file="${aprBuildDir}" />
<then>
<echo message="APR was already downloaded, skipping the build step." />
</then>
<else>
<echo message="Downloading APR" />
<property name="aprArchiveFile" value="apr-${aprVersion}-win32-src.zip" />
<get src="http://archive.apache.org/dist/apr/${aprArchiveFile}" dest="${project.build.directory}/${aprArchiveFile}" verbose="on" />
<unzip src="${project.build.directory}/${aprArchiveFile}" dest="${project.build.directory}" />
<condition property="windowsRelease" value="Win32 Release" else="x64 Release">
<equals arg1="${archBits}" arg2="32" />
</condition>
</else>
</if>
</target>
</configuration>
</execution>
<execution>
<id>build-apr</id>
<phase>compile</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target if="${linkStatic}">
<!-- Add the ant tasks from ant-contrib -->
<taskdef resource="net/sf/antcontrib/antcontrib.properties" />
<if>
<available file="${aprHome}" />
<then>
<echo message="APR was already build, skipping the build step." />
</then>
<else>
<echo message="Building APR" />
<condition property="windowsRelease" value="Win32 Release" else="x64 Release">
<equals arg1="${archBits}" arg2="32" />
</condition>
<echo message="archBits=${archBits}. Using windowsRelease=${windowsRelease}" />
<!-- On Windows, force building APR with /MT for static linking -->
<replace dir="${aprBuildDir}" token="/MD" value="/MT">
......@@ -342,6 +416,8 @@
<copy todir="${aprHome}">
<fileset dir="${aprBuildDir}/include/arch" includes="*.h" />
</copy>
</else>
</if>
</target>
</configuration>
</execution>
......@@ -363,22 +439,56 @@
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>build-apr-linux-mac</id>
<id>source-apr-linux-mac</id>
<phase>generate-sources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target if="${linkStatic}">
<!-- Add the ant tasks from ant-contrib -->
<taskdef resource="net/sf/antcontrib/antcontrib.properties" />
<if>
<available file="${aprBuildDir}" />
<then>
<echo message="APR was already downloaded, skipping the build step." />
</then>
<else>
<echo message="Downloading and unpacking APR" />
<property name="aprTarGzFile" value="apr-${aprVersion}.tar.gz" />
<property name="aprTarFile" value="apr-${aprVersion}.tar" />
<get src="http://archive.apache.org/dist/apr/${aprTarGzFile}" dest="${project.build.directory}/${aprTarGzFile}" verbose="on" />
<checksum file="${project.build.directory}/${aprTarGzFile}" algorithm="MD5" property="${aprMd5}" verifyProperty="isEqual" />
<checksum file="${project.build.directory}/${aprTarGzFile}" algorithm="SHA-256" property="${aprSha256}" verifyProperty="isEqual" />
<gunzip src="${project.build.directory}/${aprTarGzFile}" dest="${project.build.directory}" />
<!-- Use the tar command (rather than the untar ant task) in order to preserve file permissions. -->
<exec executable="tar" failonerror="true" dir="${project.build.directory}/" resolveexecutable="true">
<arg line="xfvz ${aprTarGzFile}" />
</exec>
</else>
</if>
</target>
</configuration>
</execution>
<execution>
<id>build-apr-linux-mac</id>
<phase>compile</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target if="${linkStatic}">
<!-- Add the ant tasks from ant-contrib -->
<taskdef resource="net/sf/antcontrib/antcontrib.properties" />
<if>
<available file="${aprHome}" />
<then>
<echo message="APR was already build, skipping the build step." />
</then>
<else>
<echo message="Building APR" />
<mkdir dir="${aprHome}" />
<exec executable="configure" failonerror="true" dir="${aprBuildDir}" resolveexecutable="true">
<arg line="--disable-shared --prefix=${aprHome} CFLAGS='-O3 -fno-omit-frame-pointer -fPIC'" />
......@@ -387,6 +497,8 @@
<exec executable="make" failonerror="true" dir="${aprBuildDir}" resolveexecutable="true">
<arg line="install" />
</exec>
</else>
</if>
</target>
</configuration>
</execution>
......@@ -444,7 +556,7 @@
<dependency>
<groupId>com.ceilfors.maven.plugin</groupId>
<artifactId>enforcer-rules</artifactId>
<version>1.1.0</version>
<version>1.2.0</version>
</dependency>
</dependencies>
</plugin>
......@@ -475,5 +587,53 @@
<module>libressl-static</module>
</modules>
</profile>
<profile>
<id>java9</id>
<activation>
<jdk>9</jdk>
</activation>
<properties>
<!-- Needed because of https://issues.apache.org/jira/browse/MENFORCER-275 -->
<enforcer.plugin.version>3.0.0-M1</enforcer.plugin.version>
</properties>
</profile>
<profile>
<id>java10</id>
<activation>
<jdk>10</jdk>
</activation>
<properties>
<!-- Needed because of https://issues.apache.org/jira/browse/MENFORCER-275 -->
<enforcer.plugin.version>3.0.0-M1</enforcer.plugin.version>
</properties>
</profile>
<profile>
<id>java11</id>
<activation>
<jdk>11</jdk>
</activation>
<properties>
<!-- Needed because of https://issues.apache.org/jira/browse/MENFORCER-275 -->
<enforcer.plugin.version>3.0.0-M1</enforcer.plugin.version>
</properties>
</profile>
<profile>
<id>java12</id>
<activation>
<jdk>12</jdk>
</activation>
<properties>
<!-- Needed because of https://issues.apache.org/jira/browse/MENFORCER-275 -->
<enforcer.plugin.version>3.0.0-M1</enforcer.plugin.version>
<!-- This is the minimum supported by Java12 -->
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
</profile>
</profiles>
</project>