From 5fe48c91f5fa2bd20d65ae27c96feecc544f5d2c Mon Sep 17 00:00:00 2001 From: Hussein Kasem Date: Thu, 6 Aug 2020 20:18:15 +0200 Subject: [PATCH] JNI-114 Add PassphraseType to the passphraseCallback --- src/Makefile | 7 ++- .../pEp/jniadapter/AbstractEngine.java | 4 +- src/foundation/pEp/jniadapter/Sync.java | 2 +- ...oundation_pEp_jniadapter_AbstractEngine.cc | 58 +++++++++++++++---- src/gen_cpp_Engine.ysl2 | 4 +- src/pEp.yml2 | 6 +- src/passphrase_callback.hh | 2 +- src/passphrase_callback.hxx | 5 +- .../pEp/jniadapter/test/jni114/TestAlice.java | 3 +- 9 files changed, 68 insertions(+), 23 deletions(-) diff --git a/src/Makefile b/src/Makefile index 29ba667..e1a412b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -69,7 +69,7 @@ PEP_HEADER:=$(shell $(CXX) $(CXXFLAGS) -E -M get_header.cc | grep -oe '[^[:space .PHONY: all all: $(JAR) $(SHARED) -$(JAR): status_list.yml2 $(JAVA_SOURCES) $(C_SOURCES) +$(JAR): status_list.yml2 passphrase_status_list.yml2 $(JAVA_SOURCES) $(C_SOURCES) $(JP)/javac foundation/pEp/jniadapter/*.java $(JP)/jar cf $@ foundation/pEp/jniadapter/*.class @@ -96,6 +96,9 @@ $(SHARED): $(LIBRARY) status_list.yml2: pEp.yml2 bash ../utils/extract_pEp_status_codes_from_engine.sh "$(PEP_HEADER)" $@ +passphrase_status_list.yml2: status_list.yml2 + grep passphrase $< > $@ + foundation/pEp/jniadapter/pEpException.java: pEp.yml2 gen_java_exceptions.ysl2 pEp.yml2 $(YML2_PROC) -y gen_java_exceptions.ysl2 $< -o $@ @@ -139,6 +142,8 @@ clean: rm -f foundation/pEp/jniadapter/SyncHandshakeResult.java rm -f foundation/pEp/jniadapter/SyncHandshakeSignal.java rm -f foundation/pEp/jniadapter/CipherSuite.java + rm -f foundation/pEp/jniadapter/PassphraseType.java rm -f throw_pEp_exception.* rm -f foundation_pEp_jniadapter_Message.cc foundation_pEp_jniadapter_Engine.cc rm -f status_list.yml2 + rm -f passphrase_status_list.yml2 diff --git a/src/foundation/pEp/jniadapter/AbstractEngine.java b/src/foundation/pEp/jniadapter/AbstractEngine.java index 92adbd2..cb56de8 100644 --- a/src/foundation/pEp/jniadapter/AbstractEngine.java +++ b/src/foundation/pEp/jniadapter/AbstractEngine.java @@ -193,11 +193,11 @@ abstract class AbstractEngine extends UniquelyIdentifiable implements AutoClosea return 0; } - public byte[] passphraseRequiredFromC() { + public byte[] passphraseRequiredFromC(final PassphraseType passphraseType) { String ret = ""; if (passphraseRequiredCallback != null) { System.out.println("calling passphraseRequiredCallback on engine ObjID:" + getId()); - ret = passphraseRequiredCallback.passphraseRequired(); + ret = passphraseRequiredCallback.passphraseRequired(passphraseType); } else { System.out.println("no callback registered on engine ObjID:" + getId()); // if this happens (no callback registered diff --git a/src/foundation/pEp/jniadapter/Sync.java b/src/foundation/pEp/jniadapter/Sync.java index e83211e..7593477 100644 --- a/src/foundation/pEp/jniadapter/Sync.java +++ b/src/foundation/pEp/jniadapter/Sync.java @@ -20,7 +20,7 @@ public interface Sync { } interface PassphraseRequiredCallback { - String passphraseRequired(); + String passphraseRequired(final PassphraseType pEpStatus); } public class DefaultCallback diff --git a/src/foundation_pEp_jniadapter_AbstractEngine.cc b/src/foundation_pEp_jniadapter_AbstractEngine.cc index ce5edff..026e18b 100644 --- a/src/foundation_pEp_jniadapter_AbstractEngine.cc +++ b/src/foundation_pEp_jniadapter_AbstractEngine.cc @@ -21,20 +21,24 @@ JavaVM *jvm= nullptr; std::mutex mutex_obj; -jfieldID field_value = nullptr; +jfieldID signal_field_value = nullptr; +jfieldID passphrase_type_field_value = nullptr; jmethodID messageConstructorMethodID = nullptr; jmethodID messageToSendMethodID = nullptr; jmethodID notifyHandShakeMethodID = nullptr; jmethodID needsFastPollMethodID = nullptr; jmethodID passphraseRequiredMethodID = nullptr; -jmethodID method_values = nullptr; +jmethodID sync_handshake_signal_values = nullptr; +jmethodID passphrase_status_values = nullptr; +jmethodID passphrase_callback_values = nullptr; jobject objj = nullptr; jclass messageClass = nullptr; -jclass identityClass = nullptr;; +jclass identityClass = nullptr; jclass signalClass = nullptr; jclass engineClass = nullptr; +jclass passphraseTypeClass = nullptr; namespace JNISync { JNIEnv* env() { @@ -72,6 +76,8 @@ void jni_init() { _env->NewGlobalRef(findClass(_env, "foundation/pEp/jniadapter/_Identity"))); signalClass = reinterpret_cast( _env->NewGlobalRef(findClass(_env, "foundation/pEp/jniadapter/SyncHandshakeSignal"))); + passphraseTypeClass = reinterpret_cast( + _env->NewGlobalRef(findClass(_env, "foundation/pEp/jniadapter/PassphraseType"))); engineClass = reinterpret_cast(_env->NewGlobalRef(findClass(_env, "foundation/pEp/jniadapter/Engine"))); messageConstructorMethodID = _env->GetMethodID(messageClass, "", "(J)V"); @@ -90,19 +96,47 @@ void jni_init() { passphraseRequiredMethodID = _env->GetMethodID( engineClass, "passphraseRequiredFromC", - "()[B"); + "(Lfoundation/pEp/jniadapter/PassphraseType;)[B"); - method_values = JNISync::env()->GetStaticMethodID(signalClass, "values", + sync_handshake_signal_values = JNISync::env()->GetStaticMethodID(signalClass, "values", "()[Lfoundation/pEp/jniadapter/SyncHandshakeSignal;"); - field_value = JNISync::env()->GetFieldID(signalClass, "value", "I"); + passphrase_status_values = JNISync::env()->GetStaticMethodID(passphraseTypeClass, "values", + "()[Lfoundation/pEp/jniadapter/PassphraseType;"); + signal_field_value = JNISync::env()->GetFieldID(signalClass, "value", "I"); + passphrase_type_field_value = JNISync::env()->GetFieldID(passphraseTypeClass, "value", "I"); } -char* JNIAdapter::passphraseRequiredCallback() { +char* JNIAdapter::passphraseRequiredCallback(const PEP_STATUS status) { pEpLog("called"); + jobject status_ = nullptr; + { + assert(passphraseTypeClass); + assert(passphrase_status_values); + assert(passphrase_type_field_value); + + jobjectArray values = (jobjectArray) JNISync::env()->CallStaticObjectMethod(passphraseTypeClass, + passphrase_status_values); + + if (JNISync::env()->ExceptionCheck()) { + JNISync::env()->ExceptionClear(); + throw_pEp_Exception(JNISync::env(), PEP_UNKNOWN_ERROR); + } + jsize values_size = JNISync::env()->GetArrayLength(values); + for (jsize i = 0; i < values_size; i++) { + jobject element = JNISync::env()->GetObjectArrayElement(values, i); + assert(element); + jint value = JNISync::env()->GetIntField(element, passphrase_type_field_value); + if (value == (jint) status) { + status_ = element; + break; + } + JNISync::env() -> DeleteLocalRef(element); + } + } assert(objj && passphraseRequiredMethodID); - jobject ppJO = JNISync::env()->CallObjectMethod(objj, passphraseRequiredMethodID); + jobject ppJO = JNISync::env()->CallObjectMethod(objj, passphraseRequiredMethodID, status_); if (JNISync::env()->ExceptionCheck()) { JNISync::env()->ExceptionDescribe(); JNISync::env()->ExceptionClear(); @@ -160,11 +194,11 @@ PEP_STATUS notifyHandshake(pEp_identity *me, pEp_identity *partner, sync_handsha jobject signal_ = nullptr; { assert(signalClass); - assert(method_values); - assert(field_value); + assert(sync_handshake_signal_values); + assert(signal_field_value); jobjectArray values = (jobjectArray) JNISync::env()->CallStaticObjectMethod(signalClass, - method_values); + sync_handshake_signal_values); if (JNISync::env()->ExceptionCheck()) { JNISync::env()->ExceptionClear(); return PEP_UNKNOWN_ERROR; @@ -174,7 +208,7 @@ PEP_STATUS notifyHandshake(pEp_identity *me, pEp_identity *partner, sync_handsha for (jsize i = 0; i < values_size; i++) { jobject element = JNISync::env()->GetObjectArrayElement(values, i); assert(element); - jint value = JNISync::env()->GetIntField(element, field_value); + jint value = JNISync::env()->GetIntField(element, signal_field_value); if (value == (jint) signal) { signal_ = element; break; diff --git a/src/gen_cpp_Engine.ysl2 b/src/gen_cpp_Engine.ysl2 index 3e52f11..d4e2e90 100644 --- a/src/gen_cpp_Engine.ysl2 +++ b/src/gen_cpp_Engine.ysl2 @@ -80,11 +80,11 @@ tstylesheet { pEpLog("calling passphrase_cache.api(::«@name»())"); status = passphrase_cache.api(::«@name»,session()`apply "parm", mode=call`); pEpLog("PEP_STATUS:" << status); - if(status == PEP_PASSPHRASE_REQUIRED || status == PEP_WRONG_PASSPHRASE ) { + if(status == PEP_PASSPHRASE_REQUIRED || status == PEP_WRONG_PASSPHRASE || status == PEP_PASSPHRASE_FOR_NEW_KEYS_REQUIRED) { pEpLog("none of the cached passphrases worked"); if(retryCount < maxRetries) { // call the app - char* _passphrase = passphraseRequiredCallback(); + char* _passphrase = passphraseRequiredCallback(status); pEpLog("callback returned, config_passphrase() with new passphrase"); PEP_STATUS status = ::config_passphrase(session(),passphrase_cache.add(_passphrase)); retryAgain = true; diff --git a/src/pEp.yml2 b/src/pEp.yml2 index c3022fa..d446b3a 100644 --- a/src/pEp.yml2 +++ b/src/pEp.yml2 @@ -10,7 +10,11 @@ namespace pEp { exception Status { include ./status_list.yml2 }; - + + enum PassphraseType { + include ./passphrase_status_list.yml2 + }; + enum Color { PEP_color_no_color > 0 PEP_color_yellow > 1 diff --git a/src/passphrase_callback.hh b/src/passphrase_callback.hh index 8482077..30808dd 100644 --- a/src/passphrase_callback.hh +++ b/src/passphrase_callback.hh @@ -5,7 +5,7 @@ namespace pEp { namespace JNIAdapter { - char* passphraseRequiredCallback(); + char* passphraseRequiredCallback(const PEP_STATUS status); template PEP_STATUS passphraseWrap( PEP_STATUS f(PEP_SESSION, A...), PEP_SESSION session, A... a); diff --git a/src/passphrase_callback.hxx b/src/passphrase_callback.hxx index 20bfa36..63603f3 100644 --- a/src/passphrase_callback.hxx +++ b/src/passphrase_callback.hxx @@ -17,11 +17,12 @@ namespace pEp { pEpLog("calling passphrase_cache.api from basic_api"); status = passphrase_cache.api(f, session, a...); pEpLog("PEP_STATUS:" << status); - if (status == PEP_PASSPHRASE_REQUIRED || status == PEP_WRONG_PASSPHRASE) { + if (status == PEP_PASSPHRASE_REQUIRED || status == PEP_WRONG_PASSPHRASE + || status == PEP_PASSPHRASE_FOR_NEW_KEYS_REQUIRED) { pEpLog("none of the cached passphrases worked"); if (retryCount < maxRetries) { // call the app - char *_passphrase = passphraseRequiredCallback(); + char *_passphrase = passphraseRequiredCallback(status); pEpLog("callback returned, config_passphrase() with new passphrase"); PEP_STATUS status = ::config_passphrase(session, passphrase_cache.add(_passphrase)); diff --git a/test/java/foundation/pEp/jniadapter/test/jni114/TestAlice.java b/test/java/foundation/pEp/jniadapter/test/jni114/TestAlice.java index cc09858..e6a753a 100644 --- a/test/java/foundation/pEp/jniadapter/test/jni114/TestAlice.java +++ b/test/java/foundation/pEp/jniadapter/test/jni114/TestAlice.java @@ -50,10 +50,11 @@ class TestAlice { // Register callback passphraseRequired() ctx.engine.setPassphraseRequiredCallback(new Sync.PassphraseRequiredCallback() { @Override - public String passphraseRequired() { + public String passphraseRequired(PassphraseType type) { log("passphraseRequired() called"); log("Please Enter Passphrase..."); sleep(2000); + assert type == PassphraseType.pEpPassphraseRequired; return "passphrase_alice"; } });