aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeorge Tang <gtang@affinegy.com>2016-09-25 16:06:49 -0500
committerGeorge Tang <gtang@affinegy.com>2016-09-26 12:30:59 -0500
commitd580585f1abb0804c0c1d27118fb64d97084bcc3 (patch)
tree5e74e6fef52f509449db41137a7a0c3f870edcba
parent9112fc14667939b5a41f9d804484939e5a72f035 (diff)
ASACORE-3156 Sec2 ListenerFixes and ClaimTest
These comments are in the same rough order as the changes ApplicationStateListener and PermissionConfigurationListener were holding weak references, so anonymous class idiom in java could be garbage collected and weak reference would be gone. Fixed some mistakes in PermissionConfigurator and SecurityApplicationProxy was using certificateAuthority instead of admin variable. In SecurityApplication Proxy, made calls to SecureConnection after updatePolicy and updateIdentity as the comments for these methods directed people to use. I had assumed that the listeners did not need to be persisted, because method calls into alljoyn core would deep copy. I was wrong about not using pointers to listeners. It caused errors for me when writing tests. So I used pointers instead, and added some memory management code to clean up these pointers. I also assumed some bytearrays could be local, because I assumed some deep copying, but I was wrong. So instead of using JLocalRef<jbyteArray> I am using jbyteArray. These objects are passed back to java threads, so java threads will garbage collect. I got rid of some local method ids and field ids and instead used the global ones. I also added some methods to BusAttachment that were under CredentialAccessor in core but were not available in java. getGuid and getDSAPrivateKey. I also added a test that was able to claim via PermissionConfigurator and SecurityApplicationProxy Change-Id: I4a924bd0c370fd8977afac26c0fcf9aa09b2a9a9 Signed-off-by: George Tang <gtang@affinegy.com>
-rw-r--r--alljoyn_java/jni/CertificateX509.cc10
-rw-r--r--alljoyn_java/jni/JApplicationStateListener.cc29
-rw-r--r--alljoyn_java/jni/JApplicationStateListener.h4
-rw-r--r--alljoyn_java/jni/JBusAttachment.h21
-rw-r--r--alljoyn_java/jni/JPermissionConfigurationListener.cc63
-rw-r--r--alljoyn_java/jni/JPermissionConfigurationListener.h2
-rw-r--r--alljoyn_java/jni/PermissionConfigurator.cc106
-rw-r--r--alljoyn_java/jni/SecurityApplicationProxy.cc47
-rw-r--r--alljoyn_java/jni/alljoyn_java.cc72
-rw-r--r--alljoyn_java/src/org/alljoyn/bus/BusAttachment.java2
-rw-r--r--alljoyn_java/src/org/alljoyn/bus/SecurityApplicationProxy.java10
-rw-r--r--alljoyn_java/src/org/alljoyn/bus/common/ECCPublicKey.java30
-rw-r--r--alljoyn_java/test/org/alljoyn/bus/SecurityManagementTest.java306
13 files changed, 504 insertions, 198 deletions
diff --git a/alljoyn_java/jni/CertificateX509.cc b/alljoyn_java/jni/CertificateX509.cc
index 98198e1..1ac6a77 100644
--- a/alljoyn_java/jni/CertificateX509.cc
+++ b/alljoyn_java/jni/CertificateX509.cc
@@ -320,14 +320,14 @@ JNIEXPORT jobject JNICALL Java_org_alljoyn_bus_common_CertificateX509_decodePriv
return NULL;
}
- JLocalRef<jbyteArray> jeccD = ToJByteArray(eccPrivateKey.GetD(), eccPrivateKey.GetDSize());
+ jbyteArray jeccD = ToJByteArray(eccPrivateKey.GetD(), eccPrivateKey.GetDSize());
if (jenv->ExceptionCheck()) {
QCC_LogError(ER_FAIL, ("%s: exception converting byte array", __FUNCTION__));
return NULL;
}
- jobject retObj = jenv->NewObject(CLS_ECCPrivateKey, MID_ECCPrivateKey_cnstrctr, jeccD.move());
+ jobject retObj = jenv->NewObject(CLS_ECCPrivateKey, MID_ECCPrivateKey_cnstrctr, jeccD);
if (jenv->ExceptionCheck()) {
QCC_LogError(ER_FAIL, ("%s: exception converting byte array", __FUNCTION__));
@@ -1780,10 +1780,10 @@ JNIEXPORT jobjectArray JNICALL Java_org_alljoyn_bus_common_CertificateX509_decod
}
jmethodID mid = jenv->GetMethodID(CLS_CertificateX509, "<init>", "()V");
- JLocalRef<jobjectArray> retArray = jenv->NewObjectArray(jcertExpectedCount, CLS_CertificateX509, NULL);
+ jobjectArray retArray = jenv->NewObjectArray(jcertExpectedCount, CLS_CertificateX509, NULL);
for (jlong i = 0; i < jcertExpectedCount; i++) {
- JLocalRef<jobject> jcert = jenv->NewObject(CLS_CertificateX509, mid);
+ jobject jcert = jenv->NewObject(CLS_CertificateX509, mid);
if (!jcert) {
delete [] certArray;
return NULL;
@@ -1810,7 +1810,7 @@ JNIEXPORT jobjectArray JNICALL Java_org_alljoyn_bus_common_CertificateX509_decod
}
delete [] certArray;
- return retArray.move();
+ return retArray;
}
/*
diff --git a/alljoyn_java/jni/JApplicationStateListener.cc b/alljoyn_java/jni/JApplicationStateListener.cc
index bc09faf..66869db 100644
--- a/alljoyn_java/jni/JApplicationStateListener.cc
+++ b/alljoyn_java/jni/JApplicationStateListener.cc
@@ -40,10 +40,10 @@ JApplicationStateListener::JApplicationStateListener(jobject jlistener) : jasLis
return;
}
- QCC_DbgPrintf(("%s: Taking weak global reference to listener %p", __FUNCTION__, jlistener));
- jasListener = env->NewWeakGlobalRef(jlistener);
+ QCC_DbgPrintf(("%s: Taking global reference to listener %p", __FUNCTION__, jlistener));
+ jasListener = env->NewGlobalRef(jlistener);
if (!jasListener) {
- QCC_LogError(ER_FAIL, ("%s: Can't create new weak global reference", __FUNCTION__));
+ QCC_LogError(ER_FAIL, ("%s: Can't create new global reference", __FUNCTION__));
return;
}
@@ -63,8 +63,8 @@ JApplicationStateListener::~JApplicationStateListener()
{
QCC_DbgTrace(("%s", __FUNCTION__));
if (jasListener) {
- QCC_DbgPrintf(("%s: Releasing weak global reference to listener %p", __FUNCTION__, jasListener));
- GetEnv()->DeleteWeakGlobalRef(jasListener);
+ QCC_DbgPrintf(("%s: Releasing global reference to listener %p", __FUNCTION__, jasListener));
+ GetEnv()->DeleteGlobalRef(jasListener);
jasListener = NULL;
}
}
@@ -80,17 +80,6 @@ void JApplicationStateListener::State(const char* busName, const qcc::KeyInfoNIS
JScopedEnv env;
/*
- * The weak global reference jpinglistener cannot be directly used. We have to get
- * a "hard" reference to it and then use that. If you try to use a weak reference
- * directly you will crash and burn.
- */
- jobject jo = env->NewLocalRef(jasListener);
- if (!jo) {
- QCC_LogError(ER_FAIL, ("%s: Can't get new local reference to listener", __FUNCTION__));
- return;
- }
-
- /*
* This call out to the listener means that the state method
* must be MT-Safe. This is implied by the definition of the listener.
*/
@@ -121,13 +110,13 @@ void JApplicationStateListener::State(const char* busName, const qcc::KeyInfoNIS
jobject jpublicKeyInfo = env->NewObject(CLS_KeyInfoNISTP256, MID_KeyInfoNISTP256_cnstrctr);
- JLocalRef<jbyteArray> arrayX = ToJByteArray(pubKey->GetX(), pubKey->GetCoordinateSize());
- JLocalRef<jbyteArray> arrayY = ToJByteArray(pubKey->GetY(), pubKey->GetCoordinateSize());
+ jbyteArray arrayX = ToJByteArray(pubKey->GetX(), pubKey->GetCoordinateSize());
+ jbyteArray arrayY = ToJByteArray(pubKey->GetY(), pubKey->GetCoordinateSize());
- jobject jpublicKey = env->NewObject(CLS_ECCPublicKey, MID_ECCPublicKey_cnstrctr, arrayX.move(), arrayY.move());
+ jobject jpublicKey = env->NewObject(CLS_ECCPublicKey, MID_ECCPublicKey_cnstrctr, arrayX, arrayY);
env->CallObjectMethod(jpublicKeyInfo, MID_KeyInfoNISTP256_setPublicKey, jpublicKey);
- env->CallObjectMethod(jo, MID_state, jbusName, jpublicKeyInfo, jstate);
+ env->CallObjectMethod(jasListener, MID_state, jbusName, jpublicKeyInfo, jstate);
}
diff --git a/alljoyn_java/jni/JApplicationStateListener.h b/alljoyn_java/jni/JApplicationStateListener.h
index d5f0019..c07f368 100644
--- a/alljoyn_java/jni/JApplicationStateListener.h
+++ b/alljoyn_java/jni/JApplicationStateListener.h
@@ -20,18 +20,16 @@
#include <jni.h>
#include <alljoyn/ApplicationStateListener.h>
-class JBusAttachment;
-
class JApplicationStateListener : public ajn::ApplicationStateListener {
public:
JApplicationStateListener(jobject jlistener);
~JApplicationStateListener();
void State(const char* busName, const qcc::KeyInfoNISTP256& publicKeyInfo, ajn::PermissionConfigurator::ApplicationState state);
+ jobject jasListener;
private:
- jweak jasListener;
jmethodID MID_state;
};
diff --git a/alljoyn_java/jni/JBusAttachment.h b/alljoyn_java/jni/JBusAttachment.h
index 7685cca..1beafc7 100644
--- a/alljoyn_java/jni/JBusAttachment.h
+++ b/alljoyn_java/jni/JBusAttachment.h
@@ -33,6 +33,7 @@
#include "JAuthListener.h"
#include "JPermissionConfigurationListener.h"
+#include "JApplicationStateListener.h"
#include "JKeyStoreListener.h"
#include "JSignalHandler.h"
#include "JAboutObject.h"
@@ -40,6 +41,7 @@
#include "PendingAsyncPing.h"
class JAuthListener;
+class JApplicationStateListener;
class JKeyStoreListener;
class JSignalHandler;
class JAboutObject;
@@ -56,7 +58,7 @@ class JBusAttachment : public ajn::BusAttachment {
QStatus Connect(const char* connectArgs, jobject jkeyStoreListener, const char* authMechanisms,
jobject jauthListener, const char* keyStoreFileName, jboolean isShared);
void Disconnect();
- QStatus EnablePeerSecurity(const char* authMechanisms, jobject jauthListener, const char* keyStoreFileName, jboolean isShared, JPermissionConfigurationListener jpcl = NULL);
+ QStatus EnablePeerSecurity(const char* authMechanisms, jobject jauthListener, const char* keyStoreFileName, jboolean isShared, JPermissionConfigurationListener* jpcl = NULL);
QStatus RegisterBusObject(const char* objPath, jobject jbusObject, jobjectArray jbusInterfaces,
jboolean jsecure, jstring jlangTag, jstring jdesc, jobject jtranslator);
void UnregisterBusObject(jobject jbusObject);
@@ -93,6 +95,23 @@ class JBusAttachment : public ajn::BusAttachment {
std::vector<std::pair<jobject, JSignalHandler*> > signalHandlers;
/*
+ * The single (optional) JPermissionConfigurationListener associated with this bus
+ * attachment. Note that this member is public since we trust that the native binding
+ * we wrote will use it correctly.
+ */
+ JPermissionConfigurationListener* jPermissionConfigurationListener;
+
+ /**
+ * A mutex to serialize access to bus attachment jApplicationStateListeners
+ */
+ qcc::Mutex baAppStateListenLock;
+
+ /**
+ * A vector of all of the JApplicationStateListeners
+ */
+ std::vector<JApplicationStateListener*> jApplicationStateListeners;
+
+ /*
* The single (optionsl) KeyStoreListener associated with this bus
* attachment. The KeyStoreListener and AuthListener work together to deal
* with security exchanges over secure interfaces. Note that this member is
diff --git a/alljoyn_java/jni/JPermissionConfigurationListener.cc b/alljoyn_java/jni/JPermissionConfigurationListener.cc
index 673133d..9dfb73e 100644
--- a/alljoyn_java/jni/JPermissionConfigurationListener.cc
+++ b/alljoyn_java/jni/JPermissionConfigurationListener.cc
@@ -31,14 +31,13 @@ JPermissionConfigurationListener::JPermissionConfigurationListener(jobject jlist
JNIEnv* env = GetEnv();
if (!jlistener) {
- QCC_LogError(ER_FAIL, ("%s: jlistener null", __FUNCTION__));
return;
}
- QCC_DbgPrintf(("%s: Taking weak global reference to listener %p", __FUNCTION__, jlistener));
- jpcListener = env->NewWeakGlobalRef(jlistener);
+ QCC_DbgPrintf(("%s: Taking global reference to listener %p", __FUNCTION__, jlistener));
+ jpcListener = env->NewGlobalRef(jlistener);
if (!jpcListener) {
- QCC_LogError(ER_FAIL, ("%s: Can't create new weak global reference", __FUNCTION__));
+ QCC_LogError(ER_FAIL, ("%s: Can't create new global reference", __FUNCTION__));
return;
}
@@ -73,8 +72,8 @@ JPermissionConfigurationListener::~JPermissionConfigurationListener()
{
QCC_DbgTrace(("%s", __FUNCTION__));
if (jpcListener) {
- QCC_DbgPrintf(("%s: Releasing weak global reference to listener %p", __FUNCTION__, jpcListener));
- GetEnv()->DeleteWeakGlobalRef(jpcListener);
+ QCC_DbgPrintf(("%s: Releasing global reference to listener %p", __FUNCTION__, jpcListener));
+ GetEnv()->DeleteGlobalRef(jpcListener);
jpcListener = NULL;
}
}
@@ -90,22 +89,11 @@ QStatus JPermissionConfigurationListener::FactoryReset()
JScopedEnv env;
/*
- * The weak global reference jpinglistener cannot be directly used. We have to get
- * a "hard" reference to it and then use that. If you try to use a weak reference
- * directly you will crash and burn.
- */
- jobject jo = env->NewLocalRef(jpcListener);
- if (!jo) {
- QCC_LogError(ER_FAIL, ("%s: Can't get new local reference to listener", __FUNCTION__));
- return ER_FAIL;
- }
-
- /*
* This call out to the listener means that the DestinationFound method
* must be MT-Safe. This is implied by the definition of the listener.
*/
QCC_DbgPrintf(("%s: Call out to listener object and method", __FUNCTION__));
- jobject status = env->CallObjectMethod(jo, MID_factoryReset);
+ jobject status = env->CallObjectMethod(jpcListener, MID_factoryReset);
if (env->ExceptionCheck()) {
QCC_LogError(ER_FAIL, ("%s: Exception", __FUNCTION__));
return ER_FAIL;
@@ -137,22 +125,11 @@ void JPermissionConfigurationListener::PolicyChanged()
JScopedEnv env;
/*
- * The weak global reference jpinglistener cannot be directly used. We have to get
- * a "hard" reference to it and then use that. If you try to use a weak reference
- * directly you will crash and burn.
- */
- jobject jo = env->NewLocalRef(jpcListener);
- if (!jo) {
- QCC_LogError(ER_FAIL, ("%s: Can't get new local reference to listener", __FUNCTION__));
- return;
- }
-
- /*
* This call out to the listener means that the DestinationFound method
* must be MT-Safe. This is implied by the definition of the listener.
*/
QCC_DbgPrintf(("%s: Call out to listener object and method", __FUNCTION__));
- env->CallObjectMethod(jo, MID_policyChanged);
+ env->CallObjectMethod(jpcListener, MID_policyChanged);
if (env->ExceptionCheck()) {
QCC_LogError(ER_FAIL, ("%s: Exception", __FUNCTION__));
}
@@ -170,22 +147,11 @@ void JPermissionConfigurationListener::StartManagement()
JScopedEnv env;
/*
- * The weak global reference jpinglistener cannot be directly used. We have to get
- * a "hard" reference to it and then use that. If you try to use a weak reference
- * directly you will crash and burn.
- */
- jobject jo = env->NewLocalRef(jpcListener);
- if (!jo) {
- QCC_LogError(ER_FAIL, ("%s: Can't get new local reference to listener", __FUNCTION__));
- return;
- }
-
- /*
* This call out to the listener means that the DestinationFound method
* must be MT-Safe. This is implied by the definition of the listener.
*/
QCC_DbgPrintf(("%s: Call out to listener object and method", __FUNCTION__));
- env->CallObjectMethod(jo, MID_startManagement);
+ env->CallObjectMethod(jpcListener, MID_startManagement);
if (env->ExceptionCheck()) {
QCC_LogError(ER_FAIL, ("%s: Exception", __FUNCTION__));
}
@@ -203,22 +169,11 @@ void JPermissionConfigurationListener::EndManagement()
JScopedEnv env;
/*
- * The weak global reference jpinglistener cannot be directly used. We have to get
- * a "hard" reference to it and then use that. If you try to use a weak reference
- * directly you will crash and burn.
- */
- jobject jo = env->NewLocalRef(jpcListener);
- if (!jo) {
- QCC_LogError(ER_FAIL, ("%s: Can't get new local reference to listener", __FUNCTION__));
- return;
- }
-
- /*
* This call out to the listener means that the DestinationFound method
* must be MT-Safe. This is implied by the definition of the listener.
*/
QCC_DbgPrintf(("%s: Call out to listener object and method", __FUNCTION__));
- env->CallObjectMethod(jo, MID_endManagement);
+ env->CallObjectMethod(jpcListener, MID_endManagement);
if (env->ExceptionCheck()) {
QCC_LogError(ER_FAIL, ("%s: Exception", __FUNCTION__));
}
diff --git a/alljoyn_java/jni/JPermissionConfigurationListener.h b/alljoyn_java/jni/JPermissionConfigurationListener.h
index d582915..0469953 100644
--- a/alljoyn_java/jni/JPermissionConfigurationListener.h
+++ b/alljoyn_java/jni/JPermissionConfigurationListener.h
@@ -35,7 +35,7 @@ class JPermissionConfigurationListener : public ajn::PermissionConfigurationList
private:
JBusAttachment* busPtr;
- jweak jpcListener;
+ jobject jpcListener;
jmethodID MID_factoryReset;
jmethodID MID_policyChanged;
jmethodID MID_startManagement;
diff --git a/alljoyn_java/jni/PermissionConfigurator.cc b/alljoyn_java/jni/PermissionConfigurator.cc
index c074f8f..0ee5f5d 100644
--- a/alljoyn_java/jni/PermissionConfigurator.cc
+++ b/alljoyn_java/jni/PermissionConfigurator.cc
@@ -211,6 +211,15 @@ JNIEXPORT jobject JNICALL Java_org_alljoyn_bus_PermissionConfigurator_getSigning
return NULL;
}
+ jfieldID fidKeyId = jenv->GetFieldID(CLS_KeyInfoNISTP256, "m_keyId", "[B");
+
+ if (!fidKeyId) {
+ QCC_LogError(ER_FAIL, ("%s: Can't find keyId field in KeyInfoNISTP256", __FUNCTION__));
+ return NULL;
+ }
+
+ jbyteArray jkeyId = ToJByteArray(keyInfo.GetKeyId(), keyInfo.GetKeyIdLen());
+
const ECCPublicKey* retKey = keyInfo.GetPublicKey();
if (retKey == NULL) {
QCC_LogError(ER_FAIL, ("%s: retKey is null", __FUNCTION__));
@@ -218,15 +227,17 @@ JNIEXPORT jobject JNICALL Java_org_alljoyn_bus_PermissionConfigurator_getSigning
return NULL;
}
- JLocalRef<jobject> retObj = jenv->NewObject(CLS_KeyInfoNISTP256, MID_KeyInfoNISTP256_cnstrctr);
+ jobject retObj = jenv->NewObject(CLS_KeyInfoNISTP256, MID_KeyInfoNISTP256_cnstrctr);
- JLocalRef<jbyteArray> arrayX = ToJByteArray(retKey->GetX(), retKey->GetCoordinateSize());
- JLocalRef<jbyteArray> arrayY = ToJByteArray(retKey->GetY(), retKey->GetCoordinateSize());
+ jbyteArray arrayX = ToJByteArray(retKey->GetX(), retKey->GetCoordinateSize());
+ jbyteArray arrayY = ToJByteArray(retKey->GetY(), retKey->GetCoordinateSize());
- jobject jretKey = jenv->NewObject(CLS_ECCPublicKey, MID_ECCPublicKey_cnstrctr, arrayX.move(), arrayY.move());
+ jobject jretKey = jenv->NewObject(CLS_ECCPublicKey, MID_ECCPublicKey_cnstrctr, arrayX, arrayY);
CallObjectMethod(jenv, retObj, MID_KeyInfoNISTP256_setPublicKey, jretKey);
+ jenv->SetObjectField(retObj, fidKeyId, jkeyId);
+
return retObj;
}
@@ -342,17 +353,10 @@ JNIEXPORT jobject JNICALL Java_org_alljoyn_bus_PermissionConfigurator_getConnect
return NULL;
}
- jmethodID midC = jenv->GetMethodID(CLS_ECCPublicKey, "<init>", "([B[B)V");
- if (!midC) {
- QCC_LogError(ER_FAIL, ("%s: Can't find ECCPublicKey constructor", __FUNCTION__));
- Throw("java/lang/NoSuchMethodException", NULL);
- return NULL;
- }
-
jbyteArray arrayX = ToJByteArray(retKey.GetX(), retKey.GetCoordinateSize());
jbyteArray arrayY = ToJByteArray(retKey.GetY(), retKey.GetCoordinateSize());
- jobject retObj = jenv->NewObject(CLS_ECCPublicKey, midC, arrayX, arrayY);
+ jobject retObj = jenv->NewObject(CLS_ECCPublicKey, MID_ECCPublicKey_cnstrctr, arrayX, arrayY);
if (jenv->ExceptionCheck()) {
QCC_LogError(ER_FAIL, ("%s: Couldn't make jobject", __FUNCTION__));
@@ -519,7 +523,7 @@ JNIEXPORT void JNICALL Java_org_alljoyn_bus_PermissionConfigurator_claim(JNIEnv*
jfieldID fidKeyId = jenv->GetFieldID(CLS_KeyInfoNISTP256, "m_keyId", "[B");
- if (!fid) {
+ if (!fidKeyId) {
QCC_LogError(ER_FAIL, ("%s: Can't find keyId field in KeyInfoNISTP256", __FUNCTION__));
return;
}
@@ -623,8 +627,8 @@ JNIEXPORT void JNICALL Java_org_alljoyn_bus_PermissionConfigurator_claim(JNIEnv*
KeyInfoNISTP256 adminGroup;
- certificateAuthority.SetPublicKey(&eccPublicKeyAdminGroup);
- certificateAuthority.SetKeyId(adminGroupKeyID, jenv->GetArrayLength(jadminGroupKeyID));
+ adminGroup.SetPublicKey(&eccPublicKeyAdminGroup);
+ adminGroup.SetKeyId(adminGroupKeyID, jenv->GetArrayLength(jadminGroupKeyID));
CertificateX509* certChain = new CertificateX509[jcertChainCount];
size_t maniCount = (size_t) jmaniCount;
@@ -800,10 +804,10 @@ JNIEXPORT jobjectArray JNICALL Java_org_alljoyn_bus_PermissionConfigurator_getId
}
jmethodID mid = jenv->GetMethodID(CLS_CertificateX509, "<init>", "()V");
- JLocalRef<jobjectArray> retIdentity = jenv->NewObjectArray(identity.size(), CLS_CertificateX509, NULL);
+ jobjectArray retIdentity = jenv->NewObjectArray(identity.size(), CLS_CertificateX509, NULL);
for (unsigned int i = 0; i < identity.size(); i++) {
- JLocalRef<jobject> jidcert = jenv->NewObject(CLS_CertificateX509, mid);
+ jobject jidcert = jenv->NewObject(CLS_CertificateX509, mid);
if (!jidcert) {
return NULL;
}
@@ -819,7 +823,7 @@ JNIEXPORT jobjectArray JNICALL Java_org_alljoyn_bus_PermissionConfigurator_getId
}
}
- return retIdentity.move();
+ return retIdentity;
}
/*
@@ -854,49 +858,31 @@ JNIEXPORT jobject JNICALL Java_org_alljoyn_bus_PermissionConfigurator_getIdentit
const ECCPublicKey* retKey = retKeyInfo.GetPublicKey();
- jmethodID mid = jenv->GetMethodID(CLS_KeyInfoNISTP256, "<init>", "()V");
- if (!mid) {
- QCC_LogError(ER_FAIL, ("%s: Can't find KeyInfoNISTP256 constructor", __FUNCTION__));
- return NULL;
- }
+ jobject jretKeyInfo = jenv->NewObject(CLS_KeyInfoNISTP256, MID_KeyInfoNISTP256_cnstrctr);
- JLocalRef<jobject> jretKeyInfo = jenv->NewObject(CLS_KeyInfoNISTP256, mid);
+ jbyteArray arrayX = ToJByteArray(retKey->GetX(), retKey->GetCoordinateSize());
+ jbyteArray arrayY = ToJByteArray(retKey->GetY(), retKey->GetCoordinateSize());
- jmethodID midC = jenv->GetMethodID(CLS_ECCPublicKey, "<init>", "([B[B)V");
- if (!midC) {
- QCC_LogError(ER_FAIL, ("%s: Can't find ECCPublicKey constructor", __FUNCTION__));
- return NULL;
- }
-
- JLocalRef<jbyteArray> arrayX = ToJByteArray(retKey->GetX(), retKey->GetCoordinateSize());
- JLocalRef<jbyteArray> arrayY = ToJByteArray(retKey->GetY(), retKey->GetCoordinateSize());
-
- jobject jretKey = jenv->NewObject(CLS_ECCPublicKey, midC, arrayX.move(), arrayY.move());
+ jobject jretKey = jenv->NewObject(CLS_ECCPublicKey, MID_ECCPublicKey_cnstrctr, arrayX, arrayY);
if (jenv->ExceptionCheck()) {
QCC_LogError(ER_FAIL, ("%s: Exception", __FUNCTION__));
return NULL;
}
- jmethodID midSet = jenv->GetMethodID(CLS_KeyInfoNISTP256, "setPublicKey", "(Lorg/alljoyn/bus/common/ECCPublicKey;)");
- if (!midSet) {
- QCC_LogError(ER_FAIL, ("%s: Can't find setPublicKey", __FUNCTION__));
- return NULL;
- }
-
- CallObjectMethod(jenv, jretKeyInfo, midSet, jretKey);
+ CallObjectMethod(jenv, jretKeyInfo, MID_KeyInfoNISTP256_setPublicKey, jretKey);
if (jenv->ExceptionCheck()) {
QCC_LogError(ER_FAIL, ("%s: Exception", __FUNCTION__));
return NULL;
}
jmethodID midCCert = jenv->GetMethodID(CLS_CertificateId, "<init>", "(Ljava/util/String;Lorg/alljoyn/bus/common/KeyInfoNISTP256)V");
- if (!midC) {
+ if (!midCCert) {
QCC_LogError(ER_FAIL, ("%s: Can't find ECCPublicKey constructor", __FUNCTION__));
return NULL;
}
jstring jserial = jenv->NewStringUTF(serial.c_str());
- return jenv->NewObject(CLS_CertificateId, midCCert, jserial, jretKeyInfo.move());
+ return jenv->NewObject(CLS_CertificateId, midCCert, jserial, jretKeyInfo);
}
/*
@@ -949,26 +935,8 @@ JNIEXPORT jobjectArray JNICALL Java_org_alljoyn_bus_PermissionConfigurator_getMe
return NULL;
}
- jmethodID mid = jenv->GetMethodID(CLS_KeyInfoNISTP256, "<init>", "()V");
- if (!mid) {
- QCC_LogError(ER_FAIL, ("%s: Can't find KeyInfoNISTP256 constructor", __FUNCTION__));
- return NULL;
- }
-
- jmethodID midC = jenv->GetMethodID(CLS_ECCPublicKey, "<init>", "([B[B)V");
- if (!midC) {
- QCC_LogError(ER_FAIL, ("%s: Can't find ECCPublicKey constructor", __FUNCTION__));
- return NULL;
- }
-
- jmethodID midSet = jenv->GetMethodID(CLS_KeyInfoNISTP256, "setPublicKey", "(Lorg/alljoyn/bus/common/ECCPublicKey;)");
- if (!midSet) {
- QCC_LogError(ER_FAIL, ("%s: Can't find setPublicKey", __FUNCTION__));
- return NULL;
- }
-
jmethodID midCCert = jenv->GetMethodID(CLS_CertificateId, "<init>", "(Ljava/util/String;Lorg/alljoyn/bus/common/KeyInfoNISTP256)V");
- if (!midC) {
+ if (!midCCert) {
QCC_LogError(ER_FAIL, ("%s: Can't find ECCPublicKey constructor", __FUNCTION__));
return NULL;
}
@@ -982,30 +950,30 @@ JNIEXPORT jobjectArray JNICALL Java_org_alljoyn_bus_PermissionConfigurator_getMe
return NULL;
}
- JLocalRef<jobjectArray> retMemberSummaries = jenv->NewObjectArray(serial.size(), CLS_CertificateId, NULL);
+ jobjectArray retMemberSummaries = jenv->NewObjectArray(serial.size(), CLS_CertificateId, NULL);
for (unsigned int i = 0; i < serial.size(); i++) {
const ECCPublicKey* retKey = retKeyInfo[i].GetPublicKey();
- JLocalRef<jobject> jretKeyInfo = jenv->NewObject(CLS_KeyInfoNISTP256, mid);
+ jobject jretKeyInfo = jenv->NewObject(CLS_KeyInfoNISTP256, MID_KeyInfoNISTP256_cnstrctr);
- JLocalRef<jbyteArray> arrayX = ToJByteArray(retKey->GetX(), retKey->GetCoordinateSize());
- JLocalRef<jbyteArray> arrayY = ToJByteArray(retKey->GetY(), retKey->GetCoordinateSize());
+ jbyteArray arrayX = ToJByteArray(retKey->GetX(), retKey->GetCoordinateSize());
+ jbyteArray arrayY = ToJByteArray(retKey->GetY(), retKey->GetCoordinateSize());
- jobject jretKey = jenv->NewObject(CLS_ECCPublicKey, midC, arrayX.move(), arrayY.move());
+ jobject jretKey = jenv->NewObject(CLS_ECCPublicKey, MID_ECCPublicKey_cnstrctr, arrayX, arrayY);
if (jenv->ExceptionCheck()) {
QCC_LogError(ER_FAIL, ("%s: Exception", __FUNCTION__));
return NULL;
}
- CallObjectMethod(jenv, jretKeyInfo, midSet, jretKey);
+ CallObjectMethod(jenv, jretKeyInfo, MID_KeyInfoNISTP256_setPublicKey, jretKey);
if (jenv->ExceptionCheck()) {
QCC_LogError(ER_FAIL, ("%s: Exception", __FUNCTION__));
return NULL;
}
jstring jserial = jenv->NewStringUTF(serial[i].c_str());
- jobject jcertid = jenv->NewObject(CLS_CertificateId, midCCert, jserial, jretKeyInfo.move());
+ jobject jcertid = jenv->NewObject(CLS_CertificateId, midCCert, jserial, jretKeyInfo);
jenv->SetObjectArrayElement(retMemberSummaries, i, jcertid);
if (jenv->ExceptionCheck()) {
diff --git a/alljoyn_java/jni/SecurityApplicationProxy.cc b/alljoyn_java/jni/SecurityApplicationProxy.cc
index 0f45bf0..8ccd0d6 100644
--- a/alljoyn_java/jni/SecurityApplicationProxy.cc
+++ b/alljoyn_java/jni/SecurityApplicationProxy.cc
@@ -340,10 +340,10 @@ JNIEXPORT jobjectArray JNICALL Java_org_alljoyn_bus_SecurityApplicationProxy_get
jmethodID mid = jenv->GetMethodID(CLS_CertificateX509, "<init>", "()V");
- JLocalRef<jobjectArray> retObj = jenv->NewObjectArray(certChainSize, CLS_CertificateX509, NULL);
+ jobjectArray retObj = jenv->NewObjectArray(certChainSize, CLS_CertificateX509, NULL);
for (size_t i = 0; i < certChainSize; i++) {
- JLocalRef<jobject> jidcert = jenv->NewObject(CLS_CertificateX509, mid);
+ jobject jidcert = jenv->NewObject(CLS_CertificateX509, mid);
if (!jidcert) {
delete [] certChain;
return NULL;
@@ -369,7 +369,7 @@ JNIEXPORT jobjectArray JNICALL Java_org_alljoyn_bus_SecurityApplicationProxy_get
}
delete [] certChain;
- return retObj.move();
+ return retObj;
}
/*
@@ -511,25 +511,11 @@ JNIEXPORT void JNICALL Java_org_alljoyn_bus_SecurityApplicationProxy_claim(JNIEn
return;
}
- jfieldID fidX = jenv->GetFieldID(CLS_ECCPublicKey, "x", "[B");
-
- if (!fidX) {
- QCC_LogError(ER_FAIL, ("%s: Can't find x field in ECCPrivateKey", __FUNCTION__));
- return;
- }
-
- jfieldID fidY = jenv->GetFieldID(CLS_ECCPublicKey, "y", "[B");
-
- if (!fidY) {
- QCC_LogError(ER_FAIL, ("%s: Can't find y field in ECCPrivateKey", __FUNCTION__));
- return;
- }
-
jobject jcertAuthPublicKey = (jobject) jenv->GetObjectField(jcertAuth, fid);
jbyteArray jkeyID = (jbyteArray) jenv->GetObjectField(jcertAuth, fidKeyId);
- jbyteArray jeccX = (jbyteArray) jenv->GetObjectField(jcertAuthPublicKey, fidX);
- jbyteArray jeccY = (jbyteArray) jenv->GetObjectField(jcertAuthPublicKey, fidY);
+ jbyteArray jeccX = (jbyteArray) jenv->GetObjectField(jcertAuthPublicKey, FID_ECCPublicKey_x);
+ jbyteArray jeccY = (jbyteArray) jenv->GetObjectField(jcertAuthPublicKey, FID_ECCPublicKey_y);
uint8_t* eccX = ToByteArray(jeccX);
uint8_t* eccY = ToByteArray(jeccY);
@@ -588,8 +574,8 @@ JNIEXPORT void JNICALL Java_org_alljoyn_bus_SecurityApplicationProxy_claim(JNIEn
jobject jadminGroupPublicKey = (jobject) jenv->GetObjectField(jadminGroup, fid);
jbyteArray jadminGroupKeyID = (jbyteArray) jenv->GetObjectField(jadminGroup, fidKeyId);
- jbyteArray jadminGroupEccX = (jbyteArray) jenv->GetObjectField(jadminGroupPublicKey, fidX);
- jbyteArray jadminGroupEccY = (jbyteArray) jenv->GetObjectField(jadminGroupPublicKey, fidY);
+ jbyteArray jadminGroupEccX = (jbyteArray) jenv->GetObjectField(jadminGroupPublicKey, FID_ECCPublicKey_x);
+ jbyteArray jadminGroupEccY = (jbyteArray) jenv->GetObjectField(jadminGroupPublicKey, FID_ECCPublicKey_y);
uint8_t* adminGroupEccX = ToByteArray(jadminGroupEccX);
uint8_t* adminGroupEccY = ToByteArray(jadminGroupEccY);
@@ -623,8 +609,8 @@ JNIEXPORT void JNICALL Java_org_alljoyn_bus_SecurityApplicationProxy_claim(JNIEn
KeyInfoNISTP256 adminGroup;
- certificateAuthority.SetPublicKey(&eccPublicKeyAdminGroup);
- certificateAuthority.SetKeyId(adminGroupKeyID, jenv->GetArrayLength(jadminGroupKeyID));
+ adminGroup.SetPublicKey(&eccPublicKeyAdminGroup);
+ adminGroup.SetKeyId(adminGroupKeyID, jenv->GetArrayLength(jadminGroupKeyID));
CertificateX509* certChain = new CertificateX509[jcertChainCount];
size_t maniCount = (size_t) jmaniCount;
@@ -817,6 +803,9 @@ JNIEXPORT void JNICALL Java_org_alljoyn_bus_SecurityApplicationProxy_updateIdent
status = secPtr->UpdateIdentity(certArray, jcertCount, manifests, jmaniCount);
+ if (status == ER_OK) {
+ status = secPtr->SecureConnection(true);
+ }
exit:
for (jlong i = 0; i < jmaniCount; ++i) {
@@ -867,6 +856,12 @@ JNIEXPORT void JNICALL Java_org_alljoyn_bus_SecurityApplicationProxy_updatePolic
jenv->ThrowNew(CLS_BusException, QCC_StatusText(status));
return;
}
+
+ status = secPtr->SecureConnection(true);
+
+ if (status != ER_OK) {
+ jenv->ThrowNew(CLS_BusException, QCC_StatusText(status));
+ }
}
/*
@@ -1135,10 +1130,10 @@ JNIEXPORT jobjectArray JNICALL Java_org_alljoyn_bus_SecurityApplicationProxy_get
jmethodID mid = jenv->GetMethodID(CLS_CertificateX509, "<init>", "()V");
- JLocalRef<jobjectArray> retObj = jenv->NewObjectArray(certChainSize, CLS_CertificateX509, NULL);
+ jobjectArray retObj = jenv->NewObjectArray(certChainSize, CLS_CertificateX509, NULL);
for (size_t i = 0; i < certChainSize; i++) {
- JLocalRef<jobject> jidcert = jenv->NewObject(CLS_CertificateX509, mid);
+ jobject jidcert = jenv->NewObject(CLS_CertificateX509, mid);
if (!jidcert) {
delete [] certChain;
return NULL;
@@ -1164,7 +1159,7 @@ JNIEXPORT jobjectArray JNICALL Java_org_alljoyn_bus_SecurityApplicationProxy_get
}
delete [] certChain;
- return retObj.move();
+ return retObj;
}
/*
diff --git a/alljoyn_java/jni/alljoyn_java.cc b/alljoyn_java/jni/alljoyn_java.cc
index 5f0af5c..111fa2d 100644
--- a/alljoyn_java/jni/alljoyn_java.cc
+++ b/alljoyn_java/jni/alljoyn_java.cc
@@ -3900,6 +3900,15 @@ void JBusAttachment::Disconnect()
{
QCC_DbgPrintf(("JBusAttachment::Disconnect()"));
+ QCC_VERIFY(ER_OK == baAppStateListenLock.Lock(MUTEX_CONTEXT));
+ for (vector<JApplicationStateListener*>::iterator i = jApplicationStateListeners.begin(); i != jApplicationStateListeners.end(); ++i) {
+ UnregisterApplicationStateListener(**i);
+ delete *i;
+ *i = NULL;
+ }
+ jApplicationStateListeners.clear();
+ QCC_VERIFY(ER_OK == baAppStateListenLock.Unlock(MUTEX_CONTEXT));
+
if (IsConnected()) {
QCC_DbgPrintf(("JBusAttachment::Disconnect(): calling BusAttachment::Disconnect()"));
QStatus status = BusAttachment::Disconnect();
@@ -4082,6 +4091,10 @@ void JBusAttachment::Disconnect()
QCC_DbgPrintf(("JBusAttachment::Disconnect(): Forgetting jkeyStoreListenerRef"));
env->DeleteGlobalRef(jkeyStoreListenerRef);
+ QCC_DbgPrintf(("JBusAttachment::Disconnect(): Releasing jPermissionConfigurationListener"));
+ delete jPermissionConfigurationListener;
+ jPermissionConfigurationListener = NULL;
+
if (aboutObj != NULL) {
if (aboutObj->jaboutObjGlobalRef != NULL) {
env->DeleteGlobalRef(aboutObj->jaboutObjGlobalRef);
@@ -4094,9 +4107,10 @@ void JBusAttachment::Disconnect()
QCC_DbgPrintf(("JBusAttachment::Disconnect(): Releasing global Bus Object map lock"));
gBusObjectMapLock.Unlock();
+
}
-QStatus JBusAttachment::EnablePeerSecurity(const char* authMechanisms, jobject jauthListener, const char* keyStoreFileName, jboolean isShared, JPermissionConfigurationListener jpcl)
+QStatus JBusAttachment::EnablePeerSecurity(const char* authMechanisms, jobject jauthListener, const char* keyStoreFileName, jboolean isShared, JPermissionConfigurationListener* jpcl)
{
QCC_DbgPrintf(("JBusAttachment::EnablePeerSecurity()"));
@@ -4183,7 +4197,7 @@ QStatus JBusAttachment::EnablePeerSecurity(const char* authMechanisms, jobject j
QCC_DbgPrintf(("JBusAttachment::EnablePeerSecurity(): Releasing Bus Attachment common lock"));
baCommonLock.Unlock();
- QStatus status = BusAttachment::EnablePeerSecurity(authMechanisms, authListener, keyStoreFileName, isShared, &jpcl);
+ QStatus status = BusAttachment::EnablePeerSecurity(authMechanisms, authListener, keyStoreFileName, isShared, jpcl);
/*
* We're back, and depending on what has happened out from under us we
@@ -8081,12 +8095,6 @@ JNIEXPORT jobject JNICALL Java_org_alljoyn_bus_BusAttachment_enablePeerSecurity(
return NULL;
}
- JPermissionConfigurationListener permListener(jpclistener);
- if (env->ExceptionCheck()) {
- env->ExceptionClear();
- permListener = NULL;
- }
-
JBusAttachment* busPtr = GetHandle<JBusAttachment*>(thiz);
if (env->ExceptionCheck()) {
return NULL;
@@ -8104,7 +8112,13 @@ JNIEXPORT jobject JNICALL Java_org_alljoyn_bus_BusAttachment_enablePeerSecurity(
QCC_DbgPrintf(("BusAttachment_enablePeerSecurity(): Refcount on busPtr is %d", busPtr->GetRef()));
- QStatus status = busPtr->EnablePeerSecurity(authMechanisms.c_str(), jauthListener, keyStoreFileName.c_str(), isShared, permListener);
+ busPtr->jPermissionConfigurationListener = new JPermissionConfigurationListener(jpclistener);
+ if (env->ExceptionCheck()) {
+ env->ExceptionClear();
+ busPtr->jPermissionConfigurationListener = NULL;
+ }
+
+ QStatus status = busPtr->EnablePeerSecurity(authMechanisms.c_str(), jauthListener, keyStoreFileName.c_str(), isShared, busPtr->jPermissionConfigurationListener);
if (env->ExceptionCheck()) {
QCC_LogError(ER_FAIL, ("BusAttachment_enablePeerSecurity(): Exception"));
return NULL;
@@ -10020,9 +10034,17 @@ JNIEXPORT jobject JNICALL Java_org_alljoyn_bus_BusAttachment_registerApplication
}
QCC_ASSERT(busPtr);
- JApplicationStateListener jASListener(jappstatelistener);
+ JApplicationStateListener* jASListener = new JApplicationStateListener(jappstatelistener);
- QStatus status = busPtr->RegisterApplicationStateListener(jASListener);
+ QStatus status = busPtr->RegisterApplicationStateListener(*jASListener);
+
+ if (status == ER_OK) {
+ QCC_VERIFY(ER_OK == busPtr->baAppStateListenLock.Lock(MUTEX_CONTEXT));
+ busPtr->jApplicationStateListeners.push_back(jASListener);
+ QCC_VERIFY(ER_OK == busPtr->baAppStateListenLock.Unlock(MUTEX_CONTEXT));
+ } else {
+ delete jASListener;
+ }
return JStatus(status);
}
@@ -10043,9 +10065,33 @@ JNIEXPORT jobject JNICALL Java_org_alljoyn_bus_BusAttachment_unregisterApplicati
}
QCC_ASSERT(busPtr);
- JApplicationStateListener jASListener(jappstatelistener);
+ QCC_VERIFY(ER_OK == busPtr->baAppStateListenLock.Lock(MUTEX_CONTEXT));
+
+ QStatus status = ER_FAIL;
+
+ for (vector<JApplicationStateListener*>::iterator i = busPtr->jApplicationStateListeners.begin(); i != busPtr->jApplicationStateListeners.end(); ++i) {
+ jobject jo = env->NewLocalRef((*i)->jasListener);
+ if (!jo) {
+ QCC_LogError(ER_FAIL, ("%s: Can't get new local reference to listener", __FUNCTION__));
+ continue;
+ }
+
+ if (env->IsSameObject(jo, jappstatelistener)) {
+ status = busPtr->UnregisterApplicationStateListener(**i);
+
+ if (status != ER_OK) {
+ break;
+ }
+
+ QCC_DbgPrintf(("%s: Forgetting %p", __FUNCTION__, jo));
+ delete *i;
+
+ busPtr->jApplicationStateListeners.erase(i);
+ break;
+ }
+ }
- QStatus status = busPtr->UnregisterApplicationStateListener(jASListener);
+ QCC_VERIFY(ER_OK == busPtr->baAppStateListenLock.Unlock(MUTEX_CONTEXT));
return JStatus(status);
}
diff --git a/alljoyn_java/src/org/alljoyn/bus/BusAttachment.java b/alljoyn_java/src/org/alljoyn/bus/BusAttachment.java
index 3ffec7c..20b2e73 100644
--- a/alljoyn_java/src/org/alljoyn/bus/BusAttachment.java
+++ b/alljoyn_java/src/org/alljoyn/bus/BusAttachment.java
@@ -29,9 +29,11 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import org.alljoyn.bus.common.ECCPrivateKey;
import org.alljoyn.bus.AuthListener.AuthRequest;
import org.alljoyn.bus.AuthListener.CertificateRequest;
import org.alljoyn.bus.AuthListener.Credentials;
diff --git a/alljoyn_java/src/org/alljoyn/bus/SecurityApplicationProxy.java b/alljoyn_java/src/org/alljoyn/bus/SecurityApplicationProxy.java
index 03c6df1..62bf6f1 100644
--- a/alljoyn_java/src/org/alljoyn/bus/SecurityApplicationProxy.java
+++ b/alljoyn_java/src/org/alljoyn/bus/SecurityApplicationProxy.java
@@ -236,9 +236,8 @@ public class SecurityApplicationProxy {
*
* After having a new identity certificate installed, the target bus clears
* out all of its peer's secret and session keys, so the next call will get
- * security violation. After calling UpdateIdentity, SecureConnection(true)
- * should be called to force the peers to create a new set of secret and
- * session keys.
+ * security violation. Calling updateIdentity causes existing sessions to be
+ * recreated and session keys to be renegotiated.
*
* @param identityCertificateChain the identity certificate
* @param identityCertificateChainCount the number of identity certificates
@@ -263,9 +262,8 @@ public class SecurityApplicationProxy {
*
* After having a new identity certificate installed, the target bus clears
* out all of its peer's secret and session keys, so the next call will get
- * security violation. After calling UpdateIdentity, SecureConnection(true)
- * should be called to force the peers to create a new set of secret and
- * session keys.
+ * security violation. Calling updateIdentity causes existing sessions to
+ * be created and session keys to be renegotiated.
*
* @param identityCertificateChain the identity certificate
* @param manifestXmls An array of null-terminated strings containing the application's
diff --git a/alljoyn_java/src/org/alljoyn/bus/common/ECCPublicKey.java b/alljoyn_java/src/org/alljoyn/bus/common/ECCPublicKey.java
index 851716e..ea2c4af 100644
--- a/alljoyn_java/src/org/alljoyn/bus/common/ECCPublicKey.java
+++ b/alljoyn_java/src/org/alljoyn/bus/common/ECCPublicKey.java
@@ -47,4 +47,34 @@ public class ECCPublicKey {
public String toString() {
return Arrays.toString(x) + ", " + Arrays.toString(y);
}
+
+ @Override
+ public boolean equals(Object compObj) {
+ if (this == compObj) {
+ return true;
+ }
+ if (!(compObj instanceof ECCPublicKey)) {
+ return false;
+ }
+ if (compObj == null) {
+ return false;
+ }
+
+ ECCPublicKey compPublicKey = (ECCPublicKey) compObj;
+
+ if (getCoordinateSize() != compPublicKey.getCoordinateSize()) {
+ return false;
+ }
+
+ for (int index = 0; index < getCoordinateSize(); index++) {
+ if (x[index] != compPublicKey.x[index]) {
+ return false;
+ }
+ if (y[index] != compPublicKey.y[index]) {
+ return false;
+ }
+ }
+
+ return true;
+ }
}
diff --git a/alljoyn_java/test/org/alljoyn/bus/SecurityManagementTest.java b/alljoyn_java/test/org/alljoyn/bus/SecurityManagementTest.java
new file mode 100644
index 0000000..a140b13
--- /dev/null
+++ b/alljoyn_java/test/org/alljoyn/bus/SecurityManagementTest.java
@@ -0,0 +1,306 @@
+/**
+ * Copyright AllSeen Alliance. All rights reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package org.alljoyn.bus;
+
+import java.lang.ref.WeakReference;
+import java.util.Map;
+import java.util.HashMap;
+import java.io.File;
+import java.nio.ByteBuffer;
+import java.util.UUID;
+
+import junit.framework.TestCase;
+
+import org.alljoyn.bus.annotation.BusSignalHandler;
+import org.alljoyn.bus.ifaces.DBusProxyObj;
+import org.alljoyn.bus.ifaces.Introspectable;
+import org.alljoyn.bus.common.KeyInfoNISTP256;
+import org.alljoyn.bus.common.CertificateX509;
+import org.alljoyn.bus.common.CryptoECC;
+
+public class SecurityManagementTest extends TestCase {
+ private static final long expiredInSecs = 3600;
+ private BusAttachment peerBus;
+ private BusAttachment managerBus;
+ private Map<String, PermissionConfigurator.ApplicationState> stateMap;
+ private String managerBusUniqueName;
+ private String peerBusUniqueName;
+ /**
+ * hostedSessions holds <busName, sessionId>
+ */
+ private Map<String,Integer> hostedSessions;
+
+ private static final String defaultManifestXml = "<manifest>" +
+ "<node>" +
+ "<interface>" +
+ "<any>" +
+ "<annotation name = \"org.alljoyn.Bus.Action\" value = \"Modify\"/>" +
+ "<annotation name = \"org.alljoyn.Bus.Action\" value = \"Observe\"/>" +
+ "<annotation name = \"org.alljoyn.Bus.Action\" value = \"Provide\"/>" +
+ "</any>" +
+ "</interface>" +
+ "</node>" +
+ "</manifest>";
+
+ private SessionOpts defaultSessionOpts;
+ private Mutable.ShortValue defaultSessionPort;
+ private Mutable.IntegerValue managerToManagerSessionId;
+ private Mutable.IntegerValue managerToPeerSessionId;
+
+ static {
+ System.loadLibrary("alljoyn_java");
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ peerBus = null;
+ stateMap = new HashMap<String, PermissionConfigurator.ApplicationState>();
+ hostedSessions = new HashMap<String,Integer>();
+ defaultSessionOpts = new SessionOpts();
+ defaultSessionOpts.traffic = SessionOpts.TRAFFIC_MESSAGES;
+ defaultSessionOpts.isMultipoint = false;
+ defaultSessionOpts.proximity = SessionOpts.PROXIMITY_ANY;
+ defaultSessionOpts.transports = SessionOpts.TRANSPORT_ANY;
+ defaultSessionPort = new Mutable.ShortValue((short) 42);
+ managerToManagerSessionId = new Mutable.IntegerValue((short) 0);
+ managerToPeerSessionId = new Mutable.IntegerValue((short) 0);
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+
+ if (peerBus != null) {
+ assertTrue(peerBus.isConnected());
+ peerBus.disconnect();
+ assertFalse(peerBus.isConnected());
+ peerBus.release();
+ peerBus = null;
+ }
+
+ }
+
+ /**
+ * copied and interpreted from core SecurityManagementTest.cc
+ */
+ public void testBasic() throws Exception {
+ peerBus = new BusAttachment(getClass().getName(), BusAttachment.RemoteMessage.Receive);
+ assertEquals(Status.OK, peerBus.connect());
+
+ managerBus = new BusAttachment(getClass().getName() + "manager", BusAttachment.RemoteMessage.Receive);
+ assertEquals(Status.OK, managerBus.connect());
+
+ managerBusUniqueName = managerBus.getUniqueName();
+ peerBusUniqueName = peerBus.getUniqueName();
+
+ if (System.getProperty("os.name").startsWith("Windows")) {
+ assertEquals(Status.OK, managerBus.registerAuthListener("ALLJOYN_ECDHE_NULL", authListener, null, false, pclistener));
+ assertEquals(Status.OK, peerBus.registerAuthListener("ALLJOYN_ECDHE_NULL", authListener, null, false, pclistener));
+ } else if (System.getProperty("java.vm.name").startsWith("Dalvik")) {
+ /*
+ * on some Android devices File.createTempFile trys to create a file in
+ * a location we do not have permission to write to. Resulting in a
+ * java.io.IOException: Permission denied error.
+ * This code assumes that the junit tests will have file IO permission
+ * for /data/data/org.alljoyn.bus
+ */
+ assertEquals(Status.OK, managerBus.registerAuthListener("ALLJOYN_ECDHE_NULL", authListener,
+ "/data/data/org.alljoyn.bus/files/alljoyn.ks", false, pclistener));
+ assertEquals(Status.OK, peerBus.registerAuthListener("ALLJOYN_ECDHE_NULL", authListener,
+ "/data/data/org.alljoyn.bus/files/alljoynpb.ks", false, pclistener));
+ } else {
+ assertEquals(Status.OK, managerBus.registerAuthListener("ALLJOYN_ECDHE_NULL", authListener,
+ File.createTempFile("alljoyn", "ks").getAbsolutePath(), false, pclistener));
+ assertEquals(Status.OK, peerBus.registerAuthListener("ALLJOYN_ECDHE_NULL", authListener,
+ File.createTempFile("alljoynpb", "ks").getAbsolutePath(), false, pclistener));
+ }
+
+ managerBus.getPermissionConfigurator().setManifestTemplateFromXml(defaultManifestXml);
+ peerBus.getPermissionConfigurator().setManifestTemplateFromXml(defaultManifestXml);
+
+ /**
+ * copied from the c++ counterpart.
+ * not sure what is expected from this call, or how we are going to use it later
+ * EXPECT_EQ(ER_OK, peer2Bus.CreateInterfacesFromXml(interface.c_str()));
+ * EXPECT_EQ(ER_OK, peer3Bus.CreateInterfacesFromXml(interface.c_str()));
+ */
+
+ assertEquals(Status.OK, managerBus.bindSessionPort(defaultSessionPort, defaultSessionOpts, new SessionPortListener() {
+ public boolean acceptSessionJoiner(short sessionPort, String joiner, SessionOpts opts) {
+ return true;
+ }
+ public void sessionJoined(short sessionPort, int id, String joiner) {
+ hostedSessions.put(joiner, id);
+ }
+ }));
+
+ assertEquals(Status.OK, peerBus.bindSessionPort(defaultSessionPort, defaultSessionOpts, new SessionPortListener() {
+ public boolean acceptSessionJoiner(short sessionPort, String joiner, SessionOpts opts) {
+ return true;
+ }
+ public void sessionJoined(short sessionPort, int id, String joiner) {
+ hostedSessions.put(joiner, id);
+ }
+ }));
+
+ assertEquals(Status.OK, managerBus.joinSession(managerBusUniqueName, defaultSessionPort.value, managerToManagerSessionId, defaultSessionOpts, new JoinSessionSessionListener()));
+ assertEquals(Status.OK, managerBus.joinSession(peerBusUniqueName, defaultSessionPort.value, managerToPeerSessionId, defaultSessionOpts, new JoinSessionSessionListener()));
+
+ PermissionConfigurator managerConfigurator = managerBus.getPermissionConfigurator();
+ PermissionConfigurator.ApplicationState applicationStateManager = managerConfigurator.getApplicationState();
+ assertEquals(PermissionConfigurator.ApplicationState.CLAIMABLE, applicationStateManager);
+
+ SecurityApplicationProxy sapWithPeer = new SecurityApplicationProxy(managerBus, peerBusUniqueName, managerToPeerSessionId.value);
+ PermissionConfigurator.ApplicationState applicationStatePeer;
+ assertEquals(PermissionConfigurator.ApplicationState.CLAIMABLE, sapWithPeer.getApplicationState());
+
+ assertEquals(Status.OK, managerBus.registerApplicationStateListener(appStateListener));
+
+ KeyInfoNISTP256 managerPublicKey = managerConfigurator.getSigningPublicKey();
+
+ //Create peer key
+ PermissionConfigurator pcPeer = peerBus.getPermissionConfigurator();
+ KeyInfoNISTP256 peerKey = pcPeer.getSigningPublicKey();
+
+ // Create identityCert
+ CertificateX509[] certChain = new CertificateX509[1];
+
+ UUID issuerCN = UUID.randomUUID();
+ ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
+ bb.putLong(issuerCN.getMostSignificantBits());
+ bb.putLong(issuerCN.getLeastSignificantBits());
+
+ /* generate the leaf cert */
+ certChain[0] = new CertificateX509(CertificateX509.CertificateType.IDENTITY_CERTIFICATE);
+ certChain[0].setSerial("0".getBytes());
+ certChain[0].setIssuerCN(bb.array());
+ certChain[0].setSubjectCN(bb.array());
+ certChain[0].setSubjectPublicKey(managerPublicKey.getPublicKey());
+ certChain[0].setSubjectAltName("ManagerAlias".getBytes());
+
+ long validFrom = System.currentTimeMillis() / 1000;
+ certChain[0].setValidity(validFrom, validFrom + expiredInSecs);
+
+ managerConfigurator.signCertificate(certChain[0]);
+
+ KeyInfoNISTP256 keyInfo = managerConfigurator.getSigningPublicKey();
+ certChain[0].verify(keyInfo.getPublicKey());
+
+ CryptoECC cryptoECC = new CryptoECC();
+ cryptoECC.generateDSAKeyPair();
+ String signedManifestXml = SecurityApplicationProxy.signManifest(certChain[0], cryptoECC.getDSAPrivateKey(), defaultManifestXml);
+
+ String[] signedManifestXmls = new String[]{signedManifestXml};
+ managerConfigurator.claim(managerPublicKey, issuerCN, managerPublicKey, certChain, signedManifestXmls);
+
+ for (int ms = 0; ms < 2000; ms++) {
+ Thread.sleep(5);
+ if (stateMap.get(managerBusUniqueName) == PermissionConfigurator.ApplicationState.CLAIMED) {
+ break;
+ }
+ }
+ assertEquals(stateMap.get(managerBusUniqueName), PermissionConfigurator.ApplicationState.CLAIMED);
+
+ // Create identityCert for peer
+ CertificateX509[] certChainPeer = new CertificateX509[1];
+
+ /* generate the leaf cert */
+ certChainPeer[0] = new CertificateX509(CertificateX509.CertificateType.IDENTITY_CERTIFICATE);
+ certChainPeer[0].setSerial("0".getBytes());
+ certChainPeer[0].setIssuerCN(bb.array());
+ certChainPeer[0].setSubjectCN(bb.array());
+ certChainPeer[0].setSubjectPublicKey(peerKey.getPublicKey());
+ certChainPeer[0].setSubjectAltName("Peer1Alias".getBytes());
+
+ validFrom = System.currentTimeMillis() / 1000;
+ certChainPeer[0].setValidity(validFrom, validFrom + expiredInSecs);
+
+ pcPeer.signCertificate(certChainPeer[0]);
+
+ KeyInfoNISTP256 keyInfo2 = pcPeer.getSigningPublicKey();
+ certChainPeer[0].verify(keyInfo2.getPublicKey());
+
+ String signedManifestXml2 = SecurityApplicationProxy.signManifest(certChainPeer[0], cryptoECC.getDSAPrivateKey(), defaultManifestXml);
+
+ String [] signedManifestXmls2 = new String[]{signedManifestXml2};
+
+ //Manager claims Peers
+ sapWithPeer.claim(managerPublicKey, issuerCN, managerPublicKey, certChainPeer, signedManifestXmls2);
+
+ for (int ms = 0; ms < 2000; ms++) {
+ Thread.sleep(5);
+ if (stateMap.get(peerBusUniqueName) == PermissionConfigurator.ApplicationState.CLAIMED) {
+ break;
+ }
+ }
+ assertEquals(stateMap.get(peerBusUniqueName), PermissionConfigurator.ApplicationState.CLAIMED);
+
+ CertificateX509[] certChainMembership = new CertificateX509[1];
+
+ /* generate the leaf cert */
+ certChainMembership[0] = new CertificateX509(CertificateX509.CertificateType.MEMBERSHIP_CERTIFICATE);
+ certChainMembership[0].setSerial("1".getBytes());
+ certChainMembership[0].setIssuerCN(bb.array());
+ certChainMembership[0].setSubjectCN(managerBusUniqueName.getBytes());
+ certChainMembership[0].setSubjectPublicKey(managerPublicKey.getPublicKey());
+ certChainMembership[0].setSubjectAltName(bb.array());
+ certChainMembership[0].setCA(true);
+
+ validFrom = System.currentTimeMillis() / 1000;
+ certChainMembership[0].setValidity(validFrom, validFrom + expiredInSecs);
+
+ managerConfigurator.signCertificate(certChainMembership[0]);
+ managerConfigurator.installMembership(certChainMembership);
+
+ }
+
+ private ApplicationStateListener appStateListener = new ApplicationStateListener() {
+
+ public void state(String busName, KeyInfoNISTP256 publicKeyInfo, PermissionConfigurator.ApplicationState state) {
+ System.out.println("state callback was called on this bus " + busName);
+ stateMap.put(busName, state);
+ }
+
+ };
+
+ private PermissionConfigurationListener pclistener = new PermissionConfigurationListener() {
+
+ public Status factoryReset() {
+ return Status.OK;
+ }
+
+ public void policyChanged() {
+ }
+
+ public void startManagement() {
+ }
+
+ public void endManagement() {
+ }
+ };
+
+ public class JoinSessionSessionListener extends SessionListener{
+ }
+
+ private AuthListener authListener = new AuthListener() {
+ public boolean requested(String mechanism, String authPeer, int count, String userName,
+ AuthRequest[] requests) {
+ return true;
+ }
+
+ public void completed(String mechanism, String authPeer, boolean authenticated) {}
+ };
+}