blob: d90861106e438bcb67f33c913597a596c7b8ac8c [file] [log] [blame]
/* 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.
* The ASF 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.
*/
/*
*
* @author Mladen Turk
* @version $Revision$, $Date$
*/
#include "tcn.h"
#include "apr_file_io.h"
#include "apr_thread_mutex.h"
#include "apr_atomic.h"
#include "apr_poll.h"
#ifdef HAVE_OPENSSL
#include "ssl_private.h"
static int ssl_initialized = 0;
static char *ssl_global_rand_file = NULL;
extern apr_pool_t *tcn_global_pool;
ENGINE *tcn_ssl_engine = NULL;
void *SSL_temp_keys[SSL_TMP_KEY_MAX];
tcn_pass_cb_t tcn_password_callback;
/*
* Handle the Temporary RSA Keys and DH Params
*/
#define SSL_TMP_KEY_FREE(type, idx) \
if (SSL_temp_keys[idx]) { \
type##_free((type *)SSL_temp_keys[idx]); \
SSL_temp_keys[idx] = NULL; \
} else (void)(0)
#define SSL_TMP_KEYS_FREE(type) \
SSL_TMP_KEY_FREE(type, SSL_TMP_KEY_##type##_512); \
SSL_TMP_KEY_FREE(type, SSL_TMP_KEY_##type##_1024); \
SSL_TMP_KEY_FREE(type, SSL_TMP_KEY_##type##_2048); \
SSL_TMP_KEY_FREE(type, SSL_TMP_KEY_##type##_4096)
#define SSL_TMP_KEY_INIT_RSA(bits) \
ssl_tmp_key_init_rsa(bits, SSL_TMP_KEY_RSA_##bits)
#define SSL_TMP_KEY_INIT_DH(bits) \
ssl_tmp_key_init_dh(bits, SSL_TMP_KEY_DH_##bits)
#define SSL_TMP_KEYS_INIT(R) \
SSL_temp_keys[SSL_TMP_KEY_RSA_2048] = NULL; \
SSL_temp_keys[SSL_TMP_KEY_RSA_4096] = NULL; \
R |= SSL_TMP_KEY_INIT_RSA(512); \
R |= SSL_TMP_KEY_INIT_RSA(1024); \
R |= SSL_TMP_KEY_INIT_DH(512); \
R |= SSL_TMP_KEY_INIT_DH(1024); \
R |= SSL_TMP_KEY_INIT_DH(2048); \
R |= SSL_TMP_KEY_INIT_DH(4096)
static int ssl_tmp_key_init_rsa(int bits, int idx)
{
if (!(SSL_temp_keys[idx] =
RSA_generate_key(bits, RSA_F4, NULL, NULL)))
return 1;
else
return 0;
}
static int ssl_tmp_key_init_dh(int bits, int idx)
{
if (!(SSL_temp_keys[idx] =
SSL_dh_get_tmp_param(bits)))
return 1;
else
return 0;
}
TCN_IMPLEMENT_CALL(jint, SSL, version)(TCN_STDARGS)
{
UNREFERENCED_STDARGS;
return OPENSSL_VERSION_NUMBER;
}
TCN_IMPLEMENT_CALL(jstring, SSL, versionString)(TCN_STDARGS)
{
UNREFERENCED(o);
return AJP_TO_JSTRING(OPENSSL_VERSION_TEXT);
}
/*
* the various processing hooks
*/
static apr_status_t ssl_init_cleanup(void *data)
{
UNREFERENCED(data);
if (!ssl_initialized)
return APR_SUCCESS;
ssl_initialized = 0;
if (tcn_password_callback.cb.obj) {
JNIEnv *env;
tcn_get_java_env(&env);
TCN_UNLOAD_CLASS(env,
tcn_password_callback.cb.obj);
}
SSL_TMP_KEYS_FREE(RSA);
SSL_TMP_KEYS_FREE(DH);
/*
* Try to kill the internals of the SSL library.
*/
#if OPENSSL_VERSION_NUMBER >= 0x00907001
/* Corresponds to OPENSSL_load_builtin_modules():
* XXX: borrowed from apps.h, but why not CONF_modules_free()
* which also invokes CONF_modules_finish()?
*/
CONF_modules_unload(1);
#endif
/* Corresponds to SSL_library_init: */
EVP_cleanup();
#if HAVE_ENGINE_LOAD_BUILTIN_ENGINES
ENGINE_cleanup();
#endif
#if OPENSSL_VERSION_NUMBER >= 0x00907001
CRYPTO_cleanup_all_ex_data();
#endif
ERR_remove_state(0);
/* Don't call ERR_free_strings here; ERR_load_*_strings only
* actually load the error strings once per process due to static
* variable abuse in OpenSSL. */
/*
* TODO: determine somewhere we can safely shove out diagnostics
* (when enabled) at this late stage in the game:
* CRYPTO_mem_leaks_fp(stderr);
*/
return APR_SUCCESS;
}
#ifndef OPENSSL_NO_ENGINE
/* Try to load an engine in a shareable library */
static ENGINE *ssl_try_load_engine(const char *engine)
{
ENGINE *e = ENGINE_by_id("dynamic");
if (e) {
if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", engine, 0)
|| !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) {
ENGINE_free(e);
e = NULL;
}
}
return e;
}
#endif
/*
* To ensure thread-safetyness in OpenSSL
*/
static apr_thread_mutex_t **ssl_lock_cs;
static int ssl_lock_num_locks;
static void ssl_thread_lock(int mode, int type,
const char *file, int line)
{
UNREFERENCED(file);
UNREFERENCED(line);
if (type < ssl_lock_num_locks) {
if (mode & CRYPTO_LOCK) {
apr_thread_mutex_lock(ssl_lock_cs[type]);
}
else {
apr_thread_mutex_unlock(ssl_lock_cs[type]);
}
}
}
static unsigned long ssl_thread_id(void)
{
/* OpenSSL needs this to return an unsigned long. On OS/390, the pthread
* id is a structure twice that big. Use the TCB pointer instead as a
* unique unsigned long.
*/
#ifdef __MVS__
struct PSA {
char unmapped[540];
unsigned long PSATOLD;
} *psaptr = 0;
return psaptr->PSATOLD;
#else
return (unsigned long)(apr_os_thread_current());
#endif
}
static apr_status_t ssl_thread_cleanup(void *data)
{
UNREFERENCED(data);
CRYPTO_set_locking_callback(NULL);
CRYPTO_set_id_callback(NULL);
/* Let the registered mutex cleanups do their own thing
*/
return APR_SUCCESS;
}
static void ssl_thread_setup(apr_pool_t *p)
{
int i;
ssl_lock_num_locks = CRYPTO_num_locks();
ssl_lock_cs = apr_palloc(p, ssl_lock_num_locks * sizeof(*ssl_lock_cs));
for (i = 0; i < ssl_lock_num_locks; i++) {
apr_thread_mutex_create(&(ssl_lock_cs[i]),
APR_THREAD_MUTEX_DEFAULT, p);
}
CRYPTO_set_id_callback(ssl_thread_id);
CRYPTO_set_locking_callback(ssl_thread_lock);
apr_pool_cleanup_register(p, NULL, ssl_thread_cleanup,
apr_pool_cleanup_null);
}
static int ssl_rand_choosenum(int l, int h)
{
int i;
char buf[50];
apr_snprintf(buf, sizeof(buf), "%.0f",
(((double)(rand()%RAND_MAX)/RAND_MAX)*(h-l)));
i = atoi(buf)+1;
if (i < l) i = l;
if (i > h) i = h;
return i;
}
static int ssl_rand_load_file(const char *file)
{
char buffer[APR_PATH_MAX];
int n;
if (file == NULL)
file = ssl_global_rand_file;
if (file && (strcmp(file, "builtin") == 0))
return -1;
if (file == NULL)
file = RAND_file_name(buffer, sizeof(buffer));
if (file) {
if (strncmp(file, "egd:", 4) == 0) {
if ((n = RAND_egd(file + 4)) > 0)
return n;
else
return -1;
}
if ((n = RAND_load_file(file, -1)) > 0)
return n;
}
return -1;
}
/*
* writes a number of random bytes (currently 1024) to
* file which can be used to initialize the PRNG by calling
* RAND_load_file() in a later session
*/
static int ssl_rand_save_file(const char *file)
{
char buffer[APR_PATH_MAX];
int n;
if (file == NULL)
file = RAND_file_name(buffer, sizeof(buffer));
else if ((n = RAND_egd(file)) > 0) {
return 0;
}
if (file == NULL || !RAND_write_file(file))
return 0;
else
return 1;
}
int SSL_rand_seed(const char *file)
{
unsigned char stackdata[256];
static volatile apr_uint32_t counter = 0;
if (ssl_rand_load_file(file) < 0) {
int n;
struct {
apr_time_t t;
pid_t p;
unsigned long i;
apr_uint32_t u;
} _ssl_seed;
if (counter == 0) {
apr_generate_random_bytes(stackdata, 256);
RAND_seed(stackdata, 128);
}
_ssl_seed.t = apr_time_now();
_ssl_seed.p = getpid();
_ssl_seed.i = ssl_thread_id();
apr_atomic_inc32(&counter);
_ssl_seed.u = counter;
RAND_seed((unsigned char *)&_ssl_seed, sizeof(_ssl_seed));
/*
* seed in some current state of the run-time stack (128 bytes)
*/
n = ssl_rand_choosenum(0, sizeof(stackdata)-128-1);
RAND_seed(stackdata + n, 128);
}
return RAND_status();
}
static int ssl_rand_make(const char *file, int len, int base64)
{
int r;
int num = len;
BIO *out = NULL;
out = BIO_new(BIO_s_file());
if (out == NULL)
return 0;
if ((r = BIO_write_filename(out, (char *)file)) < 0) {
BIO_free_all(out);
return 0;
}
if (base64) {
BIO *b64 = BIO_new(BIO_f_base64());
if (b64 == NULL) {
BIO_free_all(out);
return 0;
}
out = BIO_push(b64, out);
}
while (num > 0) {
unsigned char buf[4096];
int len = num;
if (len > sizeof(buf))
len = sizeof(buf);
r = RAND_bytes(buf, len);
if (r <= 0) {
BIO_free_all(out);
return 0;
}
BIO_write(out, buf, len);
num -= len;
}
BIO_flush(out);
BIO_free_all(out);
return 1;
}
TCN_IMPLEMENT_CALL(jint, SSL, initialize)(TCN_STDARGS, jstring engine)
{
int r = 0;
TCN_ALLOC_CSTRING(engine);
UNREFERENCED(o);
if (!tcn_global_pool) {
TCN_FREE_CSTRING(engine);
tcn_ThrowAPRException(e, APR_EINVAL);
return (jint)APR_EINVAL;
}
/* Check if already initialized */
if (ssl_initialized++) {
TCN_FREE_CSTRING(engine);
return (jint)APR_SUCCESS;
}
if (SSLeay() < 0x0090700L) {
TCN_FREE_CSTRING(engine);
tcn_ThrowAPRException(e, APR_EINVAL);
ssl_initialized = 0;
return (jint)APR_EINVAL;
}
/* We must register the library in full, to ensure our configuration
* code can successfully test the SSL environment.
*/
CRYPTO_malloc_init();
ERR_load_crypto_strings();
SSL_load_error_strings();
SSL_library_init();
#if HAVE_ENGINE_LOAD_BUILTIN_ENGINES
ENGINE_load_builtin_engines();
#endif
#if OPENSSL_VERSION_NUMBER >= 0x00907001
OPENSSL_load_builtin_modules();
#endif
#ifndef OPENSSL_NO_ENGINE
if (J2S(engine)) {
ENGINE *ee = NULL;
apr_status_t err = APR_SUCCESS;
if(strcmp(J2S(engine), "auto") == 0) {
ENGINE_register_all_complete();
}
else {
if ((ee = ENGINE_by_id(J2S(engine))) == NULL
&& (ee = ssl_try_load_engine(J2S(engine))) == NULL)
err = APR_ENOTIMPL;
else {
if (strcmp(J2S(engine), "chil") == 0)
ENGINE_ctrl(ee, ENGINE_CTRL_CHIL_SET_FORKCHECK, 1, 0, 0);
if (!ENGINE_set_default(ee, ENGINE_METHOD_ALL))
err = APR_ENOTIMPL;
}
/* Free our "structural" reference. */
if (ee)
ENGINE_free(ee);
}
if (err != APR_SUCCESS) {
TCN_FREE_CSTRING(engine);
ssl_init_cleanup(NULL);
tcn_ThrowAPRException(e, err);
return (jint)err;
}
tcn_ssl_engine = ee;
}
#endif
memset(&tcn_password_callback, 0, sizeof(tcn_pass_cb_t));
/* Initialize PRNG
* This will in most cases call the builtin
* low entropy seed.
*/
SSL_rand_seed(NULL);
/* For SSL_get_app_data2() at request time */
SSL_init_app_data2_idx();
SSL_TMP_KEYS_INIT(r);
if (r) {
TCN_FREE_CSTRING(engine);
ssl_init_cleanup(NULL);
tcn_ThrowAPRException(e, APR_ENOTIMPL);
return APR_ENOTIMPL;
}
/*
* Let us cleanup the ssl library when the library is unloaded
*/
apr_pool_cleanup_register(tcn_global_pool, NULL,
ssl_init_cleanup,
apr_pool_cleanup_null);
/* Initialize thread support */
ssl_thread_setup(tcn_global_pool);
TCN_FREE_CSTRING(engine);
return (jint)APR_SUCCESS;
}
TCN_IMPLEMENT_CALL(jboolean, SSL, randLoad)(TCN_STDARGS, jstring file)
{
TCN_ALLOC_CSTRING(file);
int r;
UNREFERENCED(o);
r = SSL_rand_seed(J2S(file));
TCN_FREE_CSTRING(file);
return r ? JNI_TRUE : JNI_FALSE;
}
TCN_IMPLEMENT_CALL(jboolean, SSL, randSave)(TCN_STDARGS, jstring file)
{
TCN_ALLOC_CSTRING(file);
int r;
UNREFERENCED(o);
r = ssl_rand_save_file(J2S(file));
TCN_FREE_CSTRING(file);
return r ? JNI_TRUE : JNI_FALSE;
}
TCN_IMPLEMENT_CALL(jboolean, SSL, randMake)(TCN_STDARGS, jstring file,
jint length, jboolean base64)
{
TCN_ALLOC_CSTRING(file);
int r;
UNREFERENCED(o);
r = ssl_rand_make(J2S(file), length, base64);
TCN_FREE_CSTRING(file);
return r ? JNI_TRUE : JNI_FALSE;
}
TCN_IMPLEMENT_CALL(void, SSL, randSet)(TCN_STDARGS, jstring file)
{
TCN_ALLOC_CSTRING(file);
UNREFERENCED(o);
if (J2S(file)) {
ssl_global_rand_file = apr_pstrdup(tcn_global_pool, J2S(file));
}
TCN_FREE_CSTRING(file);
}
/* OpenSSL Java Stream BIO */
typedef struct {
int refcount;
apr_pool_t *pool;
tcn_callback_t cb;
} BIO_JAVA;
static apr_status_t generic_bio_cleanup(void *data)
{
BIO *b = (BIO *)data;
if (b) {
BIO_free(b);
}
return APR_SUCCESS;
}
void SSL_BIO_close(BIO *bi)
{
if (bi == NULL)
return;
if (bi->ptr != NULL && (bi->flags & SSL_BIO_FLAG_CALLBACK)) {
BIO_JAVA *j = (BIO_JAVA *)bi->ptr;
j->refcount--;
if (j->refcount == 0) {
if (j->pool)
apr_pool_cleanup_run(j->pool, bi, generic_bio_cleanup);
else
BIO_free(bi);
}
}
else
BIO_free(bi);
}
void SSL_BIO_doref(BIO *bi)
{
if (bi == NULL)
return;
if (bi->ptr != NULL && (bi->flags & SSL_BIO_FLAG_CALLBACK)) {
BIO_JAVA *j = (BIO_JAVA *)bi->ptr;
j->refcount++;
}
}
static int jbs_new(BIO *bi)
{
BIO_JAVA *j;
if ((j = OPENSSL_malloc(sizeof(BIO_JAVA))) == NULL)
return 0;
j->pool = NULL;
j->refcount = 1;
bi->shutdown = 1;
bi->init = 0;
bi->num = -1;
bi->ptr = (char *)j;
return 1;
}
static int jbs_free(BIO *bi)
{
if (bi == NULL)
return 0;
if (bi->ptr != NULL) {
BIO_JAVA *j = (BIO_JAVA *)bi->ptr;
if (bi->init) {
JNIEnv *e = NULL;
bi->init = 0;
tcn_get_java_env(&e);
TCN_UNLOAD_CLASS(e, j->cb.obj);
}
OPENSSL_free(bi->ptr);
}
bi->ptr = NULL;
return 1;
}
static int jbs_write(BIO *b, const char *in, int inl)
{
jint ret = 0;
if (b->init && in != NULL) {
BIO_JAVA *j = (BIO_JAVA *)b->ptr;
JNIEnv *e = NULL;
jbyteArray jb = (*e)->NewByteArray(e, inl);
tcn_get_java_env(&e);
if (!(*e)->ExceptionOccurred(e)) {
(*e)->SetByteArrayRegion(e, jb, 0, inl, (jbyte *)in);
ret = (*e)->CallIntMethod(e, j->cb.obj,
j->cb.mid[0], jb);
(*e)->ReleaseByteArrayElements(e, jb, (jbyte *)in, JNI_ABORT);
(*e)->DeleteLocalRef(e, jb);
}
}
return ret;
}
static int jbs_read(BIO *b, char *out, int outl)
{
jint ret = 0;
if (b->init && out != NULL) {
BIO_JAVA *j = (BIO_JAVA *)b->ptr;
JNIEnv *e = NULL;
jbyteArray jb = (*e)->NewByteArray(e, outl);
tcn_get_java_env(&e);
if (!(*e)->ExceptionOccurred(e)) {
ret = (*e)->CallIntMethod(e, j->cb.obj,
j->cb.mid[1], jb);
if (ret > 0) {
jbyte *jout = (*e)->GetPrimitiveArrayCritical(e, jb, NULL);
memcpy(out, jout, ret);
(*e)->ReleasePrimitiveArrayCritical(e, jb, jout, 0);
}
(*e)->DeleteLocalRef(e, jb);
}
}
return ret;
}
static int jbs_puts(BIO *b, const char *in)
{
int ret = 0;
if (b->init && in != NULL) {
BIO_JAVA *j = (BIO_JAVA *)b->ptr;
JNIEnv *e = NULL;
tcn_get_java_env(&e);
ret = (*e)->CallIntMethod(e, j->cb.obj,
j->cb.mid[2],
tcn_new_string(e, in));
}
return ret;
}
static int jbs_gets(BIO *b, char *out, int outl)
{
int ret = 0;
if (b->init && out != NULL) {
BIO_JAVA *j = (BIO_JAVA *)b->ptr;
JNIEnv *e = NULL;
jobject o;
tcn_get_java_env(&e);
if ((o = (*e)->CallObjectMethod(e, j->cb.obj,
j->cb.mid[3], (jint)(outl - 1)))) {
TCN_ALLOC_CSTRING(o);
if (J2S(o)) {
int l = (int)strlen(J2S(o));
if (l < outl) {
strcpy(out, J2S(o));
ret = outl;
}
}
TCN_FREE_CSTRING(o);
}
}
return ret;
}
static long jbs_ctrl(BIO *b, int cmd, long num, void *ptr)
{
return 0;
}
static BIO_METHOD jbs_methods = {
BIO_TYPE_FILE,
"Java Callback",
jbs_write,
jbs_read,
jbs_puts,
jbs_gets,
jbs_ctrl,
jbs_new,
jbs_free,
NULL
};
static BIO_METHOD *BIO_jbs()
{
return(&jbs_methods);
}
TCN_IMPLEMENT_CALL(jlong, SSL, newBIO)(TCN_STDARGS, jlong pool,
jobject callback)
{
BIO *bio = NULL;
BIO_JAVA *j;
jclass cls;
UNREFERENCED(o);
if ((bio = BIO_new(BIO_jbs())) == NULL) {
tcn_ThrowException(e, "Create BIO failed");
goto init_failed;
}
j = (BIO_JAVA *)bio->ptr;
if ((j = (BIO_JAVA *)bio->ptr) == NULL) {
tcn_ThrowException(e, "Create BIO failed");
goto init_failed;
}
j->pool = J2P(pool, apr_pool_t *);
if (j->pool) {
apr_pool_cleanup_register(j->pool, (const void *)bio,
generic_bio_cleanup,
apr_pool_cleanup_null);
}
cls = (*e)->GetObjectClass(e, callback);
j->cb.mid[0] = (*e)->GetMethodID(e, cls, "write", "([B)I");
j->cb.mid[1] = (*e)->GetMethodID(e, cls, "read", "([B)I");
j->cb.mid[2] = (*e)->GetMethodID(e, cls, "puts", "(Ljava/lang/String;)I");
j->cb.mid[3] = (*e)->GetMethodID(e, cls, "gets", "(I)Ljava/lang/String;");
/* TODO: Check if method id's are valid */
j->cb.obj = (*e)->NewGlobalRef(e, callback);
bio->init = 1;
bio->flags = SSL_BIO_FLAG_CALLBACK;
return P2J(bio);
init_failed:
return 0;
}
TCN_IMPLEMENT_CALL(jint, SSL, closeBIO)(TCN_STDARGS, jlong bio)
{
BIO *b = J2P(bio, BIO *);
UNREFERENCED_STDARGS;
SSL_BIO_close(b);
return APR_SUCCESS;
}
TCN_IMPLEMENT_CALL(void, SSL, setPasswordCallback)(TCN_STDARGS,
jobject callback)
{
jclass cls;
UNREFERENCED(o);
if (tcn_password_callback.cb.obj) {
TCN_UNLOAD_CLASS(e,
tcn_password_callback.cb.obj);
}
cls = (*e)->GetObjectClass(e, callback);
tcn_password_callback.cb.mid[0] = (*e)->GetMethodID(e, cls, "callback",
"(Ljava/lang/String;)Ljava/lang/String;");
/* TODO: Check if method id is valid */
tcn_password_callback.cb.obj = (*e)->NewGlobalRef(e, callback);
}
TCN_IMPLEMENT_CALL(void, SSL, setPassword)(TCN_STDARGS, jstring password)
{
TCN_ALLOC_CSTRING(password);
UNREFERENCED(o);
if (J2S(password)) {
strncpy(tcn_password_callback.password, J2S(password), SSL_MAX_PASSWORD_LEN);
tcn_password_callback.password[SSL_MAX_PASSWORD_LEN-1] = '\0';
}
TCN_FREE_CSTRING(password);
}
TCN_IMPLEMENT_CALL(jboolean, SSL, generateRSATempKey)(TCN_STDARGS, jint idx)
{
int r = 1;
UNREFERENCED_STDARGS;
SSL_TMP_KEY_FREE(RSA, idx);
switch (idx) {
case SSL_TMP_KEY_RSA_512:
r = SSL_TMP_KEY_INIT_RSA(512);
break;
case SSL_TMP_KEY_RSA_1024:
r = SSL_TMP_KEY_INIT_RSA(1024);
break;
case SSL_TMP_KEY_RSA_2048:
r = SSL_TMP_KEY_INIT_RSA(2048);
break;
case SSL_TMP_KEY_RSA_4096:
r = SSL_TMP_KEY_INIT_RSA(4096);
break;
}
return r ? JNI_FALSE : JNI_TRUE;
}
TCN_IMPLEMENT_CALL(jboolean, SSL, loadDSATempKey)(TCN_STDARGS, jint idx,
jstring file)
{
jboolean r = JNI_FALSE;
TCN_ALLOC_CSTRING(file);
DH *dh;
UNREFERENCED(o);
if (!J2S(file))
return JNI_FALSE;
SSL_TMP_KEY_FREE(DSA, idx);
if ((dh = SSL_dh_get_param_from_file(J2S(file)))) {
SSL_temp_keys[idx] = dh;
r = JNI_TRUE;
}
TCN_FREE_CSTRING(file);
return r;
}
TCN_IMPLEMENT_CALL(jstring, SSL, getLastError)(TCN_STDARGS)
{
char buf[256];
UNREFERENCED(o);
ERR_error_string(ERR_get_error(), buf);
return tcn_new_string(e, buf);
}
#else
/* OpenSSL is not supported.
* Create empty stubs.
*/
TCN_IMPLEMENT_CALL(jint, SSL, version)(TCN_STDARGS)
{
UNREFERENCED_STDARGS;
return 0;
}
TCN_IMPLEMENT_CALL(jstring, SSL, versionString)(TCN_STDARGS)
{
UNREFERENCED_STDARGS;
return NULL;
}
TCN_IMPLEMENT_CALL(jint, SSL, initialize)(TCN_STDARGS, jstring engine)
{
UNREFERENCED(o);
UNREFERENCED(engine);
tcn_ThrowAPRException(e, APR_ENOTIMPL);
return (jint)APR_ENOTIMPL;
}
TCN_IMPLEMENT_CALL(jboolean, SSL, randLoad)(TCN_STDARGS, jstring file)
{
UNREFERENCED_STDARGS;
UNREFERENCED(file);
return JNI_FALSE;
}
TCN_IMPLEMENT_CALL(jboolean, SSL, randSave)(TCN_STDARGS, jstring file)
{
UNREFERENCED_STDARGS;
return JNI_FALSE;
}
TCN_IMPLEMENT_CALL(jboolean, SSL, randMake)(TCN_STDARGS, jstring file,
jint length, jboolean base64)
{
UNREFERENCED_STDARGS;
UNREFERENCED(file);
UNREFERENCED(length);
UNREFERENCED(base64);
return JNI_FALSE;
}
TCN_IMPLEMENT_CALL(jlong, SSL, newBIO)(TCN_STDARGS, jlong pool,
jobject callback)
{
UNREFERENCED_STDARGS;
UNREFERENCED(pool);
UNREFERENCED(callback);
return 0;
}
TCN_IMPLEMENT_CALL(jint, SSL, closeBIO)(TCN_STDARGS, jlong bio)
{
UNREFERENCED_STDARGS;
UNREFERENCED(bio);
return (jint)APR_ENOTIMPL;
}
TCN_IMPLEMENT_CALL(void, SSL, setPasswordCallback)(TCN_STDARGS,
jobject callback)
{
UNREFERENCED_STDARGS;
UNREFERENCED(callback);
}
TCN_IMPLEMENT_CALL(void, SSL, setPassword)(TCN_STDARGS, jstring password)
{
UNREFERENCED_STDARGS;
UNREFERENCED(password);
}
TCN_IMPLEMENT_CALL(jboolean, SSL, generateRSATempKey)(TCN_STDARGS, jint idx)
{
UNREFERENCED_STDARGS;
UNREFERENCED(idx);
return JNI_FALSE;
}
TCN_IMPLEMENT_CALL(jboolean, SSL, loadDSATempKey)(TCN_STDARGS, jint idx,
jstring file)
{
UNREFERENCED_STDARGS;
UNREFERENCED(idx);
UNREFERENCED(file);
return JNI_FALSE;
}
TCN_IMPLEMENT_CALL(jstring, SSL, getLastError)(TCN_STDARGS)
{
UNREFERENCED_STDARGS;
return NULL;
}
#endif