Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3890)

Unified Diff: c/sslcontext.c

Issue 2842333002: Updated netty-tcnative to version 2.0.0.Final (Closed)
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « c/ssl_private.h ('k') | c/sslinfo.c » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: c/sslcontext.c
diff --git a/c/sslcontext.c b/c/sslcontext.c
index 2f42eb459d070704a55f34c231b582f2807cde91..25bfb6e97977100f5c99f5772d27a675a42f9b3d 100644
--- a/c/sslcontext.c
+++ b/c/sslcontext.c
@@ -1,3 +1,18 @@
+/*
+ * Copyright 2016 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.
+ */
/* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
@@ -14,23 +29,15 @@
* limitations under the License.
*/
-/** SSL Context wrapper
- *
- * @author Mladen Turk
- * @version $Id: sslcontext.c 1649733 2015-01-06 04:42:24Z billbarker $
- */
-
#include "tcn.h"
-#include "apr_file_io.h"
-#include "apr_thread_mutex.h"
#include "apr_thread_rwlock.h"
-#include "apr_poll.h"
+#include "apr_atomic.h"
-#ifdef HAVE_OPENSSL
#include "ssl_private.h"
+#include <stdint.h>
-static jclass byteArrayClass;
+extern apr_pool_t *tcn_global_pool;
static apr_status_t ssl_context_cleanup(void *data)
{
@@ -38,46 +45,30 @@ static apr_status_t ssl_context_cleanup(void *data)
JNIEnv *e;
if (c) {
- int i;
- if (c->crl)
- X509_STORE_free(c->crl);
- c->crl = NULL;
- if (c->ctx)
- SSL_CTX_free(c->ctx);
+ SSL_CTX_free(c->ctx); // this function is safe to call with NULL
c->ctx = NULL;
- for (i = 0; i < SSL_AIDX_MAX; i++) {
- if (c->certs[i]) {
- X509_free(c->certs[i]);
- c->certs[i] = NULL;
- }
- if (c->keys[i]) {
- EVP_PKEY_free(c->keys[i]);
- c->keys[i] = NULL;
- }
- }
- if (c->bio_is) {
- SSL_BIO_close(c->bio_is);
- c->bio_is = NULL;
- }
- if (c->bio_os) {
- SSL_BIO_close(c->bio_os);
- c->bio_os = NULL;
- }
- if (c->verifier) {
+ if (c->verifier != NULL) {
tcn_get_java_env(&e);
(*e)->DeleteGlobalRef(e, c->verifier);
c->verifier = NULL;
}
c->verifier_method = NULL;
- if (c->next_proto_data) {
+ if (c->cert_requested_callback != NULL) {
+ tcn_get_java_env(&e);
+ (*e)->DeleteGlobalRef(e, c->cert_requested_callback);
+ c->cert_requested_callback = NULL;
+ }
+ c->cert_requested_callback_method = NULL;
+
+ if (c->next_proto_data != NULL) {
free(c->next_proto_data);
c->next_proto_data = NULL;
}
c->next_proto_len = 0;
- if (c->alpn_proto_data) {
+ if (c->alpn_proto_data != NULL) {
free(c->alpn_proto_data);
c->alpn_proto_data = NULL;
}
@@ -85,28 +76,41 @@ static apr_status_t ssl_context_cleanup(void *data)
apr_thread_rwlock_destroy(c->mutex);
- if (c->ticket_keys) {
+ if (c->ticket_keys != NULL) {
free(c->ticket_keys);
c->ticket_keys = NULL;
}
c->ticket_keys_len = 0;
+
+ if (c->password != NULL) {
+ free(c->password);
+ c->password = NULL;
+ }
}
return APR_SUCCESS;
}
/* Initialize server context */
-TCN_IMPLEMENT_CALL(jlong, SSLContext, make)(TCN_STDARGS, jlong pool,
- jint protocol, jint mode)
+TCN_IMPLEMENT_CALL(jlong, SSLContext, make)(TCN_STDARGS, jint protocol, jint mode)
{
- apr_pool_t *p = J2P(pool, apr_pool_t *);
+ apr_pool_t *p = NULL;
tcn_ssl_ctxt_t *c = NULL;
SSL_CTX *ctx = NULL;
- jclass clazz;
UNREFERENCED(o);
- if (protocol == SSL_PROTOCOL_TLSV1_2) {
-#ifdef SSL_OP_NO_TLSv1_2
+ switch (protocol) {
+ case SSL_PROTOCOL_TLS:
+ case SSL_PROTOCOL_ALL:
+ if (mode == SSL_MODE_CLIENT)
+ ctx = SSL_CTX_new(SSLv23_client_method());
+ else if (mode == SSL_MODE_SERVER)
+ ctx = SSL_CTX_new(SSLv23_server_method());
+ else
+ ctx = SSL_CTX_new(SSLv23_method());
+ break;
+ case SSL_PROTOCOL_TLSV1_2:
+#ifndef OPENSSL_NO_TLS1
if (mode == SSL_MODE_CLIENT)
ctx = SSL_CTX_new(TLSv1_2_client_method());
else if (mode == SSL_MODE_SERVER)
@@ -114,8 +118,9 @@ TCN_IMPLEMENT_CALL(jlong, SSLContext, make)(TCN_STDARGS, jlong pool,
else
ctx = SSL_CTX_new(TLSv1_2_method());
#endif
- } else if (protocol == SSL_PROTOCOL_TLSV1_1) {
-#ifdef SSL_OP_NO_TLSv1_1
+ break;
+ case SSL_PROTOCOL_TLSV1_1:
+#ifndef OPENSSL_NO_TLS1
if (mode == SSL_MODE_CLIENT)
ctx = SSL_CTX_new(TLSv1_1_client_method());
else if (mode == SSL_MODE_SERVER)
@@ -123,15 +128,19 @@ TCN_IMPLEMENT_CALL(jlong, SSLContext, make)(TCN_STDARGS, jlong pool,
else
ctx = SSL_CTX_new(TLSv1_1_method());
#endif
- } else if (protocol == SSL_PROTOCOL_TLSV1) {
+ break;
+ case SSL_PROTOCOL_TLSV1:
+#ifndef OPENSSL_NO_TLS1
if (mode == SSL_MODE_CLIENT)
ctx = SSL_CTX_new(TLSv1_client_method());
else if (mode == SSL_MODE_SERVER)
ctx = SSL_CTX_new(TLSv1_server_method());
else
ctx = SSL_CTX_new(TLSv1_method());
+#endif
+ break;
+ case SSL_PROTOCOL_SSLV3:
#ifndef OPENSSL_NO_SSL3
- } else if (protocol == SSL_PROTOCOL_SSLV3) {
if (mode == SSL_MODE_CLIENT)
ctx = SSL_CTX_new(SSLv3_client_method());
else if (mode == SSL_MODE_SERVER)
@@ -139,8 +148,9 @@ TCN_IMPLEMENT_CALL(jlong, SSLContext, make)(TCN_STDARGS, jlong pool,
else
ctx = SSL_CTX_new(SSLv3_method());
#endif
+ break;
+ case SSL_PROTOCOL_SSLV2:
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) && !defined(OPENSSL_NO_SSL2)
- } else if (protocol == SSL_PROTOCOL_SSLV2) {
if (mode == SSL_MODE_CLIENT)
ctx = SSL_CTX_new(SSLv2_client_method());
else if (mode == SSL_MODE_SERVER)
@@ -148,40 +158,80 @@ TCN_IMPLEMENT_CALL(jlong, SSLContext, make)(TCN_STDARGS, jlong pool,
else
ctx = SSL_CTX_new(SSLv2_method());
#endif
-#ifndef SSL_OP_NO_TLSv1_2
- } else if (protocol & SSL_PROTOCOL_TLSV1_2) {
- /* requested but not supported */
+ break;
+ default:
+ // Try to give the user the highest supported protocol.
+#ifndef OPENSSL_NO_TLS1
+ if (protocol & SSL_PROTOCOL_TLSV1_2) {
+ if (mode == SSL_MODE_CLIENT)
+ ctx = SSL_CTX_new(TLSv1_2_client_method());
+ else if (mode == SSL_MODE_SERVER)
+ ctx = SSL_CTX_new(TLSv1_2_server_method());
+ else
+ ctx = SSL_CTX_new(TLSv1_2_method());
+ break;
+ } else if (protocol & SSL_PROTOCOL_TLSV1_1) {
+ if (mode == SSL_MODE_CLIENT)
+ ctx = SSL_CTX_new(TLSv1_1_client_method());
+ else if (mode == SSL_MODE_SERVER)
+ ctx = SSL_CTX_new(TLSv1_1_server_method());
+ else
+ ctx = SSL_CTX_new(TLSv1_1_method());
+ break;
+ } else if (protocol & SSL_PROTOCOL_TLSV1) {
+ if (mode == SSL_MODE_CLIENT)
+ ctx = SSL_CTX_new(TLSv1_client_method());
+ else if (mode == SSL_MODE_SERVER)
+ ctx = SSL_CTX_new(TLSv1_server_method());
+ else
+ ctx = SSL_CTX_new(TLSv1_method());
+ break;
+ }
+#endif
+#ifndef OPENSSL_NO_SSL3
+ if (protocol & SSL_PROTOCOL_SSLV3) {
+ if (mode == SSL_MODE_CLIENT)
+ ctx = SSL_CTX_new(SSLv3_client_method());
+ else if (mode == SSL_MODE_SERVER)
+ ctx = SSL_CTX_new(SSLv3_server_method());
+ else
+ ctx = SSL_CTX_new(SSLv3_method());
+ break;
+ }
#endif
-#ifndef SSL_OP_NO_TLSv1_1
- } else if (protocol & SSL_PROTOCOL_TLSV1_1) {
- /* requested but not supported */
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L) && !defined(OPENSSL_NO_SSL2)
+ if (protocol & SSL_PROTOCOL_SSLV2) {
+ if (mode == SSL_MODE_CLIENT)
+ ctx = SSL_CTX_new(SSLv2_client_method());
+ else if (mode == SSL_MODE_SERVER)
+ ctx = SSL_CTX_new(SSLv2_server_method());
+ else
+ ctx = SSL_CTX_new(SSLv2_method());
+ break;
+ }
#endif
- } else {
- if (mode == SSL_MODE_CLIENT)
- ctx = SSL_CTX_new(SSLv23_client_method());
- else if (mode == SSL_MODE_SERVER)
- ctx = SSL_CTX_new(SSLv23_server_method());
- else
- ctx = SSL_CTX_new(SSLv23_method());
+ tcn_Throw(e, "Unsupported SSL protocol (%d)", protocol);
+ goto cleanup;
}
- if (!ctx) {
+ if (ctx == NULL) {
char err[256];
ERR_error_string(ERR_get_error(), err);
- tcn_Throw(e, "Invalid Server SSL Protocol (%s)", err);
- goto init_failed;
+ tcn_Throw(e, "Failed to initialize SSL_CTX (%s)", err);
+ goto cleanup;
}
+
+ TCN_THROW_IF_ERR(apr_pool_create(&p, tcn_global_pool), p);
+
if ((c = apr_pcalloc(p, sizeof(tcn_ssl_ctxt_t))) == NULL) {
tcn_ThrowAPRException(e, apr_get_os_error());
- goto init_failed;
+ goto cleanup;
}
c->protocol = protocol;
c->mode = mode;
c->ctx = ctx;
c->pool = p;
- c->bio_os = NULL;
- SSL_CTX_set_options(c->ctx, SSL_OP_ALL);
if (!(protocol & SSL_PROTOCOL_SSLV2))
SSL_CTX_set_options(c->ctx, SSL_OP_NO_SSLv2);
if (!(protocol & SSL_PROTOCOL_SSLV3))
@@ -204,28 +254,22 @@ TCN_IMPLEMENT_CALL(jlong, SSLContext, make)(TCN_STDARGS, jlong pool,
SSL_CTX_set_options(c->ctx, SSL_OP_SINGLE_ECDH_USE);
#endif
-#ifdef SSL_OP_NO_COMPRESSION
SSL_CTX_set_options(c->ctx, SSL_OP_NO_COMPRESSION);
-#else
-#error "SSL_OP_NO_COMPRESSION not supported in your version of OpenSSL"
-#endif
-#ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
/*
* Disallow a session from being resumed during a renegotiation,
* so that an acceptable cipher suite can be negotiated.
*/
SSL_CTX_set_options(c->ctx, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
-#else
-#error "SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION not supported in your version of OpenSSL"
-#endif
+ /**
+ * These options may be set by default but can be dangerous in practice [1].
+ * [1] https://www.openssl.org/docs/man1.0.1/ssl/SSL_CTX_set_options.html
+ */
+ SSL_CTX_clear_options(c->ctx, SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION | SSL_OP_LEGACY_SERVER_CONNECT);
-#ifdef SSL_MODE_RELEASE_BUFFERS
/* Release idle buffers to the SSL_CTX free list */
SSL_CTX_set_mode(c->ctx, SSL_MODE_RELEASE_BUFFERS);
-#else
-#error "SSL_MODE_RELEASE_BUFFERS not supported in your version of OpenSSL"
-#endif
+
/* Default session context id and cache size */
SSL_CTX_sess_set_cache_size(c->ctx, SSL_DEFAULT_CACHE_SIZE);
@@ -244,26 +288,16 @@ TCN_IMPLEMENT_CALL(jlong, SSLContext, make)(TCN_STDARGS, jlong pool,
EC_KEY_free(ecdh);
#endif
-// This method should not be used when using libressl as it will result in
-// error:14085042:SSL routines:SSL3_CTX_CTRL:called a function you should not call
-//
-// See also http://forum.nginx.org/read.php?2,256381,257336#msg-257336
-#ifndef LIBRESSL_VERSION_NUMBER
- SSL_CTX_set_tmp_rsa_callback(c->ctx, SSL_callback_tmp_RSA);
-#endif
SSL_CTX_set_tmp_dh_callback(c->ctx, SSL_callback_tmp_DH);
}
- /* Set default Certificate verification level
- * and depth for the Client Authentication
- */
- c->verify_depth = 1;
- c->verify_mode = SSL_CVERIFY_UNSET;
- c->shutdown_type = SSL_SHUTDOWN_TYPE_UNSET;
+
+ // Default depth is 100 and disabled according to https://www.openssl.org/docs/man1.0.2/ssl/SSL_set_verify.html.
+ c->verify_config.verify_depth = 100;
+ c->verify_config.verify_mode = SSL_CVERIFY_NONE;
/* Set default password callback */
SSL_CTX_set_default_passwd_cb(c->ctx, (pem_password_cb *)SSL_password_callback);
- SSL_CTX_set_default_passwd_cb_userdata(c->ctx, (void *)(&tcn_password_callback));
- SSL_CTX_set_info_callback(c->ctx, SSL_callback_handshake);
+ SSL_CTX_set_default_passwd_cb_userdata(c->ctx, (void *) c->password);
apr_thread_rwlock_create(&c->mutex, p);
/*
@@ -273,13 +307,12 @@ TCN_IMPLEMENT_CALL(jlong, SSLContext, make)(TCN_STDARGS, jlong pool,
ssl_context_cleanup,
apr_pool_cleanup_null);
-
- // Cache the byte[].class for performance reasons
- clazz = (*e)->FindClass(e, "[B");
- byteArrayClass = (jclass) (*e)->NewGlobalRef(e, clazz);
-
return P2J(c);
-init_failed:
+cleanup:
+ if (p != NULL) {
+ apr_pool_destroy(p);
+ }
+ SSL_CTX_free(ctx); // this function is safe to call with NULL.
return 0;
}
@@ -289,7 +322,9 @@ TCN_IMPLEMENT_CALL(jint, SSLContext, free)(TCN_STDARGS, jlong ctx)
UNREFERENCED_STDARGS;
TCN_ASSERT(ctx != 0);
/* Run and destroy the cleanup callback */
- return apr_pool_cleanup_run(c->pool, c, ssl_context_cleanup);
+ int result = apr_pool_cleanup_run(c->pool, c, ssl_context_cleanup);
+ apr_pool_destroy(c->pool);
+ return result;
}
TCN_IMPLEMENT_CALL(void, SSLContext, setContextId)(TCN_STDARGS, jlong ctx,
@@ -308,29 +343,6 @@ TCN_IMPLEMENT_CALL(void, SSLContext, setContextId)(TCN_STDARGS, jlong ctx,
TCN_FREE_CSTRING(id);
}
-TCN_IMPLEMENT_CALL(void, SSLContext, setBIO)(TCN_STDARGS, jlong ctx,
- jlong bio, jint dir)
-{
- tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
- BIO *bio_handle = J2P(bio, BIO *);
-
- UNREFERENCED_STDARGS;
- TCN_ASSERT(ctx != 0);
- if (dir == 0) {
- if (c->bio_os && c->bio_os != bio_handle)
- SSL_BIO_close(c->bio_os);
- c->bio_os = bio_handle;
- }
- else if (dir == 1) {
- if (c->bio_is && c->bio_is != bio_handle)
- SSL_BIO_close(c->bio_is);
- c->bio_is = bio_handle;
- }
- else
- return;
- SSL_BIO_doref(bio_handle);
-}
-
TCN_IMPLEMENT_CALL(void, SSLContext, setOptions)(TCN_STDARGS, jlong ctx,
jint opt)
{
@@ -338,11 +350,7 @@ TCN_IMPLEMENT_CALL(void, SSLContext, setOptions)(TCN_STDARGS, jlong ctx,
UNREFERENCED_STDARGS;
TCN_ASSERT(ctx != 0);
-#ifndef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
- /* Clear the flag if not supported */
- if (opt & 0x00040000)
- opt &= ~0x00040000;
-#endif
+
SSL_CTX_set_options(c->ctx, opt);
}
@@ -366,16 +374,6 @@ TCN_IMPLEMENT_CALL(void, SSLContext, clearOptions)(TCN_STDARGS, jlong ctx,
SSL_CTX_clear_options(c->ctx, opt);
}
-TCN_IMPLEMENT_CALL(void, SSLContext, setQuietShutdown)(TCN_STDARGS, jlong ctx,
- jboolean mode)
-{
- tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
-
- UNREFERENCED_STDARGS;
- TCN_ASSERT(ctx != 0);
- SSL_CTX_set_quiet_shutdown(c->ctx, mode ? 1 : 0);
-}
-
TCN_IMPLEMENT_CALL(jboolean, SSLContext, setCipherSuite)(TCN_STDARGS, jlong ctx,
jstring ciphers)
{
@@ -398,55 +396,6 @@ TCN_IMPLEMENT_CALL(jboolean, SSLContext, setCipherSuite)(TCN_STDARGS, jlong ctx,
return rv;
}
-TCN_IMPLEMENT_CALL(jboolean, SSLContext, setCARevocation)(TCN_STDARGS, jlong ctx,
- jstring file,
- jstring path)
-{
- tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
- TCN_ALLOC_CSTRING(file);
- TCN_ALLOC_CSTRING(path);
- jboolean rv = JNI_FALSE;
- X509_LOOKUP *lookup;
- char err[256];
-
- UNREFERENCED(o);
- TCN_ASSERT(ctx != 0);
- if (J2S(file) == NULL && J2S(path) == NULL)
- return JNI_FALSE;
-
- if (!c->crl) {
- if ((c->crl = X509_STORE_new()) == NULL)
- goto cleanup;
- }
- if (J2S(file)) {
- lookup = X509_STORE_add_lookup(c->crl, X509_LOOKUP_file());
- if (lookup == NULL) {
- ERR_error_string(ERR_get_error(), err);
- X509_STORE_free(c->crl);
- c->crl = NULL;
- tcn_Throw(e, "Lookup failed for file %s (%s)", J2S(file), err);
- goto cleanup;
- }
- X509_LOOKUP_load_file(lookup, J2S(file), X509_FILETYPE_PEM);
- }
- if (J2S(path)) {
- lookup = X509_STORE_add_lookup(c->crl, X509_LOOKUP_hash_dir());
- if (lookup == NULL) {
- ERR_error_string(ERR_get_error(), err);
- X509_STORE_free(c->crl);
- c->crl = NULL;
- tcn_Throw(e, "Lookup failed for path %s (%s)", J2S(file), err);
- goto cleanup;
- }
- X509_LOOKUP_add_dir(lookup, J2S(path), X509_FILETYPE_PEM);
- }
- rv = JNI_TRUE;
-cleanup:
- TCN_FREE_CSTRING(file);
- TCN_FREE_CSTRING(path);
- return rv;
-}
-
TCN_IMPLEMENT_CALL(jboolean, SSLContext, setCertificateChainFile)(TCN_STDARGS, jlong ctx,
jstring file,
jboolean skipfirst)
@@ -482,215 +431,57 @@ TCN_IMPLEMENT_CALL(jboolean, SSLContext, setCertificateChainBio)(TCN_STDARGS, jl
return JNI_FALSE;
}
-TCN_IMPLEMENT_CALL(jboolean, SSLContext, setCACertificate)(TCN_STDARGS,
- jlong ctx,
- jstring file,
- jstring path)
+TCN_IMPLEMENT_CALL(jboolean, SSLContext, setCACertificateBio)(TCN_STDARGS, jlong ctx, jlong certs)
{
tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
- jboolean rv = JNI_TRUE;
- TCN_ALLOC_CSTRING(file);
- TCN_ALLOC_CSTRING(path);
-
- UNREFERENCED(o);
- TCN_ASSERT(ctx != 0);
- if (file == NULL && path == NULL)
- return JNI_FALSE;
-
- /*
- * Configure Client Authentication details
- */
- if (!SSL_CTX_load_verify_locations(c->ctx,
- J2S(file), J2S(path))) {
- char err[256];
- ERR_error_string(ERR_get_error(), err);
- tcn_Throw(e, "Unable to configure locations "
- "for client authentication (%s)", err);
- rv = JNI_FALSE;
- goto cleanup;
- }
- c->store = SSL_CTX_get_cert_store(c->ctx);
- if (c->mode) {
- STACK_OF(X509_NAME) *ca_certs;
- c->ca_certs++;
- ca_certs = SSL_CTX_get_client_CA_list(c->ctx);
- if (ca_certs == NULL) {
- SSL_load_client_CA_file(J2S(file));
- if (ca_certs != NULL)
- SSL_CTX_set_client_CA_list(c->ctx, ca_certs);
- }
- else {
- if (!SSL_add_file_cert_subjects_to_stack(ca_certs, J2S(file)))
- ca_certs = NULL;
- }
- if (ca_certs == NULL && c->verify_mode == SSL_CVERIFY_REQUIRE) {
- /*
- * Give a warning when no CAs were configured but client authentication
- * should take place. This cannot work.
- */
- if (c->bio_os) {
- BIO_printf(c->bio_os,
- "[WARN] Oops, you want to request client "
- "authentication, but no CAs are known for "
- "verification!?");
- }
- else {
- fprintf(stderr,
- "[WARN] Oops, you want to request client "
- "authentication, but no CAs are known for "
- "verification!?");
- }
- }
- }
-cleanup:
- TCN_FREE_CSTRING(file);
- TCN_FREE_CSTRING(path);
- return rv;
-}
+ BIO *b = J2P(certs, BIO *);
-TCN_IMPLEMENT_CALL(void, SSLContext, setTmpDH)(TCN_STDARGS, jlong ctx,
- jstring file)
-{
- tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
- BIO *bio = NULL;
- DH *dh = NULL;
- TCN_ALLOC_CSTRING(file);
UNREFERENCED(o);
- TCN_ASSERT(ctx != 0);
- TCN_ASSERT(file);
-
- if (!J2S(file)) {
- tcn_Throw(e, "Error while configuring DH: no dh param file given");
- return;
- }
-
- bio = BIO_new_file(J2S(file), "r");
- if (!bio) {
- char err[256];
- ERR_error_string(ERR_get_error(), err);
- tcn_Throw(e, "Error while configuring DH using %s: %s", J2S(file), err);
- TCN_FREE_CSTRING(file);
- return;
- }
-
- dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
- BIO_free(bio);
- if (!dh) {
- char err[256];
- ERR_error_string(ERR_get_error(), err);
- tcn_Throw(e, "Error while configuring DH: no DH parameter found in %s (%s)", J2S(file), err);
- TCN_FREE_CSTRING(file);
- return;
- }
+ TCN_ASSERT(c != NULL);
- if (1 != SSL_CTX_set_tmp_dh(c->ctx, dh)) {
- char err[256];
- DH_free(dh);
- ERR_error_string(ERR_get_error(), err);
- tcn_Throw(e, "Error while configuring DH with file %s: %s", J2S(file), err);
- TCN_FREE_CSTRING(file);
- return;
- }
-
- DH_free(dh);
- TCN_FREE_CSTRING(file);
+ return b != NULL && c->mode != SSL_MODE_CLIENT && SSL_CTX_use_client_CA_bio(c->ctx, b) > 0 ? JNI_TRUE : JNI_FALSE;
}
-TCN_IMPLEMENT_CALL(void, SSLContext, setTmpECDHByCurveName)(TCN_STDARGS, jlong ctx,
- jstring curveName)
+TCN_IMPLEMENT_CALL(void, SSLContext, setTmpDHLength)(TCN_STDARGS, jlong ctx, jint length)
{
-#ifdef HAVE_ECC
tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
- int i;
- EC_KEY *ecdh;
- TCN_ALLOC_CSTRING(curveName);
UNREFERENCED(o);
TCN_ASSERT(ctx != 0);
- TCN_ASSERT(curveName);
-
- // First try to get curve by name
- i = OBJ_sn2nid(J2S(curveName));
- if (!i) {
- tcn_Throw(e, "Can't configure elliptic curve: unknown curve name %s", J2S(curveName));
- TCN_FREE_CSTRING(curveName);
- return;
- }
-
- ecdh = EC_KEY_new_by_curve_name(i);
- if (!ecdh) {
- tcn_Throw(e, "Can't configure elliptic curve: unknown curve name %s", J2S(curveName));
- TCN_FREE_CSTRING(curveName);
- return;
- }
-
- // Setting found curve to context
- if (1 != SSL_CTX_set_tmp_ecdh(c->ctx, ecdh)) {
- char err[256];
- EC_KEY_free(ecdh);
- ERR_error_string(ERR_get_error(), err);
- tcn_Throw(e, "Error while configuring elliptic curve %s: %s", J2S(curveName), err);
- TCN_FREE_CSTRING(curveName);
- return;
+ switch (length) {
+ case 512:
+ SSL_CTX_set_tmp_dh_callback(c->ctx, SSL_callback_tmp_DH_512);
+ return;
+ case 1024:
+ SSL_CTX_set_tmp_dh_callback(c->ctx, SSL_callback_tmp_DH_1024);
+ return;
+ case 2048:
+ SSL_CTX_set_tmp_dh_callback(c->ctx, SSL_callback_tmp_DH_2048);
+ return;
+ case 4096:
+ SSL_CTX_set_tmp_dh_callback(c->ctx, SSL_callback_tmp_DH_4096);
+ return;
+ default:
+ tcn_Throw(e, "Unsupported length %s", length);
+ return;
}
- EC_KEY_free(ecdh);
- TCN_FREE_CSTRING(curveName);
-#else
- tcn_Throw(e, "Cant't configure elliptic curve: unsupported by this OpenSSL version");
- return;
-#endif
-}
-
-TCN_IMPLEMENT_CALL(void, SSLContext, setShutdownType)(TCN_STDARGS, jlong ctx,
- jint type)
-{
- tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
-
- UNREFERENCED_STDARGS;
- TCN_ASSERT(ctx != 0);
- c->shutdown_type = type;
}
-TCN_IMPLEMENT_CALL(void, SSLContext, setVerify)(TCN_STDARGS, jlong ctx,
- jint level, jint depth)
+TCN_IMPLEMENT_CALL(void, SSLContext, setVerify)(TCN_STDARGS, jlong ctx, jint level, jint depth)
{
tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
- int verify = SSL_VERIFY_NONE;
UNREFERENCED(o);
- TCN_ASSERT(ctx != 0);
- c->verify_mode = level;
-
- if (c->verify_mode == SSL_CVERIFY_UNSET)
- c->verify_mode = SSL_CVERIFY_NONE;
- if (depth > 0)
- c->verify_depth = depth;
- /*
- * Configure callbacks for SSL context
- */
- if (c->verify_mode == SSL_CVERIFY_REQUIRE)
- verify |= SSL_VERIFY_PEER_STRICT;
- if ((c->verify_mode == SSL_CVERIFY_OPTIONAL) ||
- (c->verify_mode == SSL_CVERIFY_OPTIONAL_NO_CA))
- verify |= SSL_VERIFY_PEER;
- if (!c->store) {
- if (SSL_CTX_set_default_verify_paths(c->ctx)) {
- c->store = SSL_CTX_get_cert_store(c->ctx);
- X509_STORE_set_flags(c->store, 0);
- }
- else {
- /* XXX: See if this is fatal */
- }
- }
+ TCN_ASSERT(c != NULL);
- SSL_CTX_set_verify(c->ctx, verify, SSL_callback_SSL_verify);
+ // No need to set the callback for SSL_CTX_set_verify because we override the default certificate verification via SSL_CTX_set_cert_verify_callback.
+ SSL_CTX_set_verify(c->ctx, tcn_set_verify_config(&c->verify_config, level, depth), NULL);
+ SSL_CTX_set_verify_depth(c->ctx, c->verify_config.verify_depth);
}
static EVP_PKEY *load_pem_key(tcn_ssl_ctxt_t *c, const char *file)
{
BIO *bio = NULL;
EVP_PKEY *key = NULL;
- tcn_pass_cb_t *cb_data = c->cb_data;
- int i;
if ((bio = BIO_new(BIO_s_file())) == NULL) {
return NULL;
@@ -699,38 +490,10 @@ static EVP_PKEY *load_pem_key(tcn_ssl_ctxt_t *c, const char *file)
BIO_free(bio);
return NULL;
}
- if (!cb_data)
- cb_data = &tcn_password_callback;
- for (i = 0; i < 3; i++) {
- key = PEM_read_bio_PrivateKey(bio, NULL,
- (pem_password_cb *)SSL_password_callback,
- (void *)cb_data);
- if (key != NULL)
- break;
- cb_data->password[0] = '\0';
- BIO_ctrl(bio, BIO_CTRL_RESET, 0, NULL);
- }
- BIO_free(bio);
- return key;
-}
-static EVP_PKEY *load_pem_key_bio(tcn_ssl_ctxt_t *c, const BIO *bio)
-{
- EVP_PKEY *key = NULL;
- tcn_pass_cb_t *cb_data = c->cb_data;
- int i;
+ key = PEM_read_bio_PrivateKey(bio, NULL, (pem_password_cb *)SSL_password_callback, (void *)c->password);
- if (cb_data == NULL)
- cb_data = &tcn_password_callback;
- for (i = 0; i < 3; i++) {
- key = PEM_read_bio_PrivateKey((BIO*) bio, NULL,
- (pem_password_cb *)SSL_password_callback,
- (void *)cb_data);
- if (key)
- break;
- cb_data->password[0] = '\0';
- BIO_ctrl((BIO*) bio, BIO_CTRL_RESET, 0, NULL);
- }
+ BIO_free(bio);
return key;
}
@@ -738,7 +501,6 @@ static X509 *load_pem_cert(tcn_ssl_ctxt_t *c, const char *file)
{
BIO *bio = NULL;
X509 *cert = NULL;
- tcn_pass_cb_t *cb_data = c->cb_data;
if ((bio = BIO_new(BIO_s_file())) == NULL) {
return NULL;
@@ -747,11 +509,9 @@ static X509 *load_pem_cert(tcn_ssl_ctxt_t *c, const char *file)
BIO_free(bio);
return NULL;
}
- if (!cb_data)
- cb_data = &tcn_password_callback;
cert = PEM_read_bio_X509_AUX(bio, NULL,
(pem_password_cb *)SSL_password_callback,
- (void *)cb_data);
+ (void *)c->password);
if (cert == NULL &&
(ERR_GET_REASON(ERR_peek_last_error()) == PEM_R_NO_START_LINE)) {
ERR_clear_error();
@@ -762,25 +522,6 @@ static X509 *load_pem_cert(tcn_ssl_ctxt_t *c, const char *file)
return cert;
}
-static X509 *load_pem_cert_bio(tcn_ssl_ctxt_t *c, const BIO *bio)
-{
- X509 *cert = NULL;
- tcn_pass_cb_t *cb_data = c->cb_data;
-
- if (cb_data == NULL)
- cb_data = &tcn_password_callback;
- cert = PEM_read_bio_X509_AUX((BIO*) bio, NULL,
- (pem_password_cb *)SSL_password_callback,
- (void *)cb_data);
- if (cert == NULL &&
- (ERR_GET_REASON(ERR_peek_last_error()) == PEM_R_NO_START_LINE)) {
- ERR_clear_error();
- BIO_ctrl((BIO*) bio, BIO_CTRL_RESET, 0, NULL);
- cert = d2i_X509_bio((BIO*) bio, NULL);
- }
- return cert;
-}
-
static int ssl_load_pkcs12(tcn_ssl_ctxt_t *c, const char *file,
EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca)
{
@@ -789,7 +530,6 @@ static int ssl_load_pkcs12(tcn_ssl_ctxt_t *c, const char *file,
int len, rc = 0;
PKCS12 *p12;
BIO *in;
- tcn_pass_cb_t *cb_data = c->cb_data;
if ((in = BIO_new(BIO_s_file())) == 0)
return 0;
@@ -807,9 +547,7 @@ static int ssl_load_pkcs12(tcn_ssl_ctxt_t *c, const char *file,
pass = "";
}
else {
- if (!cb_data)
- cb_data = &tcn_password_callback;
- len = SSL_password_callback(buff, PEM_BUFSIZE, 0, cb_data);
+ len = SSL_password_callback(buff, PEM_BUFSIZE, 0, (void *) c->password);
if (len < 0) {
/* Passpharse callback error */
goto cleanup;
@@ -828,45 +566,47 @@ cleanup:
return rc;
}
-TCN_IMPLEMENT_CALL(void, SSLContext, setRandom)(TCN_STDARGS, jlong ctx,
- jstring file)
-{
- tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
- TCN_ALLOC_CSTRING(file);
-
- TCN_ASSERT(ctx != 0);
- UNREFERENCED(o);
- if (J2S(file))
- c->rand_file = apr_pstrdup(c->pool, J2S(file));
- TCN_FREE_CSTRING(file);
+static void free_and_reset_pass(tcn_ssl_ctxt_t *c, char* old_password, const jboolean rv) {
+ if (!rv) {
+ if (c->password != NULL) {
+ free(c->password);
+ c->password = NULL;
+ }
+ // Restore old password
+ c->password = old_password;
+ } else if (old_password != NULL) {
+ free(old_password);
+ }
}
+
TCN_IMPLEMENT_CALL(jboolean, SSLContext, setCertificate)(TCN_STDARGS, jlong ctx,
jstring cert, jstring key,
- jstring password, jint idx)
+ jstring password)
{
tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
jboolean rv = JNI_TRUE;
TCN_ALLOC_CSTRING(cert);
TCN_ALLOC_CSTRING(key);
TCN_ALLOC_CSTRING(password);
+ EVP_PKEY *pkey = NULL;
+ X509 *xcert = NULL;
const char *key_file, *cert_file;
const char *p;
+ char *old_password = NULL;
char err[256];
UNREFERENCED(o);
TCN_ASSERT(ctx != 0);
- if (idx < 0 || idx >= SSL_AIDX_MAX) {
- /* TODO: Throw something */
- rv = JNI_FALSE;
- goto cleanup;
- }
if (J2S(password)) {
- if (!c->cb_data)
- c->cb_data = &tcn_password_callback;
- strncpy(c->cb_data->password, J2S(password), SSL_MAX_PASSWORD_LEN);
- c->cb_data->password[SSL_MAX_PASSWORD_LEN-1] = '\0';
+ old_password = c->password;
+
+ c->password = strdup(cpassword);
+ if (c->password == NULL) {
+ rv = JNI_FALSE;
+ goto cleanup;
+ }
}
key_file = J2S(key);
cert_file = J2S(cert);
@@ -878,7 +618,7 @@ TCN_IMPLEMENT_CALL(jboolean, SSLContext, setCertificate)(TCN_STDARGS, jlong ctx,
goto cleanup;
}
if ((p = strrchr(cert_file, '.')) != NULL && strcmp(p, ".pkcs12") == 0) {
- if (!ssl_load_pkcs12(c, cert_file, &c->keys[idx], &c->certs[idx], 0)) {
+ if (!ssl_load_pkcs12(c, cert_file, &pkey, &xcert, 0)) {
ERR_error_string(ERR_get_error(), err);
tcn_Throw(e, "Unable to load certificate %s (%s)",
cert_file, err);
@@ -887,14 +627,14 @@ TCN_IMPLEMENT_CALL(jboolean, SSLContext, setCertificate)(TCN_STDARGS, jlong ctx,
}
}
else {
- if ((c->keys[idx] = load_pem_key(c, key_file)) == NULL) {
+ if ((pkey = load_pem_key(c, key_file)) == NULL) {
ERR_error_string(ERR_get_error(), err);
tcn_Throw(e, "Unable to load certificate key %s (%s)",
key_file, err);
rv = JNI_FALSE;
goto cleanup;
}
- if ((c->certs[idx] = load_pem_cert(c, cert_file)) == NULL) {
+ if ((xcert = load_pem_cert(c, cert_file)) == NULL) {
ERR_error_string(ERR_get_error(), err);
tcn_Throw(e, "Unable to load certificate %s (%s)",
cert_file, err);
@@ -902,13 +642,13 @@ TCN_IMPLEMENT_CALL(jboolean, SSLContext, setCertificate)(TCN_STDARGS, jlong ctx,
goto cleanup;
}
}
- if (SSL_CTX_use_certificate(c->ctx, c->certs[idx]) <= 0) {
+ if (SSL_CTX_use_certificate(c->ctx, xcert) <= 0) {
ERR_error_string(ERR_get_error(), err);
tcn_Throw(e, "Error setting certificate (%s)", err);
rv = JNI_FALSE;
goto cleanup;
}
- if (SSL_CTX_use_PrivateKey(c->ctx, c->keys[idx]) <= 0) {
+ if (SSL_CTX_use_PrivateKey(c->ctx, pkey) <= 0) {
ERR_error_string(ERR_get_error(), err);
tcn_Throw(e, "Error setting private key (%s)", err);
rv = JNI_FALSE;
@@ -925,35 +665,40 @@ cleanup:
TCN_FREE_CSTRING(cert);
TCN_FREE_CSTRING(key);
TCN_FREE_CSTRING(password);
+ EVP_PKEY_free(pkey); // this function is safe to call with NULL
+ X509_free(xcert); // this function is safe to call with NULL
+ free_and_reset_pass(c, old_password, rv);
return rv;
}
TCN_IMPLEMENT_CALL(jboolean, SSLContext, setCertificateBio)(TCN_STDARGS, jlong ctx,
jlong cert, jlong key,
- jstring password, jint idx)
+ jstring password)
{
tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
BIO *cert_bio = J2P(cert, BIO *);
BIO *key_bio = J2P(key, BIO *);
+ EVP_PKEY *pkey = NULL;
+ X509 *xcert = NULL;
jboolean rv = JNI_TRUE;
TCN_ALLOC_CSTRING(password);
+ char *old_password = NULL;
char err[256];
UNREFERENCED(o);
TCN_ASSERT(ctx != 0);
- if (idx < 0 || idx >= SSL_AIDX_MAX) {
- /* TODO: Throw something */
- rv = JNI_FALSE;
- goto cleanup;
- }
if (J2S(password)) {
- if (!c->cb_data)
- c->cb_data = &tcn_password_callback;
- strncpy(c->cb_data->password, J2S(password), SSL_MAX_PASSWORD_LEN);
- c->cb_data->password[SSL_MAX_PASSWORD_LEN-1] = '\0';
+ old_password = c->password;
+
+ c->password = strdup(cpassword);
+ if (c->password == NULL) {
+ rv = JNI_FALSE;
+ goto cleanup;
+ }
}
+
if (!key)
key = cert;
if (!cert || !key) {
@@ -962,14 +707,14 @@ TCN_IMPLEMENT_CALL(jboolean, SSLContext, setCertificateBio)(TCN_STDARGS, jlong c
goto cleanup;
}
- if ((c->keys[idx] = load_pem_key_bio(c, key_bio)) == NULL) {
+ if ((pkey = load_pem_key_bio(c->password, key_bio)) == NULL) {
ERR_error_string(ERR_get_error(), err);
ERR_clear_error();
tcn_Throw(e, "Unable to load certificate key (%s)",err);
rv = JNI_FALSE;
goto cleanup;
}
- if ((c->certs[idx] = load_pem_cert_bio(c, cert_bio)) == NULL) {
+ if ((xcert = load_pem_cert_bio(c->password, cert_bio)) == NULL) {
ERR_error_string(ERR_get_error(), err);
ERR_clear_error();
tcn_Throw(e, "Unable to load certificate (%s) ", err);
@@ -977,14 +722,14 @@ TCN_IMPLEMENT_CALL(jboolean, SSLContext, setCertificateBio)(TCN_STDARGS, jlong c
goto cleanup;
}
- if (SSL_CTX_use_certificate(c->ctx, c->certs[idx]) <= 0) {
+ if (SSL_CTX_use_certificate(c->ctx, xcert) <= 0) {
ERR_error_string(ERR_get_error(), err);
ERR_clear_error();
tcn_Throw(e, "Error setting certificate (%s)", err);
rv = JNI_FALSE;
goto cleanup;
}
- if (SSL_CTX_use_PrivateKey(c->ctx, c->keys[idx]) <= 0) {
+ if (SSL_CTX_use_PrivateKey(c->ctx, pkey) <= 0) {
ERR_error_string(ERR_get_error(), err);
ERR_clear_error();
tcn_Throw(e, "Error setting private key (%s)", err);
@@ -1002,17 +747,19 @@ TCN_IMPLEMENT_CALL(jboolean, SSLContext, setCertificateBio)(TCN_STDARGS, jlong c
}
cleanup:
TCN_FREE_CSTRING(password);
+ EVP_PKEY_free(pkey); // this function is safe to call with NULL
+ X509_free(xcert); // this function is safe to call with NULL
+ free_and_reset_pass(c, old_password, rv);
return rv;
}
-
// Convert protos to wire format
static int initProtocols(JNIEnv *e, unsigned char **proto_data,
unsigned int *proto_len, jobjectArray protos) {
int i;
unsigned char *p_data;
// We start with allocate 128 bytes which should be good enough for most use-cases while still be pretty low.
- // We will call realloc to increate this if needed.
+ // We will call realloc to increase this if needed.
size_t p_data_size = 128;
size_t p_data_len = 0;
jstring proto_string;
@@ -1273,6 +1020,34 @@ TCN_IMPLEMENT_CALL(jlong, SSLContext, sessionCacheFull)(TCN_STDARGS, jlong ctx)
return rv;
}
+TCN_IMPLEMENT_CALL(jlong, SSLContext, sessionTicketKeyNew)(TCN_STDARGS, jlong ctx)
+{
+ tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
+ jlong rv = apr_atomic_read32(&c->ticket_keys_new);
+ return rv;
+}
+
+TCN_IMPLEMENT_CALL(jlong, SSLContext, sessionTicketKeyResume)(TCN_STDARGS, jlong ctx)
+{
+ tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
+ jlong rv = apr_atomic_read32(&c->ticket_keys_resume);
+ return rv;
+}
+
+TCN_IMPLEMENT_CALL(jlong, SSLContext, sessionTicketKeyRenew)(TCN_STDARGS, jlong ctx)
+{
+ tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
+ jlong rv = apr_atomic_read32(&c->ticket_keys_renew);
+ return rv;
+}
+
+TCN_IMPLEMENT_CALL(jlong, SSLContext, sessionTicketKeyFail)(TCN_STDARGS, jlong ctx)
+{
+ tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
+ jlong rv = apr_atomic_read32(&c->ticket_keys_fail);
+ return rv;
+}
+
static int current_session_key(tcn_ssl_ctxt_t *c, tcn_ssl_ticket_key_t *key) {
int result = JNI_FALSE;
apr_thread_rwlock_rdlock(c->mutex);
@@ -1303,37 +1078,44 @@ static int find_session_key(tcn_ssl_ctxt_t *c, unsigned char key_name[16], tcn_s
}
static int ssl_tlsext_ticket_key_cb(SSL *s, unsigned char key_name[16], unsigned char *iv, EVP_CIPHER_CTX *ctx, HMAC_CTX *hctx, int enc) {
- tcn_ssl_ctxt_t *c = SSL_get_app_data2(s);
- tcn_ssl_ticket_key_t key;
- int is_current_key;
-
- if (enc) { /* create new session */
- if (current_session_key(c, &key)) {
- if (RAND_bytes(iv, EVP_MAX_IV_LENGTH) <= 0) {
- return -1; /* insufficient random */
- }
-
- memcpy(key_name, key.key_name, 16);
-
- EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key.aes_key, iv);
- HMAC_Init_ex(hctx, key.hmac_key, 16, EVP_sha256(), NULL);
- return 1;
- }
- // No ticket configured
- return 0;
- } else { /* retrieve session */
- if (find_session_key(c, key_name, &key, &is_current_key)) {
- HMAC_Init_ex(hctx, key.hmac_key, 16, EVP_sha256(), NULL);
- EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key.aes_key, iv );
- if (!is_current_key) {
- return 2;
- }
- return 1;
- }
- // No ticket
- return 0;
- }
-}
+ tcn_ssl_ctxt_t *c = SSL_get_app_data2(s);
+ tcn_ssl_ticket_key_t key;
+ int is_current_key;
+
+ if (enc) { /* create new session */
+ if (current_session_key(c, &key)) {
+ if (RAND_bytes(iv, EVP_MAX_IV_LENGTH) <= 0) {
+ return -1; /* insufficient random */
+ }
+
+ memcpy(key_name, key.key_name, 16);
+
+ EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key.aes_key, iv);
+ HMAC_Init_ex(hctx, key.hmac_key, 16, EVP_sha256(), NULL);
+ apr_atomic_inc32(&c->ticket_keys_new);
+ return 1;
+ }
+ // No ticket configured
+ return 0;
+ } else { /* retrieve session */
+ if (find_session_key(c, key_name, &key, &is_current_key)) {
+ HMAC_Init_ex(hctx, key.hmac_key, 16, EVP_sha256(), NULL);
+ EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key.aes_key, iv );
+ if (!is_current_key) {
+ // The ticket matched a key in the list, and we want to upgrade it to the current
+ // key.
+ apr_atomic_inc32(&c->ticket_keys_renew);
+ return 2;
+ }
+ // The ticket matched the current key.
+ apr_atomic_inc32(&c->ticket_keys_resume);
+ return 1;
+ }
+ // No matching ticket.
+ apr_atomic_inc32(&c->ticket_keys_fail);
+ return 0;
+ }
+}
TCN_IMPLEMENT_CALL(void, SSLContext, setSessionTicketKeys0)(TCN_STDARGS, jlong ctx, jbyteArray keys)
{
@@ -1369,104 +1151,21 @@ TCN_IMPLEMENT_CALL(void, SSLContext, setSessionTicketKeys0)(TCN_STDARGS, jlong c
SSL_CTX_set_tlsext_ticket_key_cb(c->ctx, ssl_tlsext_ticket_key_cb);
}
-
-/*
- * Adapted from OpenSSL:
- * http://osxr.org/openssl/source/ssl/ssl_locl.h#0291
- */
-/* Bits for algorithm_mkey (key exchange algorithm) */
-#define SSL_kRSA 0x00000001L /* RSA key exchange */
-#define SSL_kDHr 0x00000002L /* DH cert, RSA CA cert */ /* no such ciphersuites supported! */
-#define SSL_kDHd 0x00000004L /* DH cert, DSA CA cert */ /* no such ciphersuite supported! */
-#define SSL_kEDH 0x00000008L /* tmp DH key no DH cert */
-#define SSL_kKRB5 0x00000010L /* Kerberos5 key exchange */
-#define SSL_kECDHr 0x00000020L /* ECDH cert, RSA CA cert */
-#define SSL_kECDHe 0x00000040L /* ECDH cert, ECDSA CA cert */
-#define SSL_kEECDH 0x00000080L /* ephemeral ECDH */
-#define SSL_kPSK 0x00000100L /* PSK */
-#define SSL_kGOST 0x00000200L /* GOST key exchange */
-#define SSL_kSRP 0x00000400L /* SRP */
-
-/* Bits for algorithm_auth (server authentication) */
-#define SSL_aRSA 0x00000001L /* RSA auth */
-#define SSL_aDSS 0x00000002L /* DSS auth */
-#define SSL_aNULL 0x00000004L /* no auth (i.e. use ADH or AECDH) */
-#define SSL_aDH 0x00000008L /* Fixed DH auth (kDHd or kDHr) */ /* no such ciphersuites supported! */
-#define SSL_aECDH 0x00000010L /* Fixed ECDH auth (kECDHe or kECDHr) */
-#define SSL_aKRB5 0x00000020L /* KRB5 auth */
-#define SSL_aECDSA 0x00000040L /* ECDSA auth*/
-#define SSL_aPSK 0x00000080L /* PSK auth */
-#define SSL_aGOST94 0x00000100L /* GOST R 34.10-94 signature auth */
-#define SSL_aGOST01 0x00000200L /* GOST R 34.10-2001 signature auth */
-
-/* OpenSSL end */
-
-/*
- * Adapted from Android:
- * https://android.googlesource.com/platform/external/openssl/+/master/patches/0003-jsse.patch
- */
-const char* cipher_authentication_method(const SSL_CIPHER* cipher){
-#ifndef OPENSSL_IS_BORINGSSL
- switch (cipher->algorithm_mkey)
- {
- case SSL_kRSA:
- return SSL_TXT_RSA;
- case SSL_kDHr:
- return SSL_TXT_DH "_" SSL_TXT_RSA;
-
- case SSL_kDHd:
- return SSL_TXT_DH "_" SSL_TXT_DSS;
- case SSL_kEDH:
- switch (cipher->algorithm_auth)
- {
- case SSL_aDSS:
- return "DHE_" SSL_TXT_DSS;
- case SSL_aRSA:
- return "DHE_" SSL_TXT_RSA;
- case SSL_aNULL:
- return SSL_TXT_DH "_anon";
- default:
- return "UNKNOWN";
- }
- case SSL_kKRB5:
- return SSL_TXT_KRB5;
- case SSL_kECDHr:
- return SSL_TXT_ECDH "_" SSL_TXT_RSA;
- case SSL_kECDHe:
- return SSL_TXT_ECDH "_" SSL_TXT_ECDSA;
- case SSL_kEECDH:
- switch (cipher->algorithm_auth)
- {
- case SSL_aECDSA:
- return "ECDHE_" SSL_TXT_ECDSA;
- case SSL_aRSA:
- return "ECDHE_" SSL_TXT_RSA;
- case SSL_aNULL:
- return SSL_TXT_ECDH "_anon";
- default:
- return "UNKNOWN";
- }
- default:
- return "UNKNOWN";
- }
-#else
- return SSL_CIPHER_get_kx_name(cipher);
-#endif
-
-}
-
static const char* authentication_method(const SSL* ssl) {
{
+ const STACK_OF(SSL_CIPHER) *ciphers = NULL;
+
switch (SSL_version(ssl))
{
case SSL2_VERSION:
return SSL_TXT_RSA;
default:
-#if defined(OPENSSL_IS_BORINGSSL)
- return cipher_authentication_method(SSL_get_pending_cipher(ssl));
-#else
- return cipher_authentication_method(ssl->s3->tmp.new_cipher);
-#endif
+ ciphers = SSL_get_ciphers(ssl);
+ if (ciphers == NULL || sk_SSL_CIPHER_num(ciphers) <= 0) {
+ // No cipher available so return UNKNOWN.
+ return TCN_UNKNOWN_AUTH_METHOD;
+ }
+ return SSL_cipher_authentication_method(sk_SSL_CIPHER_value(ciphers, 0));
}
}
}
@@ -1475,13 +1174,22 @@ static const char* authentication_method(const SSL* ssl) {
static int SSL_cert_verify(X509_STORE_CTX *ctx, void *arg) {
/* Get Apache context back through OpenSSL context */
SSL *ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
+ TCN_ASSERT(ssl != NULL);
tcn_ssl_ctxt_t *c = SSL_get_app_data2(ssl);
-
+ TCN_ASSERT(c != NULL);
+ tcn_ssl_verify_config_t* verify_config = SSL_get_app_data4(ssl);
+ TCN_ASSERT(verify_config != NULL);
// Get a stack of all certs in the chain
STACK_OF(X509) *sk = ctx->untrusted;
- int len = sk_num((_STACK*) sk);
+ // SSL_CTX_set_verify_depth() and SSL_set_verify_depth() set the limit up to which depth certificates in a chain are
+ // used during the verification procedure. If the certificate chain is longer than allowed, the certificates above
+ // the limit are ignored. Error messages are generated as if these certificates would not be present,
+ // most likely a X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY will be issued.
+ // https://www.openssl.org/docs/man1.0.2/ssl/SSL_set_verify.html
+ const int totalQueuedLength = sk_X509_num(sk);
+ int len = TCN_MIN(verify_config->verify_depth, totalQueuedLength);
unsigned i;
X509 *cert;
int length;
@@ -1491,23 +1199,25 @@ static int SSL_cert_verify(X509_STORE_CTX *ctx, void *arg) {
jbyteArray bArray;
const char *authMethod;
jstring authMethodString;
- jboolean result;
- int r;
+ jint result;
+ jclass byteArrayClass = tcn_get_byte_array_class();
tcn_get_java_env(&e);
// Create the byte[][] array that holds all the certs
array = (*e)->NewObjectArray(e, len, byteArrayClass, NULL);
for(i = 0; i < len; i++) {
- cert = (X509*) sk_value((_STACK*) sk, i);
+ cert = sk_X509_value(sk, i);
buf = NULL;
length = i2d_X509(cert, &buf);
if (length < 0) {
// In case of error just return an empty byte[][]
array = (*e)->NewObjectArray(e, 0, byteArrayClass, NULL);
- // We need to delete the local references so we not leak memory as this method is called via callback.
- OPENSSL_free(buf);
+ if (buf != NULL) {
+ // We need to delete the local references so we not leak memory as this method is called via callback.
+ OPENSSL_free(buf);
+ }
break;
}
bArray = (*e)->NewByteArray(e, length);
@@ -1523,17 +1233,35 @@ static int SSL_cert_verify(X509_STORE_CTX *ctx, void *arg) {
authMethod = authentication_method(ssl);
authMethodString = (*e)->NewStringUTF(e, authMethod);
- result = (*e)->CallBooleanMethod(e, c->verifier, c->verifier_method, P2J(ssl), array,
- authMethodString);
+ result = (*e)->CallIntMethod(e, c->verifier, c->verifier_method, P2J(ssl), array, authMethodString);
+
+#ifdef X509_V_ERR_UNSPECIFIED
+ // If we failed to verify for an unknown reason (currently this happens if we can't find a common root) then we should
+ // fail with the same status as recommended in the OpenSSL docs https://www.openssl.org/docs/man1.0.2/ssl/SSL_set_verify.html
+ if (result == X509_V_ERR_UNSPECIFIED && len < totalQueuedLength) {
+ result = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY;
+ }
+#else
+ // HACK!
+ // LibreSSL 2.4.x doesn't support the X509_V_ERR_UNSPECIFIED so we introduce a work around to make sure a supported alert is used.
+ // This should be reverted when we support LibreSSL 2.5.x (which does support X509_V_ERR_UNSPECIFIED).
+ if (result == TCN_X509_V_ERR_UNSPECIFIED) {
+ result = len < totalQueuedLength ? X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY : X509_V_ERR_CERT_REJECTED;
+ }
+#endif
+
+ // TODO(scott): if verify_config->verify_depth == SSL_CVERIFY_OPTIONAL we have the option to let the handshake
+ // succeed for some of the "informational" error messages (e.g. X509_V_ERR_EMAIL_MISMATCH ?)
- r = result == JNI_TRUE ? 1 : 0;
+ // Set the correct error so it will be included in the alert.
+ X509_STORE_CTX_set_error(ctx, result);
// We need to delete the local references so we not leak memory as this method is called via callback.
(*e)->DeleteLocalRef(e, authMethodString);
(*e)->DeleteLocalRef(e, array);
- return r;
-}
+ return result == X509_V_OK ? 1 : 0;
+}
TCN_IMPLEMENT_CALL(void, SSLContext, setCertVerifyCallback)(TCN_STDARGS, jlong ctx, jobject verifier)
{
@@ -1546,7 +1274,7 @@ TCN_IMPLEMENT_CALL(void, SSLContext, setCertVerifyCallback)(TCN_STDARGS, jlong c
SSL_CTX_set_cert_verify_callback(c->ctx, NULL, NULL);
} else {
jclass verifier_class = (*e)->GetObjectClass(e, verifier);
- jmethodID method = (*e)->GetMethodID(e, verifier_class, "verify", "(J[[BLjava/lang/String;)Z");
+ jmethodID method = (*e)->GetMethodID(e, verifier_class, "verify", "(J[[BLjava/lang/String;)I");
if (method == NULL) {
return;
@@ -1562,366 +1290,236 @@ TCN_IMPLEMENT_CALL(void, SSLContext, setCertVerifyCallback)(TCN_STDARGS, jlong c
}
}
-TCN_IMPLEMENT_CALL(jboolean, SSLContext, setSessionIdContext)(TCN_STDARGS, jlong ctx, jbyteArray sidCtx)
-{
- tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
- int len = (*e)->GetArrayLength(e, sidCtx);
+/**
+ * Returns an array containing all the X500 principal's bytes.
+ *
+ * Partly based on code from conscrypt:
+ * https://android.googlesource.com/platform/external/conscrypt/+/master/src/main/native/org_conscrypt_NativeCrypto.cpp
+ */
+static jobjectArray principalBytes(JNIEnv* e, const STACK_OF(X509_NAME)* names) {
+ jobjectArray array;
+ jbyteArray bArray;
+ int i;
+ int count;
+ int length;
unsigned char *buf;
- int res;
+ X509_NAME* principal;
+ jclass byteArrayClass = tcn_get_byte_array_class();
- UNREFERENCED(o);
- TCN_ASSERT(ctx != 0);
-
- buf = malloc(len);
-
- (*e)->GetByteArrayRegion(e, sidCtx, 0, len, (jbyte*) buf);
-
- res = SSL_CTX_set_session_id_context(c->ctx, buf, len);
- free(buf);
-
- if (res == 1) {
- return JNI_TRUE;
+ if (names == NULL) {
+ return NULL;
}
- return JNI_FALSE;
-}
-#else
-/* OpenSSL is not supported.
- * Create empty stubs.
- */
-
-TCN_IMPLEMENT_CALL(jlong, SSLContext, make)(TCN_STDARGS, jlong pool,
- jint protocol, jint mode)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(pool);
- UNREFERENCED(protocol);
- UNREFERENCED(mode);
- return 0;
-}
-
-TCN_IMPLEMENT_CALL(jint, SSLContext, free)(TCN_STDARGS, jlong ctx)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- return APR_ENOTIMPL;
-}
-
-TCN_IMPLEMENT_CALL(void, SSLContext, setContextId)(TCN_STDARGS, jlong ctx,
- jstring id)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- UNREFERENCED(id);
-}
-
-TCN_IMPLEMENT_CALL(void, SSLContext, setBIO)(TCN_STDARGS, jlong ctx,
- jlong bio, jint dir)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- UNREFERENCED(bio);
- UNREFERENCED(dir);
-}
-TCN_IMPLEMENT_CALL(void, SSLContext, setOptions)(TCN_STDARGS, jlong ctx,
- jint opt)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- UNREFERENCED(opt);
-}
+ count = sk_X509_NAME_num(names);
+ if (count <= 0) {
+ return NULL;
+ }
-TCN_IMPLEMENT_CALL(jint, SSLContext, getOptions)(TCN_STDARGS, jlong ctx)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
-}
+ array = (*e)->NewObjectArray(e, count, byteArrayClass, NULL);
+ if (array == NULL) {
+ return NULL;
+ }
-TCN_IMPLEMENT_CALL(void, SSLContext, clearOptions)(TCN_STDARGS, jlong ctx,
- jint opt)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- UNREFERENCED(opt);
-}
+ for (i = 0; i < count; i++) {
+ principal = sk_X509_NAME_value(names, i);
+ buf = NULL;
+ length = i2d_X509_NAME(principal, &buf);
+ if (length < 0) {
+ if (buf != NULL) {
+ // We need to delete the local references so we not leak memory as this method is called via callback.
+ OPENSSL_free(buf);
+ }
+ // In case of error just return an empty byte[][]
+ return (*e)->NewObjectArray(e, 0, byteArrayClass, NULL);
+ }
+ bArray = (*e)->NewByteArray(e, length);
+ (*e)->SetByteArrayRegion(e, bArray, 0, length, (jbyte*) buf);
+ (*e)->SetObjectArrayElement(e, array, i, bArray);
-TCN_IMPLEMENT_CALL(void, SSLContext, setQuietShutdown)(TCN_STDARGS, jlong ctx,
- jboolean mode)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- UNREFERENCED(mode);
-}
+ // Delete the local reference as we not know how long the chain is and local references are otherwise
+ // only freed once jni method returns.
+ (*e)->DeleteLocalRef(e, bArray);
+ OPENSSL_free(buf);
+ }
-TCN_IMPLEMENT_CALL(jboolean, SSLContext, setCipherSuite)(TCN_STDARGS, jlong ctx,
- jstring ciphers)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- UNREFERENCED(ciphers);
- return JNI_FALSE;
+ return array;
}
-TCN_IMPLEMENT_CALL(jboolean, SSLContext, setCARevocation)(TCN_STDARGS, jlong ctx,
- jstring file,
- jstring path)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- UNREFERENCED(file);
- UNREFERENCED(path);
- return JNI_FALSE;
-}
+static int cert_requested(SSL* ssl, X509** x509Out, EVP_PKEY** pkeyOut) {
+#if defined(LIBRESSL_VERSION_NUMBER)
+ return -1;
+#else
+ tcn_ssl_ctxt_t *c = SSL_get_app_data2(ssl);
+ int ctype_num;
+ jbyte* ctype_bytes;
+ jobjectArray issuers;
+ JNIEnv *e;
+ jbyteArray keyTypes;
+ jobject keyMaterial;
+ STACK_OF(X509) *chain = NULL;
+ X509 *cert = NULL;
+ EVP_PKEY* pkey = NULL;
+ jlong certChain;
+ jlong privateKey;
+ int certChainLen;
+ int i;
-TCN_IMPLEMENT_CALL(jboolean, SSLContext, setCertificateChainFile)(TCN_STDARGS, jlong ctx,
- jstring file,
- jboolean skipfirst)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- UNREFERENCED(file);
- UNREFERENCED(skipfirst);
- return JNI_FALSE;
-}
+ tcn_get_java_env(&e);
-TCN_IMPLEMENT_CALL(jboolean, SSLContext, setCertificateChainBio)(TCN_STDARGS, jlong ctx,
- jlong chain,
- jboolean skipfirst)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- UNREFERENCED(chain);
- UNREFERENCED(skipfirst);
- return JNI_FALSE;
-}
+#if OPENSSL_VERSION_NUMBER < 0x10002000L
+ char ssl2_ctype = SSL3_CT_RSA_SIGN;
+ switch (ssl->version) {
+ case SSL2_VERSION:
+ ctype_bytes = (jbyte*) &ssl2_ctype;
+ ctype_num = 1;
+ break;
+ case SSL3_VERSION:
+ case TLS1_VERSION:
+ case TLS1_1_VERSION:
+ case TLS1_2_VERSION:
+ case DTLS1_VERSION:
+ ctype_bytes = (jbyte*) ssl->s3->tmp.ctype;
+ ctype_num = ssl->s3->tmp.ctype_num;
+ break;
+ }
+#else
+ ctype_num = SSL_get0_certificate_types(ssl, (const uint8_t **) &ctype_bytes);
+#endif
+ 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);
-TCN_IMPLEMENT_CALL(jboolean, SSLContext, setCACertificate)(TCN_STDARGS,
- jlong ctx,
- jstring file,
- jstring path)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- UNREFERENCED(file);
- UNREFERENCED(path);
- return JNI_FALSE;
-}
+ issuers = principalBytes(e, SSL_get_client_CA_list(ssl));
-TCN_IMPLEMENT_CALL(void, SSLContext, setShutdownType)(TCN_STDARGS, jlong ctx,
- jint type)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- UNREFERENCED(type);
-}
+ // Execute the java callback
+ keyMaterial = (*e)->CallObjectMethod(e, c->cert_requested_callback, c->cert_requested_callback_method, P2J(ssl), keyTypes, issuers);
+ if (keyMaterial == NULL) {
+ return 0;
+ }
-TCN_IMPLEMENT_CALL(void, SSLContext, setVerify)(TCN_STDARGS, jlong ctx,
- jint level, jint depth)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- UNREFERENCED(level);
- UNREFERENCED(depth);
-}
+ // Any failure after this line must cause a goto fail to cleanup things.
+ certChain = (*e)->GetLongField(e, keyMaterial, tcn_get_key_material_certificate_chain_field());
+ privateKey = (*e)->GetLongField(e, keyMaterial, tcn_get_key_material_private_key_field());
-TCN_IMPLEMENT_CALL(void, SSLContext, setRandom)(TCN_STDARGS, jlong ctx,
- jstring file)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- UNREFERENCED(file);
-}
+ chain = J2P(certChain, STACK_OF(X509) *);
+ pkey = J2P(privateKey, EVP_PKEY *);
-TCN_IMPLEMENT_CALL(jboolean, SSLContext, setCertificate)(TCN_STDARGS, jlong ctx,
- jstring cert, jstring key,
- jstring password, jint idx)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- UNREFERENCED(cert);
- UNREFERENCED(key);
- UNREFERENCED(password);
- UNREFERENCED(idx);
- return JNI_FALSE;
-}
-
-TCN_IMPLEMENT_CALL(jboolean, SSLContext, setCertificateBio)(TCN_STDARGS, jlong ctx,
- jlong cert, jlong key,
- jstring password, jint idx)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- UNREFERENCED(cert);
- UNREFERENCED(key);
- UNREFERENCED(password);
- UNREFERENCED(idx);
- return JNI_FALSE;
-}
-TCN_IMPLEMENT_CALL(void, SSLContext, setNpnProtos)(TCN_STDARGS, jlong ctx, jobjectArray next_protos,
- jint selectorFailureBehavior)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- UNREFERENCED(next_protos);
-}
+ if (chain == NULL || pkey == NULL) {
+ goto fail;
+ }
+ certChainLen = sk_X509_num(chain);
-TCN_IMPLEMENT_CALL(void, SSLContext, setAlpnProtos)(TCN_STDARGS, jlong ctx, jobjectArray alpn_protos,
- jint selectorFailureBehavior)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- UNREFERENCED(alpn_protos);
-}
+ if (certChainLen <= 0) {
+ goto fail;
+ }
-TCN_IMPLEMENT_CALL(jlong, SSLContext, setSessionCacheMode)(TCN_STDARGS, jlong ctx, jlong mode)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- UNREFERENCED(mode);
- return -1;
-}
+ // Skip the first cert in the chain as we will write this to x509Out.
+ // See https://github.com/netty/netty-tcnative/issues/184
+ for (i = 1; i < certChainLen; ++i) {
+ // We need to explicit add extra certs to the chain as stated in:
+ // https://www.openssl.org/docs/manmaster/ssl/SSL_CTX_set_client_cert_cb.html
+ //
+ // Using SSL_add0_chain_cert(...) here as we not want to increment the reference count.
+ if (SSL_add0_chain_cert(ssl, sk_X509_value(chain, i)) <= 0) {
+ goto fail;
+ }
+ }
-TCN_IMPLEMENT_CALL(jlong, SSLContext, getSessionCacheMode)(TCN_STDARGS, jlong ctx)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- return -1;
-}
+ cert = sk_X509_value(chain, 0);
+ // Increment the reference count as we already set the chain via SSL_set0_chain(...) and using a cert out of it.
+ if (tcn_X509_up_ref(cert) <= 0) {
+ goto fail;
+ }
+ *x509Out = cert;
+ *pkeyOut = pkey;
+ // Free the stack it self but not the certs.
+ sk_X509_free(chain);
+ return 1;
+fail:
+ ERR_clear_error();
+ sk_X509_pop_free(chain, X509_free);
+ EVP_PKEY_free(pkey);
-TCN_IMPLEMENT_CALL(jlong, SSLContext, setSessionCacheTimeout)(TCN_STDARGS, jlong ctx, jlong timeout)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- UNREFERENCED(timeout);
+ // TODO: Would it be more correct to return 0 in this case we may not want to use any cert / private key ?
return -1;
+#endif /* defined(LIBRESSL_VERSION_NUMBER) */
}
-TCN_IMPLEMENT_CALL(jlong, SSLContext, getSessionCacheTimeout)(TCN_STDARGS, jlong ctx)
+TCN_IMPLEMENT_CALL(void, SSLContext, setCertRequestedCallback)(TCN_STDARGS, jlong ctx, jobject callback)
{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- return -1;
-}
+ tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
-TCN_IMPLEMENT_CALL(jlong, SSLContext, setSessionCacheSize)(TCN_STDARGS, jlong ctx, jlong size)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- UNREFERENCED(size);
- return -1;
-}
+ UNREFERENCED(o);
+ TCN_ASSERT(ctx != 0);
-TCN_IMPLEMENT_CALL(jlong, SSLContext, getSessionCacheSize)(TCN_STDARGS, jlong ctx)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- return -1;
-}
+ if (callback == NULL) {
+ SSL_CTX_set_client_cert_cb(c->ctx, NULL);
+ } else {
+ jclass callback_class = (*e)->GetObjectClass(e, callback);
+ jmethodID method = (*e)->GetMethodID(e, callback_class, "requested", "(J[B[[B)Lio/netty/internal/tcnative/CertificateRequestedCallback$KeyMaterial;");
+ if (method == NULL) {
+ return;
+ }
+ // Delete the reference to the previous specified verifier if needed.
+ if (c->cert_requested_callback != NULL) {
+ (*e)->DeleteLocalRef(e, c->cert_requested_callback);
+ }
+ c->cert_requested_callback = (*e)->NewGlobalRef(e, callback);
+ c->cert_requested_callback_method = method;
-TCN_IMPLEMENT_CALL(jlong, SSLContext, sessionNumber)(TCN_STDARGS, jlong ctx)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- return 0;
+ SSL_CTX_set_client_cert_cb(c->ctx, cert_requested);
+ }
}
-TCN_IMPLEMENT_CALL(jlong, SSLContext, sessionConnect)(TCN_STDARGS, jlong ctx)
+TCN_IMPLEMENT_CALL(jboolean, SSLContext, setSessionIdContext)(TCN_STDARGS, jlong ctx, jbyteArray sidCtx)
{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- return 0;
-}
+ tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
+ int len = (*e)->GetArrayLength(e, sidCtx);
+ unsigned char *buf;
+ int res;
-TCN_IMPLEMENT_CALL(jlong, SSLContext, sessionConnectGood)(TCN_STDARGS, jlong ctx)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- return 0;
-}
+ UNREFERENCED(o);
+ TCN_ASSERT(ctx != 0);
-TCN_IMPLEMENT_CALL(jlong, SSLContext, sessionConnectRenegotiate)(TCN_STDARGS, jlong ctx)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- return 0;
-}
+ buf = malloc(len);
-TCN_IMPLEMENT_CALL(jlong, SSLContext, sessionAccept)(TCN_STDARGS, jlong ctx)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- return 0;
-}
+ (*e)->GetByteArrayRegion(e, sidCtx, 0, len, (jbyte*) buf);
-TCN_IMPLEMENT_CALL(jlong, SSLContext, sessionAcceptGood)(TCN_STDARGS, jlong ctx)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- return 0;
-}
+ res = SSL_CTX_set_session_id_context(c->ctx, buf, len);
+ free(buf);
-TCN_IMPLEMENT_CALL(jlong, SSLContext, sessionAcceptRenegotiate)(TCN_STDARGS, jlong ctx)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- return 0;
+ if (res == 1) {
+ return JNI_TRUE;
+ }
+ return JNI_FALSE;
}
-TCN_IMPLEMENT_CALL(jlong, SSLContext, sessionHits)(TCN_STDARGS, jlong ctx)
+TCN_IMPLEMENT_CALL(jint, SSLContext, setMode)(TCN_STDARGS, jlong ctx, jint mode)
{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- return 0;
-}
+ tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
-TCN_IMPLEMENT_CALL(jlong, SSLContext, sessionCbHits)(TCN_STDARGS, jlong ctx)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- return 0;
-}
+ UNREFERENCED(o);
+ TCN_ASSERT(ctx != 0);
-TCN_IMPLEMENT_CALL(jlong, SSLContext, sessionTimeouts)(TCN_STDARGS, jlong ctx)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- return 0;
+ return (jint) SSL_CTX_set_mode(c->ctx, mode);
}
-TCN_IMPLEMENT_CALL(jlong, SSLContext, sessionCacheFull)(TCN_STDARGS, jlong ctx)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- return 0;
-}
-TCN_IMPLEMENT_CALL(jlong, SSLContext, sessionMisses)(TCN_STDARGS, jlong ctx)
+TCN_IMPLEMENT_CALL(jint, SSLContext, getMode)(TCN_STDARGS, jlong ctx)
{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- return 0;
-}
+ tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
-TCN_IMPLEMENT_CALL(void, SSLContext, setSessionTicketKeys0)(TCN_STDARGS, jlong ctx, jbyteArray keys)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- UNREFERENCED(keys);
-}
+ UNREFERENCED(o);
+ TCN_ASSERT(ctx != 0);
-TCN_IMPLEMENT_CALL(void, SSLContext, setCertVerifyCallback)(TCN_STDARGS, jlong ctx, jobject verifier)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- UNREFERENCED(verifier);
-}
-TCN_IMPLEMENT_CALL(jboolean, SSLContext, setSessionIdContext)(TCN_STDARGS, jlong ctx, jbyteArray sidCtx)
-{
- UNREFERENCED_STDARGS;
- UNREFERENCED(ctx);
- UNREFERENCED(sidCtx);
- return JNI_FALSE;
+ return (jint) SSL_CTX_get_mode(c->ctx);
}
-#endif
« no previous file with comments | « c/ssl_private.h ('k') | c/sslinfo.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698