From 47d36cb0cc4216e059af3c7dcdfdda972e262304 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Mon, 15 Jan 2024 16:45:14 -0700 Subject: [PATCH] JSSE: enable native wolfSSL debug logs at SSLContext and WolfSSLProvider levels, register Java logging callback to push native logs over System.out.println and include thread ID --- native/com_wolfssl_WolfSSL.c | 37 +++++++++++++-- scripts/infer.sh | 1 + src/java/com/wolfssl/WolfSSL.java | 3 ++ .../wolfssl/provider/jsse/WolfSSLContext.java | 6 +++ .../wolfssl/provider/jsse/WolfSSLDebug.java | 45 ++++++++++++++++++ .../jsse/WolfSSLNativeLoggingCallback.java | 47 +++++++++++++++++++ .../provider/jsse/WolfSSLProvider.java | 12 ++--- 7 files changed, 138 insertions(+), 13 deletions(-) create mode 100644 src/java/com/wolfssl/provider/jsse/WolfSSLNativeLoggingCallback.java diff --git a/native/com_wolfssl_WolfSSL.c b/native/com_wolfssl_WolfSSL.c index 833a467..86b0d4e 100644 --- a/native/com_wolfssl_WolfSSL.c +++ b/native/com_wolfssl_WolfSSL.c @@ -800,19 +800,24 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSL_setLoggingCb ret = wolfSSL_SetLoggingCb(NativeLoggingCallback); } + else { + /* reset back to null */ + ret = wolfSSL_SetLoggingCb(NULL); + } return ret; } void NativeLoggingCallback(const int logLevel, const char *const logMessage) { - JNIEnv* jenv; + JNIEnv* jenv = NULL; jint vmret = 0; jclass excClass; jclass logClass; jmethodID logMethod; + jstring logMsg; + int needsDetach = 0; /* Should we explicitly detach? */ jobjectRefType refcheck; - jstring logMsg; /* get JNIEnv from JavaVM */ vmret = (int)((*g_vm)->GetEnv(g_vm, (void**) &jenv, JNI_VERSION_1_6)); @@ -822,11 +827,16 @@ void NativeLoggingCallback(const int logLevel, const char *const logMessage) #else vmret = (*g_vm)->AttachCurrentThread(g_vm, (void**) &jenv, NULL); #endif - if (vmret) { - printf("Failed to attach JNIEnv to thread\n"); + /* (*jenv) may be NULL if JVM is shutting down */ + if ((vmret != JNI_OK) || (jenv == NULL) || (*jenv == NULL)) { + printf("Failed to attach to thread in NativeLoggingCallback\n"); + return; } + needsDetach = 1; + } else if (vmret != JNI_OK) { - printf("Unable to get JNIEnv from JavaVM\n"); + printf("Unable to get JNIEnv from JavaVM in NativeLoggingCallback\n"); + return; } /* find exception class */ @@ -834,6 +844,9 @@ void NativeLoggingCallback(const int logLevel, const char *const logMessage) if ((*jenv)->ExceptionOccurred(jenv)) { (*jenv)->ExceptionDescribe(jenv); (*jenv)->ExceptionClear(jenv); + if (needsDetach == 1) { + (*g_vm)->DetachCurrentThread(g_vm); + } return; } @@ -851,6 +864,10 @@ void NativeLoggingCallback(const int logLevel, const char *const logMessage) (*jenv)->ThrowNew(jenv, excClass, "Can't get native WolfSSLLoggingCallback class reference"); + + if (needsDetach == 1) { + (*g_vm)->DetachCurrentThread(g_vm); + } return; } @@ -864,6 +881,9 @@ void NativeLoggingCallback(const int logLevel, const char *const logMessage) } (*jenv)->ThrowNew(jenv, excClass, "Error getting loggingCallback method from JNI"); + if (needsDetach == 1) { + (*g_vm)->DetachCurrentThread(g_vm); + } return; } @@ -879,6 +899,9 @@ void NativeLoggingCallback(const int logLevel, const char *const logMessage) (*jenv)->ThrowNew(jenv, excClass, "Error calling logging callback from JNI"); + if (needsDetach == 1) { + (*g_vm)->DetachCurrentThread(g_vm); + } return; } @@ -891,6 +914,10 @@ void NativeLoggingCallback(const int logLevel, const char *const logMessage) (*jenv)->ThrowNew(jenv, excClass, "Object reference invalid in NativeLoggingCallback"); } + + if (needsDetach == 1) { + (*g_vm)->DetachCurrentThread(g_vm); + } } void NativeFIPSErrorCallback(const int ok, const int err, diff --git a/scripts/infer.sh b/scripts/infer.sh index 5045b00..7ec8822 100755 --- a/scripts/infer.sh +++ b/scripts/infer.sh @@ -57,6 +57,7 @@ infer run -- javac \ src/java/com/wolfssl/provider/jsse/WolfSSLInternalVerifyCb.java \ src/java/com/wolfssl/provider/jsse/WolfSSLKeyManager.java \ src/java/com/wolfssl/provider/jsse/WolfSSLKeyX509.java \ + src/java/com/wolfssl/provider/jsse/WolfSSLNativeLoggingCallback.java \ src/java/com/wolfssl/provider/jsse/WolfSSLParametersHelper.java \ src/java/com/wolfssl/provider/jsse/WolfSSLParameters.java \ src/java/com/wolfssl/provider/jsse/WolfSSLProvider.java \ diff --git a/src/java/com/wolfssl/WolfSSL.java b/src/java/com/wolfssl/WolfSSL.java index bb2c864..1c4cb1e 100644 --- a/src/java/com/wolfssl/WolfSSL.java +++ b/src/java/com/wolfssl/WolfSSL.java @@ -1482,6 +1482,9 @@ public class WolfSSL { { synchronized(cleanupLock) { if (this.active == true) { + /* reset logging callback before calling cleanup() */ + this.setLoggingCb(null); + /* free resources, set state */ this.cleanup(); this.active = false; diff --git a/src/java/com/wolfssl/provider/jsse/WolfSSLContext.java b/src/java/com/wolfssl/provider/jsse/WolfSSLContext.java index d21fb06..1379f6a 100644 --- a/src/java/com/wolfssl/provider/jsse/WolfSSLContext.java +++ b/src/java/com/wolfssl/provider/jsse/WolfSSLContext.java @@ -66,6 +66,12 @@ public class WolfSSLContext extends SSLContextSpi { long method; String[] ciphersIana = null; + /* Enable native wolfSSL debug logging if 'wolfssl.debug' + * System property is set. Also attempted in WolfSSLProvider + * but System property may not have been set by user yet at that + * point. */ + WolfSSLDebug.setNativeWolfSSLDebugging(); + /* Get available wolfSSL cipher suites in IANA format */ ciphersIana = WolfSSL.getCiphersAvailableIana(this.currentVersion); diff --git a/src/java/com/wolfssl/provider/jsse/WolfSSLDebug.java b/src/java/com/wolfssl/provider/jsse/WolfSSLDebug.java index 6db2933..1e515ba 100644 --- a/src/java/com/wolfssl/provider/jsse/WolfSSLDebug.java +++ b/src/java/com/wolfssl/provider/jsse/WolfSSLDebug.java @@ -24,6 +24,9 @@ package com.wolfssl.provider.jsse; import java.util.Date; import java.sql.Timestamp; +import com.wolfssl.WolfSSL; +import com.wolfssl.WolfSSLLoggingCallback; + /** * Central location for all debugging messages * @@ -48,6 +51,13 @@ public class WolfSSLDebug { */ public static final String INFO = "INFO"; + /** + * Native wolfSSL logging callback. + * Used to print native wolfSSL debug logs when 'wolfssl.debug' System + * property is set to "true". + */ + private static WolfSSLNativeLoggingCallback nativeLogCb = null; + private static boolean checkProperty() { String enabled = System.getProperty("wolfjsse.debug"); @@ -119,5 +129,40 @@ public class WolfSSLDebug { System.out.println(""); } } + + /** + * Enable native wolfSSL debug logging based on value of the + * 'wolfssl.debug' System property. + * + * Native wolfSSL must ben compiled with "--enable-debug" or + * DEBUG_WOLFSSL defined in order for debug logs to print. + */ + protected static synchronized void setNativeWolfSSLDebugging() { + + String wolfsslDebug = System.getProperty("wolfssl.debug"); + + if ((wolfsslDebug != null) && (wolfsslDebug.equalsIgnoreCase("true"))) { + + WolfSSL.debuggingON(); + } + + /* Register our default logging callback for native wolfSSL logs */ + setDefaultNativeLoggingCallback(); + } + + /** + * Register default native wolfSSL logging callback. + * Default callback class is WolfSSLNativeLoggingCallback. This could be + * modified in the future to allow a custom user-registerable callback. + */ + protected static synchronized void setDefaultNativeLoggingCallback() { + + /* Only create one logging callback object */ + if (nativeLogCb == null) { + nativeLogCb = new WolfSSLNativeLoggingCallback(); + } + + WolfSSL.setLoggingCb(nativeLogCb); + } } diff --git a/src/java/com/wolfssl/provider/jsse/WolfSSLNativeLoggingCallback.java b/src/java/com/wolfssl/provider/jsse/WolfSSLNativeLoggingCallback.java new file mode 100644 index 0000000..dc64d9a --- /dev/null +++ b/src/java/com/wolfssl/provider/jsse/WolfSSLNativeLoggingCallback.java @@ -0,0 +1,47 @@ +/* WolfSSLNativeLoggingCallback.java + * + * Copyright (C) 2006-2023 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ +package com.wolfssl.provider.jsse; + +import java.util.Date; +import java.sql.Timestamp; + +import com.wolfssl.WolfSSLLoggingCallback; + +/** + * Utility class to help with JSSE-level functionality. + * + * Native logging callback class, implements com.wolfssl.WolfSSLLoggingCallback. + * loggingCallback() method is called by native wolfSSL debug logging + * mechanism. + * + * @author wolfSSL + */ +class WolfSSLNativeLoggingCallback implements WolfSSLLoggingCallback +{ + public synchronized void loggingCallback(int logLevel, String logMessage) { + + System.out.println(new Timestamp(new java.util.Date().getTime()) + + " [wolfSSL: TID " + + Thread.currentThread().getId() + + "] " + logMessage); + } +} + diff --git a/src/java/com/wolfssl/provider/jsse/WolfSSLProvider.java b/src/java/com/wolfssl/provider/jsse/WolfSSLProvider.java index bd7684c..1b9d47a 100644 --- a/src/java/com/wolfssl/provider/jsse/WolfSSLProvider.java +++ b/src/java/com/wolfssl/provider/jsse/WolfSSLProvider.java @@ -28,9 +28,7 @@ import com.wolfssl.WolfSSLFIPSErrorCallback; /** * wolfSSL JSSE Provider implementation - * * @author wolfSSL - * @version 1.8 */ public final class WolfSSLProvider extends Provider { @@ -103,12 +101,10 @@ public final class WolfSSLProvider extends Provider { "Failed to initialize native wolfSSL library"); } - /* enable native wolfSSL debug logging, native wolfSSL must be - * compiled with --enable-debug */ - String wolfsslDebug = System.getProperty("wolfssl.debug"); - if ((wolfsslDebug != null) && (wolfsslDebug.equalsIgnoreCase("true"))) { - WolfSSL.debuggingON(); - } + /* Enable native wolfSSL debug logging if 'wolfssl.debug' System + * property has been set to "true" and native wolfSSL compiled with + * '--enable-debug' */ + WolfSSLDebug.setNativeWolfSSLDebugging(); /* Key Factory */ put("KeyManagerFactory.PKIX",