Merge branch 'security-summit' into 'master'
authorSachin Agrawal <sachin.agrawal@intel.com>
Sun, 20 Sep 2015 02:14:42 +0000 (19:14 -0700)
committerSachin Agrawal <sachin.agrawal@intel.com>
Sun, 20 Sep 2015 02:14:42 +0000 (19:14 -0700)
* security-summit:
  Added AMS functionality to support on-demand ACL provisioning.
  Added Android support for Provisioning APIs
  Quick fix on getting secure port information

Conflicts:
android/android_api/base/jni/JniOcStack.cpp
android/examples/settings.gradle
resource/csdk/security/include/internal/secureresourcemanager.h
resource/csdk/security/src/secureresourcemanager.c

Change-Id: I57d1157e4c1e74425fe27757e7dfa8a4ef8d427a
Signed-off-by: Sachin Agrawal <sachin.agrawal@intel.com>
63 files changed:
android/android_api/SConscript
android/android_api/base/build.gradle
android/android_api/base/jni/Android.mk
android/android_api/base/jni/JniOcProvisioning.cpp [new file with mode: 0644]
android/android_api/base/jni/JniOcProvisioning.h [new file with mode: 0644]
android/android_api/base/jni/JniOcSecureResource.cpp [new file with mode: 0644]
android/android_api/base/jni/JniOcSecureResource.h [new file with mode: 0644]
android/android_api/base/jni/JniOcStack.cpp
android/android_api/base/jni/JniOcStack.h
android/android_api/base/jni/JniPinCheckListener.cpp [new file with mode: 0644]
android/android_api/base/jni/JniPinCheckListener.h [new file with mode: 0644]
android/android_api/base/jni/JniProvisionResultListner.cpp [new file with mode: 0644]
android/android_api/base/jni/JniProvisionResultListner.h [new file with mode: 0644]
android/android_api/base/jni/JniSecureUtils.cpp [new file with mode: 0644]
android/android_api/base/jni/JniSecureUtils.h [new file with mode: 0644]
android/android_api/base/src/main/java/org/iotivity/base/CredType.java [new file with mode: 0644]
android/android_api/base/src/main/java/org/iotivity/base/DeviceStatus.java [new file with mode: 0644]
android/android_api/base/src/main/java/org/iotivity/base/KeySize.java [new file with mode: 0644]
android/android_api/base/src/main/java/org/iotivity/base/OcProvisioning.java [new file with mode: 0644]
android/android_api/base/src/main/java/org/iotivity/base/OcSecureResource.java [new file with mode: 0644]
android/android_api/base/src/main/java/org/iotivity/base/OicSecAcl.java [new file with mode: 0644]
android/android_api/base/src/main/java/org/iotivity/base/OwnedStatus.java [new file with mode: 0644]
android/android_api/base/src/main/java/org/iotivity/base/OxmType.java [new file with mode: 0644]
android/android_api/base/src/main/java/org/iotivity/base/ProvisionResult.java [new file with mode: 0644]
android/examples/provisioningclient/build.gradle [new file with mode: 0644]
android/examples/provisioningclient/proguard-rules.pro [new file with mode: 0644]
android/examples/provisioningclient/provisioningclient.iml [new file with mode: 0644]
android/examples/provisioningclient/src/main/AndroidManifest.xml [new file with mode: 0644]
android/examples/provisioningclient/src/main/assets/oic_svr_db_client.json [new file with mode: 0644]
android/examples/provisioningclient/src/main/java/org/iotivity/base/examples/provisioningclient/ProvisioningClient.java [new file with mode: 0644]
android/examples/provisioningclient/src/main/java/org/iotivity/base/examples/provisioningclient/StringConstants.java [new file with mode: 0644]
android/examples/provisioningclient/src/main/res/layout/activity_secure_provision_client.xml [new file with mode: 0644]
android/examples/provisioningclient/src/main/res/menu/menu_secure_provision_client.xml [new file with mode: 0644]
android/examples/provisioningclient/src/main/res/mipmap-hdpi/ic_launcher.png [new file with mode: 0644]
android/examples/provisioningclient/src/main/res/mipmap-mdpi/ic_launcher.png [new file with mode: 0644]
android/examples/provisioningclient/src/main/res/mipmap-xhdpi/ic_launcher.png [new file with mode: 0644]
android/examples/provisioningclient/src/main/res/mipmap-xxhdpi/ic_launcher.png [new file with mode: 0644]
android/examples/provisioningclient/src/main/res/values-v21/styles.xml [new file with mode: 0644]
android/examples/provisioningclient/src/main/res/values-w820dp/dimens.xml [new file with mode: 0644]
android/examples/provisioningclient/src/main/res/values/dimens.xml [new file with mode: 0644]
android/examples/provisioningclient/src/main/res/values/strings.xml [new file with mode: 0644]
android/examples/provisioningclient/src/main/res/values/styles.xml [new file with mode: 0644]
android/examples/settings.gradle
resource/csdk/security/SConscript
resource/csdk/security/include/internal/aclresource.h
resource/csdk/security/include/internal/amaclresource.h
resource/csdk/security/include/internal/amsmgr.h [new file with mode: 0644]
resource/csdk/security/include/internal/policyengine.h
resource/csdk/security/include/internal/secureresourcemanager.h
resource/csdk/security/include/securevirtualresourcetypes.h
resource/csdk/security/src/aclresource.c
resource/csdk/security/src/amaclresource.c
resource/csdk/security/src/amsmgr.c [new file with mode: 0644]
resource/csdk/security/src/policyengine.c
resource/csdk/security/src/secureresourcemanager.c
resource/csdk/security/unittest/policyengine.cpp
resource/csdk/stack/samples/linux/secure/README [new file with mode: 0644]
resource/csdk/stack/samples/linux/secure/SConscript
resource/csdk/stack/samples/linux/secure/ocamsservice.cpp [new file with mode: 0644]
resource/csdk/stack/samples/linux/secure/oic_amss_db.json [new file with mode: 0644]
resource/csdk/stack/samples/linux/secure/oic_svr_db_server.json
resource/provisioning/examples/SConscript
resource/provisioning/unittests/SConscript

index f2bc851..0f27318 100644 (file)
@@ -9,6 +9,7 @@ if env.get('RELEASE'):
        ANDROID_RELEASE="release"
 else:
        ANDROID_RELEASE="debug"
+ANDROID_SECURED = env.get('SECURED')
 
 os.environ['ANDROID_HOME'] = env.get('ANDROID_HOME')
 os.environ['ANDROID_NDK_HOME'] = env.get('ANDROID_NDK')
@@ -46,6 +47,6 @@ def ensure_libs(target, source, env):
     return target, [source, env.get('BUILD_DIR') + 'liboc.so', env.get('BUILD_DIR') + 'liboc_logger.so']
 
 jdk_env = Environment(ENV=os.environ)
-jdk_env['BUILDERS']['Gradle'] = Builder(action = env.get('ANDROID_GRADLE') + ' build -b' + os.getcwd()+'/build.gradle -PTARGET_ARCH=%s -PRELEASE=%s --stacktrace' %(ANDROID_TARGET_ARCH, ANDROID_RELEASE), emitter = ensure_libs)
+jdk_env['BUILDERS']['Gradle'] = Builder(action = env.get('ANDROID_GRADLE') + ' build -b' + os.getcwd()+'/build.gradle -PSECURED=%s -PTARGET_ARCH=%s -PRELEASE=%s --stacktrace' %(ANDROID_SECURED, ANDROID_TARGET_ARCH, ANDROID_RELEASE), emitter = ensure_libs)
 jdk_env['BUILD_DIR'] = env.get('BUILD_DIR')
 jdk_env.Gradle(target="base/objs", source="base/src/main/java/org/iotivity/base/OcResource.java")
index 9cbdaf8..afeb10d 100755 (executable)
@@ -94,7 +94,7 @@ task buildNative(type: Exec) {
         //for windows use 'ndk-build.cmd'\r
         //def ndkBuild = new File(System.env.ANDROID_NDK_HOME, 'ndk-build.cmd')\r
         def ndkBuild = new File(System.env.ANDROID_NDK_HOME, 'ndk-build')\r
-        commandLine ndkBuild, "APP_ABI=$TARGET_ARCH", "APP_OPTIM=$RELEASE"\r
+        commandLine ndkBuild, "APP_ABI=$TARGET_ARCH", "APP_OPTIM=$RELEASE", "SECURE=$SECURED"
     } else {\r
         println '##################'\r
         println 'Skipping NDK build'\r
index f29d75a..05172ee 100644 (file)
@@ -1,5 +1,6 @@
 LOCAL_PATH := $(call my-dir)\r
 TARGET_ARCH_ABI := $(APP_ABI)\r
+SECURED := $(SECURE)
 \r
 include $(CLEAR_VARS)\r
 OIC_LIB_PATH := ../../../../out/android/$(APP_ABI)/$(APP_OPTIM)\r
@@ -25,6 +26,20 @@ LOCAL_MODULE := libandroid-ca
 LOCAL_SRC_FILES := $(OIC_LIB_PATH)/libconnectivity_abstraction.so\r
 include $(PREBUILT_SHARED_LIBRARY)\r
 \r
+ifeq ($(SECURED), 1)
+include $(CLEAR_VARS)
+OIC_LIB_PATH := ../../../../out/android/$(APP_ABI)/$(APP_OPTIM)
+LOCAL_MODULE := libandroid-ocprovision
+LOCAL_SRC_FILES := $(OIC_LIB_PATH)/libocprovision.a
+include $(PREBUILT_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+OIC_LIB_PATH := ../../../../out/android/$(APP_ABI)/$(APP_OPTIM)
+LOCAL_MODULE := libandroid-ocpmapi
+LOCAL_SRC_FILES := $(OIC_LIB_PATH)/libocpmapi.a
+include $(PREBUILT_STATIC_LIBRARY)
+endif
+
 include $(CLEAR_VARS)\r
 OIC_SRC_PATH := ../../../resource\r
 LOCAL_MODULE := libca-interface\r
@@ -60,6 +75,13 @@ LOCAL_SRC_FILES :=  JniOcStack.cpp \
                     JniOcResource.cpp \\r
                     JniOcResourceIdentifier.cpp \
                     JniOcSecurity.cpp
+ifeq ($(SECURED), 1)
+LOCAL_SRC_FILES +=  JniOcSecureResource.cpp \
+                    JniOcProvisioning.cpp \
+                    JniSecureUtils.cpp \
+                    JniProvisionResultListner.cpp \
+                    JniPinCheckListener.cpp
+endif
 \r
 LOCAL_LDLIBS := -llog\r
 LOCAL_STATIC_LIBRARIES := android-oc\r
@@ -68,14 +90,23 @@ LOCAL_STATIC_LIBRARIES += android-coap
 LOCAL_STATIC_LIBRARIES += android-oc_logger\r
 LOCAL_STATIC_LIBRARIES += android-ca\r
 LOCAL_STATIC_LIBRARIES += android_cpp11_compat\r
+ifeq ($(SECURED), 1)
+LOCAL_STATIC_LIBRARIES += android-ocprovision
+LOCAL_STATIC_LIBRARIES += android-ocpmapi
+endif
 \r
 LOCAL_CPPFLAGS += -std=c++0x\r
 LOCAL_CPP_FEATURES := rtti exceptions\r
 LOCAL_C_INCLUDES := $(OIC_SRC_PATH)/include\r
 LOCAL_C_INCLUDES += $(OIC_SRC_PATH)/c_common\r
+LOCAL_C_INCLUDES += $(OIC_SRC_PATH)/c_common/oic_string/include
 LOCAL_C_INCLUDES += $(OIC_SRC_PATH)/csdk/stack/include\r
 LOCAL_C_INCLUDES += $(OIC_SRC_PATH)/csdk/ocsocket/include\r
 LOCAL_C_INCLUDES += $(OIC_SRC_PATH)/oc_logger/include\r
 LOCAL_C_INCLUDES += $(OIC_SRC_PATH)/../extlibs/boost/boost_1_58_0\r
 LOCAL_C_INCLUDES += $(OIC_SRC_PATH)/../build_common/android/compatibility\r
+LOCAL_C_INCLUDES += $(OIC_SRC_PATH)/csdk/security/provisioning/include
+LOCAL_C_INCLUDES += $(OIC_SRC_PATH)/csdk/security/provisioning/include/oxm/
+LOCAL_C_INCLUDES += $(OIC_SRC_PATH)/csdk/security/provisioning/include/internal
+LOCAL_C_INCLUDES += $(OIC_SRC_PATH)/csdk/security/include
 include $(BUILD_SHARED_LIBRARY)\r
diff --git a/android/android_api/base/jni/JniOcProvisioning.cpp b/android/android_api/base/jni/JniOcProvisioning.cpp
new file mode 100644 (file)
index 0000000..7813169
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+* //******************************************************************
+* //
+* // Copyright 2015 Samsung Electronics All Rights Reserved.
+* //
+* //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+* //
+* // Licensed 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.
+* //
+* //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+*/
+
+#include "JniOcProvisioning.h"
+#include "JniPinCheckListener.h"
+
+using namespace OC;
+namespace PH = std::placeholders;
+
+static JniPinCheckListener *PinListener = nullptr;
+
+void Callback(char *buf, size_t size)
+{
+    if (PinListener)
+    {
+        PinListener->PinCallback(buf, size);
+    }
+    else
+    {
+        LOGE("PinListener is null");
+    }
+}
+
+/*
+ * Class:     org_iotivity_base_OcProvisioning
+ * Method:    ownershipTransferCDdata
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcProvisioning_ownershipTransferCBdata
+  (JNIEnv *env, jobject thiz, jint OxmType, jobject jListener)
+{
+    LOGD("OcProvisioning_ownershipTransferCBdata");
+    OCStackResult result = OC_STACK_ERROR;
+
+    try
+    {
+        OTMCallbackData_t CBData = {0};
+        if (OIC_JUST_WORKS == (OicSecOxm_t)OxmType)
+        {
+            CBData.loadSecretCB = LoadSecretJustWorksCallback;
+            CBData.createSecureSessionCB = CreateSecureSessionJustWorksCallback;
+            CBData.createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload;
+            CBData.createOwnerTransferPayloadCB = CreateJustWorksOwnerTransferPayload;
+
+            result = OCSecure::setOwnerTransferCallbackData((OicSecOxm_t)OxmType,
+                    &CBData, NULL);
+        }
+        if (OIC_RANDOM_DEVICE_PIN == (OicSecOxm_t)OxmType)
+        {
+            if (jListener)
+            {
+                delete PinListener;
+                PinListener = new JniPinCheckListener(env, jListener);
+                CBData.loadSecretCB = InputPinCodeCallback;
+                CBData.createSecureSessionCB = CreateSecureSessionRandomPinCallbak;
+                CBData.createSelectOxmPayloadCB = CreatePinBasedSelectOxmPayload;
+                CBData.createOwnerTransferPayloadCB = CreatePinBasedOwnerTransferPayload;
+                result = OCSecure::setOwnerTransferCallbackData((OicSecOxm_t)OxmType,
+                        &CBData, Callback);
+            }
+            else
+            {
+                result = OC_STACK_ERROR;
+            }
+        }
+
+        if (OC_STACK_OK != result)
+        {
+            ThrowOcException(result, "OcProvisioning_ownershipTransferCDdata");
+            return;
+        }
+    }
+    catch (OCException& e)
+    {
+        LOGE("%s", e.reason().c_str());
+        ThrowOcException(e.code(), e.reason().c_str());
+    }
+}
+
+/*
+* Class:     org_iotivity_base_OcProvisioning
+* Method:    discoverUnownedDevices
+* Signature: (I)[Lorg/iotivity/base/OcSecureResource;
+*/
+JNIEXPORT jobjectArray JNICALL Java_org_iotivity_base_OcProvisioning_discoverUnownedDevices1
+  (JNIEnv *env, jclass clazz, jint timeout)
+{
+    LOGI("OcProvisioning_discoverUnownedDevices");
+    DeviceList_t list;
+
+    try
+    {
+        OCStackResult result = OCSecure::discoverUnownedDevices((unsigned short)timeout, list);
+
+        if (OC_STACK_OK != result)
+        {
+            ThrowOcException(result, "Failed to discover Unowned devices");
+            return nullptr;
+        }
+
+        return JniSecureUtils::convertDeviceVectorToJavaArray(env, list);
+    }
+    catch (OCException& e)
+    {
+        LOGE("%s", e.reason().c_str());
+        ThrowOcException(OC_STACK_ERROR, e.reason().c_str());
+    }
+}
+
+/*
+ * Class:     org_iotivity_base_OcProvisioning
+ * Method:    provisionInit
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcProvisioning_provisionInit
+  (JNIEnv *env, jclass calzz, jstring jdbPath)
+{
+    LOGI("OcProvisioning_provisionInit");
+    char *dbpath;
+
+    if (!jdbPath)
+    {
+        ThrowOcException(OC_STACK_INVALID_PARAM, "SVR db path cannot be null");
+        return;
+    }
+
+    try
+    {
+        dbpath = (char*)env->GetStringUTFChars(jdbPath, NULL);
+        OCStackResult result = OCSecure::provisionInit(env->GetStringUTFChars(jdbPath, NULL));
+
+        if (OC_STACK_OK != result)
+        {
+            env->ReleaseStringUTFChars(jdbPath, (const char*)dbpath);
+            ThrowOcException(result, "Failed to Init Provisioning Manager");
+            return;
+        }
+        env->ReleaseStringUTFChars(jdbPath, (const char*)dbpath);
+    }
+    catch (OCException& e)
+    {
+        LOGE("%s", e.reason().c_str());
+        ThrowOcException(OC_STACK_ERROR, e.reason().c_str());
+    }
+}
+
+/*
+ * Class:     org_iotivity_base_OcProvisioning
+ * Method:    discoverOwnedDevices
+ * Signature: (I)[Lorg/iotivity/base/OcSecureResource;
+ */
+JNIEXPORT jobjectArray JNICALL Java_org_iotivity_base_OcProvisioning_discoverOwnedDevices1
+  (JNIEnv *env, jclass clazz , jint timeout)
+{
+    LOGI("OcProvisioning_discoverOwnedDevices");
+    DeviceList_t list;
+
+    try
+    {
+        OCStackResult result = OCSecure::discoverOwnedDevices((unsigned short)timeout, list);
+        if (OC_STACK_OK != result)
+        {
+            ThrowOcException(result, "Failed to discover Owned devices");
+            return nullptr;
+        }
+
+        return JniSecureUtils::convertDeviceVectorToJavaArray(env, list);
+    }
+    catch (OCException& e)
+    {
+        LOGE("%s", e.reason().c_str());
+        ThrowOcException(OC_STACK_ERROR, e.reason().c_str());
+    }
+}
+
+/*
+ * Class:     org_iotivity_base_OcProvisioning
+ * Method:    getDevicestatusLists
+ * Signature: (I)[Lorg/iotivity/base/OcSecureResource;
+ */
+JNIEXPORT jobjectArray JNICALL Java_org_iotivity_base_OcProvisioning_getDeviceStatusList1
+  (JNIEnv *env, jclass clazz, jint timeout)
+{
+    LOGI("OcProvisioning_getDeviceStatusList");
+    DeviceList_t  ownedDevList, unownedDevList;
+
+    try
+    {
+        OCStackResult result = OCSecure::getDevInfoFromNetwork((unsigned short)timeout,
+                ownedDevList, unownedDevList);
+        if (OC_STACK_OK != result)
+        {
+            ThrowOcException(result, "Failed to get Device Status List");
+            return nullptr;
+        }
+        ownedDevList.insert(ownedDevList.end(), unownedDevList.begin(), unownedDevList.end());
+        return JniSecureUtils::convertDeviceVectorToJavaArray(env, ownedDevList);
+    }
+    catch (OCException& e)
+    {
+        LOGE("%s", e.reason().c_str());
+        ThrowOcException(OC_STACK_ERROR, e.reason().c_str());
+    }
+}
diff --git a/android/android_api/base/jni/JniOcProvisioning.h b/android/android_api/base/jni/JniOcProvisioning.h
new file mode 100644 (file)
index 0000000..fe5bd9a
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+* //******************************************************************
+* //
+* // Copyright 2015 Samsung Electronics All Rights Reserved.
+* //
+* //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+* //
+* // Licensed 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.
+* //
+* //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+*/
+#include "JniOcStack.h"
+#include "OCProvisioningManager.h"
+#include "JniSecureUtils.h"
+#include "oxmjustworks.h"
+#include "oxmrandompin.h"
+#include <jni.h>
+#include <mutex>
+
+#ifndef _Included_org_iotivity_base_OcProvisioning
+#define _Included_org_iotivity_base_OcProvisioning
+
+using namespace OC;
+
+/* DO NOT EDIT THIS FILE - it is machine generated */
+/* Header for class org_iotivity_base_OcProvisioning */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class:     org_iotivity_base_OcProvisioning
+ * Method:    ownershipTransferCDdata
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcProvisioning_ownershipTransferCBdata
+  (JNIEnv *, jobject, jint, jobject);
+
+/*
+ * Class:     org_iotivity_base_OcProvisioning
+ * Method:    discoverUnownedDevices
+ * Signature: (I)[Lorg/iotivity/base/OcSecureResource;
+ */
+JNIEXPORT jobjectArray JNICALL Java_org_iotivity_base_OcProvisioning_discoverUnownedDevices1
+  (JNIEnv *, jclass, jint);
+
+/*
+ * Class:     org_iotivity_base_OcProvisioning
+ * Method:    provisionInit
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcProvisioning_provisionInit
+  (JNIEnv *, jclass, jstring);
+
+/*
+ * Class:     org_iotivity_base_OcProvisioning
+ * Method:    discoverOwnedDevices
+ * Signature: (I)[Lorg/iotivity/base/OcSecureResource;
+ */
+JNIEXPORT jobjectArray JNICALL Java_org_iotivity_base_OcProvisioning_discoverOwnedDevices1
+  (JNIEnv *, jclass, jint);
+
+/*
+ * Class:     org_iotivity_base_OcProvisioning
+ * Method:    getDevicestatusLists
+ * Signature: (I)[Lorg/iotivity/base/OcSecureResource;
+ */
+JNIEXPORT jobjectArray JNICALL Java_org_iotivity_base_OcProvisioning_getDeviceStatusList1
+  (JNIEnv *, jclass, jint);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/android/android_api/base/jni/JniOcSecureResource.cpp b/android/android_api/base/jni/JniOcSecureResource.cpp
new file mode 100644 (file)
index 0000000..d2929de
--- /dev/null
@@ -0,0 +1,653 @@
+/*
+* //******************************************************************
+* //
+* // Copyright 2015 Samsung Electronics All Rights Reserved.
+* //
+* //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+* //
+* // Licensed 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.
+* //
+* //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+*/
+
+#include "JniOcSecureResource.h"
+#include "JniSecureUtils.h"
+namespace PH = std::placeholders;
+
+JniOcSecureResource::JniOcSecureResource(std::shared_ptr<OCSecureResource> device)
+    : m_sharedSecureResource(device)
+{}
+
+JniOcSecureResource::~JniOcSecureResource()
+{
+    LOGD("~JniOcSecureResource()");
+    m_sharedSecureResource = nullptr;
+}
+
+std::string JniOcSecureResource::getIpAddr()
+{
+    return m_sharedSecureResource->getDevAddr();
+}
+
+std::string JniOcSecureResource::getDeviceID()
+{
+    return m_sharedSecureResource->getDeviceID();
+}
+
+int JniOcSecureResource::getDeviceStatus()
+{
+    return m_sharedSecureResource->getDeviceStatus();
+}
+
+bool JniOcSecureResource::getOwnedStatus()
+{
+    return m_sharedSecureResource->getOwnedStatus();
+}
+
+OCSecureResource* JniOcSecureResource::getDevicePtr()
+{
+    return m_sharedSecureResource.get();
+}
+
+JniOcSecureResource* JniOcSecureResource::getJniOcSecureResourcePtr(JNIEnv *env, jobject thiz)
+{
+    JniOcSecureResource *secureResource = GetHandle<JniOcSecureResource>(env, thiz);
+    if (env->ExceptionCheck())
+    {
+        LOGE("Failed to get native handle from OcSecureResource");
+    }
+    if (!secureResource)
+    {
+        ThrowOcException(JNI_NO_NATIVE_POINTER, "");
+    }
+    return secureResource;
+}
+
+JniProvisionResultListner* JniOcSecureResource::AddProvisionResultListener(JNIEnv* env,
+        jobject jListener)
+{
+    JniProvisionResultListner *resultListener = NULL;
+    resultMapLock.lock();
+
+    for (auto it = resultMap.begin(); it != resultMap.end(); ++it)
+    {
+        if (env->IsSameObject(jListener, it->first))
+        {
+            auto refPair = it->second;
+            resultListener = refPair.first;
+            refPair.second++;
+            it->second = refPair;
+            resultMap.insert(*it);
+            LOGD("Provision resultListener: ref. count incremented");
+            break;
+        }
+    }
+    if (!resultListener)
+    {
+        resultListener = new JniProvisionResultListner(env, jListener,
+            RemoveCallback(std::bind(&JniOcSecureResource::RemoveProvisionResultListener,
+                    this, PH::_1, PH::_2)));
+        jobject jgListener = env->NewGlobalRef(jListener);
+
+        resultMap.insert(std::pair < jobject, std::pair < JniProvisionResultListner*,
+                int >> (jgListener, std::pair<JniProvisionResultListner*, int>(resultListener, 1)));
+        LOGD("Provision resultListener: new listener");
+    }
+    resultMapLock.unlock();
+    return resultListener;
+}
+
+void JniOcSecureResource::RemoveProvisionResultListener(JNIEnv* env, jobject jListener)
+{
+    resultMapLock.lock();
+
+    for (auto it = resultMap.begin(); it != resultMap.end(); ++it)
+    {
+        if (env->IsSameObject(jListener, it->first))
+        {
+            auto refPair = it->second;
+            if (refPair.second > 1)
+            {
+                refPair.second--;
+                it->second = refPair;
+                resultMap.insert(*it);
+                LOGI("Provision resultListener: ref. count decremented");
+            }
+            else
+            {
+                env->DeleteGlobalRef(it->first);
+                JniProvisionResultListner* listener = refPair.first;
+                delete listener;
+                resultMap.erase(it);
+                LOGI("Provision resultListener removed");
+            }
+            break;
+        }
+    }
+    resultMapLock.unlock();
+}
+
+OCStackResult JniOcSecureResource::doOwnershipTransfer(JNIEnv* env, jobject jListener)
+{
+    JniProvisionResultListner *resultListener = AddProvisionResultListener(env, jListener);
+
+    ResultCallBack resultCallback = [resultListener](PMResultList_t *result, int hasError)
+    {
+        resultListener->ProvisionResultCallback(result, hasError, ListenerFunc::OWNERSHIPTRANSFER);
+    };
+
+    return m_sharedSecureResource->doOwnershipTransfer(resultCallback);
+}
+
+OCStackResult JniOcSecureResource::getLinkedDevices(JNIEnv *env, UuidList_t &uuidList)
+{
+    return m_sharedSecureResource->getLinkedDevices(uuidList);
+}
+
+OCStackResult JniOcSecureResource::removeDevice(JNIEnv* env, jint timeout, jobject jListener)
+{
+    JniProvisionResultListner *resultListener = AddProvisionResultListener(env, jListener);
+
+    ResultCallBack resultCallback = [resultListener](PMResultList_t *result, int hasError)
+    {
+        resultListener->ProvisionResultCallback(result, hasError, ListenerFunc::REMOVEDEVICE);
+    };
+
+    return m_sharedSecureResource->removeDevice((int)timeout, resultCallback);
+}
+
+OCStackResult JniOcSecureResource::unlinkDevices(JNIEnv* env, jobject _device2, jobject jListener)
+{
+    JniProvisionResultListner *resultListener = AddProvisionResultListener(env, jListener);
+
+    ResultCallBack resultCallback = [resultListener](PMResultList_t *result, int hasError)
+    {
+        resultListener->ProvisionResultCallback(result, hasError, ListenerFunc::UNLINKDEVICES);
+    };
+
+    JniOcSecureResource *device2 = JniOcSecureResource::getJniOcSecureResourcePtr(env, _device2);
+    if (!device2)
+    {
+        return OC_STACK_ERROR;
+    }
+
+    return m_sharedSecureResource->unlinkDevices(*device2->getDevicePtr(), resultCallback);
+}
+
+OCStackResult JniOcSecureResource::provisionCredentials(JNIEnv* env, jint type, jint keySize,
+        jobject _device2, jobject jListener)
+{
+    JniProvisionResultListner *resultListener = AddProvisionResultListener(env, jListener);
+
+    ResultCallBack resultCallback = [resultListener](PMResultList_t *result, int hasError)
+    {
+        resultListener->ProvisionResultCallback(result, hasError, ListenerFunc::PROVISIONCREDENTIALS);
+    };
+
+    JniOcSecureResource *device2 = JniOcSecureResource::getJniOcSecureResourcePtr(env, _device2);
+    if (!device2)
+    {
+        return OC_STACK_ERROR;
+    }
+
+    Credential cred((OicSecCredType_t)type, keySize);
+
+    return m_sharedSecureResource->provisionCredentials(cred, *device2->getDevicePtr(),
+            resultCallback);
+}
+
+OCStackResult JniOcSecureResource::provisionACL(JNIEnv* env, jobject _acl, jobject jListener)
+{
+    OCStackResult ret;
+    JniProvisionResultListner *resultListener = AddProvisionResultListener(env, jListener);
+    OicSecAcl_t *acl = new OicSecAcl_t;
+    acl->next = nullptr;
+    if (!acl)
+    {
+        return OC_STACK_NO_MEMORY;
+    }
+
+    if (OC_STACK_OK != JniSecureUtils::convertJavaACLToOCAcl(env, _acl, acl))
+    {
+        delete acl;
+        return OC_STACK_ERROR;
+    }
+
+    ResultCallBack resultCallback = [acl, resultListener](PMResultList_t *result, int hasError)
+    {
+        delete acl;
+        resultListener->ProvisionResultCallback(result, hasError, ListenerFunc::PROVISIONACL);
+    };
+    ret = m_sharedSecureResource->provisionACL(acl, resultCallback);
+
+    if (ret != OC_STACK_OK)
+    {
+        delete acl;
+
+    }
+    return ret;
+}
+
+OCStackResult JniOcSecureResource::provisionPairwiseDevices(JNIEnv* env, jint type, jint keySize,
+        jobject _acl1, jobject _device2, jobject _acl2, jobject jListener)
+{
+    OCStackResult ret;
+
+    JniProvisionResultListner *resultListener = AddProvisionResultListener(env, jListener);
+    JniOcSecureResource *device2 = JniOcSecureResource::getJniOcSecureResourcePtr(env, _device2);
+    if (!device2)
+    {
+        return OC_STACK_ERROR;
+    }
+
+    Credential cred((OicSecCredType_t)type, keySize);
+
+    OicSecAcl_t *acl1 = nullptr;
+    OicSecAcl_t *acl2 = nullptr;
+
+    if (_acl1)
+    {
+        acl1 = new OicSecAcl_t;
+        if (!acl1)
+        {
+            return OC_STACK_NO_MEMORY;
+        }
+
+        if (OC_STACK_OK != JniSecureUtils::convertJavaACLToOCAcl(env, _acl1, acl1))
+        {
+            delete acl1;
+            return OC_STACK_ERROR;
+        }
+        acl1->next = nullptr;
+    }
+
+    if (_acl2)
+    {
+        acl2 = new OicSecAcl_t;
+        if (!acl2)
+        {
+            delete acl1;
+            return OC_STACK_NO_MEMORY;
+        }
+
+        if (OC_STACK_OK != JniSecureUtils::convertJavaACLToOCAcl(env, _acl2, acl2))
+        {
+            delete acl2;
+            return OC_STACK_ERROR;
+        }
+        acl2->next = nullptr;
+    }
+
+    ResultCallBack resultCallback = [acl1, acl2, resultListener](PMResultList_t *result,
+            int hasError)
+    {
+        delete acl1;
+        delete acl2;
+        resultListener->ProvisionResultCallback(result, hasError,
+                ListenerFunc::PROVISIONPAIRWISEDEVICES);
+    };
+
+
+    ret = m_sharedSecureResource->provisionPairwiseDevices(cred, acl1,
+            *device2->getDevicePtr(), acl2, resultCallback);
+    if (ret != OC_STACK_OK)
+    {
+        delete acl1;
+        delete acl2;
+    }
+    return ret;
+}
+
+/*
+ * Class:     org_iotivity_base_OcSecureResource
+ * Method:    doOwnershipTransfer
+ * Signature: (Lorg/iotivity/base/OcSecureResource/doOwnershipTransferListener;)V
+ */
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcSecureResource_doOwnershipTransfer
+(JNIEnv *env, jobject thiz, jobject jListener)
+{
+    LOGD("OcSecureResource_doOwnershipTransfer");
+    if (!jListener)
+    {
+        ThrowOcException(OC_STACK_INVALID_PARAM, "provisionResultListener cannot be null");
+        return;
+    }
+
+    JniOcSecureResource *secureResource = JniOcSecureResource::getJniOcSecureResourcePtr(env, thiz);
+    if (!secureResource)
+    {
+        return;
+    }
+
+    try
+    {
+        OCStackResult result = secureResource->doOwnershipTransfer(env, jListener);
+        if (OC_STACK_OK != result)
+        {
+            ThrowOcException(result, "OcSecureResource_doOwnershipTransfer");
+            return;
+        }
+    }
+    catch (OCException& e)
+    {
+        LOGE("%s", e.reason().c_str());
+        ThrowOcException(e.code(), e.reason().c_str());
+    }
+}
+
+/*
+ * Class:     org_iotivity_base_OcSecureResource
+ * Method:    removeDevice
+ * Signature: (ILorg/iotivity/base/OcSecureResource/removeDevice;)V
+ */
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcSecureResource_removeDevice
+(JNIEnv *env, jobject thiz, jint timeout, jobject jListener)
+{
+    LOGD("OcSecureResource_removeDevice");
+    if (!jListener)
+    {
+        ThrowOcException(OC_STACK_INVALID_PARAM, "provisionResultListener cannot be null");
+        return;
+    }
+
+    JniOcSecureResource *secureResource = JniOcSecureResource::getJniOcSecureResourcePtr(env, thiz);
+    if (!secureResource)
+    {
+        return;
+    }
+
+    try
+    {
+        OCStackResult result = secureResource->removeDevice(env, timeout, jListener);
+        if (OC_STACK_OK != result)
+        {
+            ThrowOcException(result, "OcSecureResource_removeDevice");
+            return;
+        }
+    }
+    catch (OCException& e)
+    {
+        LOGE("%s", e.reason().c_str());
+        ThrowOcException(e.code(), e.reason().c_str());
+    }
+}
+
+/*
+ * Class:     org_iotivity_base_OcSecureResource
+ * Method:    unlinkDevices
+ * Signature: (Lorg/iotivity/base/OcSecureResource/unlinkDevices;)V
+ */
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcSecureResource_unlinkDevices
+(JNIEnv *env, jobject thiz, jobject device2, jobject jListener)
+{
+    LOGD("OcSecureResource_unlinkDevices");
+    if (!jListener)
+    {
+        ThrowOcException(OC_STACK_INVALID_PARAM, "provisionResultListener cannot be null");
+        return;
+    }
+
+    JniOcSecureResource *secureResource = JniOcSecureResource::getJniOcSecureResourcePtr(env, thiz);
+    if (!secureResource)
+    {
+        return;
+    }
+
+    try
+    {
+        OCStackResult result = secureResource->unlinkDevices(env, device2, jListener);
+        if (OC_STACK_OK != result)
+        {
+            ThrowOcException(result, "OcSecureResource_unlinkDevices");
+            return;
+        }
+    }
+    catch (OCException& e)
+    {
+        LOGE("%s", e.reason().c_str());
+        ThrowOcException(e.code(), e.reason().c_str());
+    }
+}
+
+/*
+ * Class:     org_iotivity_base_OcSecureResource
+ * Method:    provisionCredentials1
+ * Signature: (Lorg/iotivity/base/OcSecureResource/provisionCredentials;)V
+ */
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcSecureResource_provisionCredentials1
+(JNIEnv *env, jobject thiz, jint type, jint keySize, jobject device2, jobject jListener)
+{
+    LOGD("OcSecureResource_provisionCredentials");
+    if (!jListener)
+    {
+        ThrowOcException(OC_STACK_INVALID_PARAM, "provisionResultListener cannot be null");
+        return;
+    }
+
+    JniOcSecureResource *secureResource = JniOcSecureResource::getJniOcSecureResourcePtr(env, thiz);
+    if (!secureResource)
+    {
+        return;
+    }
+
+    try
+    {
+        OCStackResult result = secureResource->provisionCredentials(env, type, keySize, device2,
+                jListener);
+        if (OC_STACK_OK != result)
+        {
+            ThrowOcException(result, "OcSecureResource_provisionCredentials");
+            return;
+        }
+    }
+    catch (OCException& e)
+    {
+        LOGE("%s", e.reason().c_str());
+        ThrowOcException(e.code(), e.reason().c_str());
+    }
+}
+
+/*
+ * Class:     org_iotivity_base_OcSecureResource
+ * Method:    provisionACL
+ * Signature: (Lorg/iotivity/base/OcSecureResource/provisionACL;)V
+ */
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcSecureResource_provisionACL
+(JNIEnv *env, jobject thiz, jobject acl, jobject jListener)
+{
+    LOGD("OcSecureResource_provisionACL");
+    if (!jListener)
+    {
+        ThrowOcException(OC_STACK_INVALID_PARAM, "provisionResultListener cannot be null");
+        return;
+    }
+
+    JniOcSecureResource *secureResource = JniOcSecureResource::getJniOcSecureResourcePtr(env, thiz);
+    if (!secureResource)
+    {
+        return;
+    }
+
+    try
+    {
+        OCStackResult result = secureResource->provisionACL(env, acl, jListener);
+        if (OC_STACK_OK != result)
+        {
+            ThrowOcException(result, "OcSecureResource_provisionACL");
+            return;
+        }
+    }
+    catch (OCException& e)
+    {
+        LOGE("%s", e.reason().c_str());
+        ThrowOcException(e.code(), e.reason().c_str());
+    }
+}
+
+/*
+ * Class:     org_iotivity_base_OcSecureResource
+ * Method:    provisionPairwiseDevices1
+ * Signature: (Lorg/iotivity/base/OcSecureResource/provisionPairwiseDevices;)V
+ */
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcSecureResource_provisionPairwiseDevices1
+(JNIEnv *env, jobject thiz, jint type, jint keySize, jobject acl1, jobject device2,
+        jobject acl2, jobject jListener)
+{
+    LOGD("OcSecureResource_provisionPairwiseDevices");
+    if (!jListener)
+    {
+        ThrowOcException(OC_STACK_INVALID_PARAM, "provisionResultListener cannot be null");
+        return;
+    }
+
+    JniOcSecureResource *secureResource = JniOcSecureResource::getJniOcSecureResourcePtr(env, thiz);
+    if (!secureResource)
+    {
+        return;
+    }
+
+    try
+    {
+        OCStackResult result = secureResource->provisionPairwiseDevices(env, type, keySize,
+                acl1, device2, acl2, jListener);
+        if (OC_STACK_OK != result)
+        {
+            ThrowOcException(result, "OcSecureResource_provisionPairwiseDevices");
+            return;
+        }
+    }
+    catch (OCException& e)
+    {
+        LOGE("%s", e.reason().c_str());
+        ThrowOcException(e.code(), e.reason().c_str());
+    }
+}
+
+/*
+ * Class:     org_iotivity_base_OcSecureResource
+ * Method:    getLinkedDevices
+ * Signature: ()Ljava/util/List;
+ */
+JNIEXPORT jobject JNICALL Java_org_iotivity_base_OcSecureResource_getLinkedDevices
+(JNIEnv *env, jobject thiz)
+{
+    LOGD("OcSecureResource_getLinkedDevices");
+    UuidList_t uuidList;
+
+    JniOcSecureResource *secureResource = JniOcSecureResource::getJniOcSecureResourcePtr(env, thiz);
+    if (!secureResource)
+    {
+        return nullptr;
+    }
+
+    try
+    {
+        OCStackResult result = secureResource->getLinkedDevices(env, uuidList);
+        if (OC_STACK_OK != result)
+        {
+            ThrowOcException(result, "OcSecureResource_getLinkedDevices");
+            return nullptr;
+        }
+        return JniSecureUtils::convertUUIDVectorToJavaStrList(env, uuidList);
+    }
+    catch (OCException& e)
+    {
+        LOGE("%s", e.reason().c_str());
+        ThrowOcException(e.code(), e.reason().c_str());
+    }
+}
+
+/*
+ * Class:     org_iotivity_base_OcSecureResource
+ * Method:    getIpAddr
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_org_iotivity_base_OcSecureResource_getIpAddr
+  (JNIEnv *env, jobject thiz)
+{
+    LOGD("OcSecureResource_getIpAddr");
+    JniOcSecureResource *secureResource = JniOcSecureResource::getJniOcSecureResourcePtr(env, thiz);
+    if (!secureResource)
+    {
+        return nullptr;
+    }
+
+    return env->NewStringUTF(secureResource->getIpAddr().c_str());
+}
+
+/*
+ * Class:     org_iotivity_base_OcSecureResource
+ * Method:    getDeviceID
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_org_iotivity_base_OcSecureResource_getDeviceID
+  (JNIEnv *env , jobject thiz)
+{
+    LOGD("OcSecureResource_getDeviceID");
+    JniOcSecureResource *secureResource = JniOcSecureResource::getJniOcSecureResourcePtr(env, thiz);
+    if (!secureResource)
+    {
+        return nullptr;
+    }
+
+    return env->NewStringUTF(secureResource->getDeviceID().c_str());
+}
+
+/*
+ * Class:     org_iotivity_base_OcSecureResource
+ * Method:    deviceStatus
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_org_iotivity_base_OcSecureResource_deviceStatus
+  (JNIEnv *env, jobject thiz)
+{
+    LOGD("OcSecureResource_deviceStatus");
+    JniOcSecureResource *secureResource = JniOcSecureResource::getJniOcSecureResourcePtr(env, thiz);
+    if (!secureResource)
+    {
+        return -1;
+    }
+
+    return secureResource->getDeviceStatus();
+}
+
+/*
+ * Class:     org_iotivity_base_OcSecureResource
+ * Method:    ownedStatus
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_org_iotivity_base_OcSecureResource_ownedStatus
+  (JNIEnv *env, jobject thiz)
+{
+    LOGD("OcSecureResource_ownedStatus");
+    JniOcSecureResource *secureResource = JniOcSecureResource::getJniOcSecureResourcePtr(env, thiz);
+    if (!secureResource)
+    {
+        return -1;
+    }
+
+    return secureResource->getOwnedStatus();
+}
+
+/*
+ * Class:     org_iotivity_base_OcSecureResource
+ * Method:    dispose
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcSecureResource_dispose
+  (JNIEnv *env, jobject thiz)
+{
+    LOGD("OcSecureResource_dispose");
+    JniOcSecureResource *secureResource = JniOcSecureResource::getJniOcSecureResourcePtr(env, thiz);
+    delete secureResource;
+}
diff --git a/android/android_api/base/jni/JniOcSecureResource.h b/android/android_api/base/jni/JniOcSecureResource.h
new file mode 100644 (file)
index 0000000..0b98f75
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+* //******************************************************************
+* //
+* // Copyright 2015 Samsung Electronics All Rights Reserved.
+* //
+* //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+* //
+* // Licensed 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.
+* //
+* //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+*/
+
+#include "JniOcStack.h"
+#include "JniProvisionResultListner.h"
+#include "OCProvisioningManager.h"
+#include <mutex>
+
+#ifndef _Included_org_iotivity_base_OcSecureResource
+#define _Included_org_iotivity_base_OcSecureResource
+
+using namespace OC;
+
+class JniOcSecureResource
+{
+    public:
+        JniOcSecureResource(std::shared_ptr<OCSecureResource> secureresource);
+        ~JniOcSecureResource();
+
+        static JniOcSecureResource* getJniOcSecureResourcePtr(JNIEnv *env, jobject thiz);
+        std::string getDeviceID(void);
+        std::string getIpAddr(void);
+        int getDeviceStatus(void);
+        bool getOwnedStatus(void);
+        OCSecureResource* getDevicePtr();
+
+        JniProvisionResultListner* AddProvisionResultListener(JNIEnv* env, jobject jListener);
+        void  RemoveProvisionResultListener(JNIEnv* env, jobject jListener);
+
+        OCStackResult doOwnershipTransfer(JNIEnv* env, jobject jListener);
+        OCStackResult getLinkedDevices(JNIEnv *env, UuidList_t &uuidList);
+        OCStackResult provisionACL(JNIEnv* env, jobject acl, jobject jListener);
+        OCStackResult provisionPairwiseDevices(JNIEnv* env, jint type, jint keySize,
+                jobject acl1, jobject device2, jobject acl2, jobject jListener);
+        OCStackResult provisionCredentials(JNIEnv* env, jint type, jint keySize,
+                jobject device2, jobject jListener);
+        OCStackResult unlinkDevices(JNIEnv* env, jobject device2, jobject jListener);
+        OCStackResult removeDevice(JNIEnv* env, jint timeout, jobject jListener);
+
+    private:
+
+        std::map<jobject, std::pair<JniProvisionResultListner*, int>> resultMap;
+        std::mutex resultMapLock;
+        std::shared_ptr<OCSecureResource> m_sharedSecureResource;
+};
+
+/* DO NOT EDIT THIS FILE BEYOND THIS LINE - it is machine generated */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class:     org_iotivity_base_OcSecureResource
+ * Method:    doOwnershipTransfer
+ * Signature: (Lorg/iotivity/base/OcSecureResource/DoOwnershipTransferListener;)V
+ */
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcSecureResource_doOwnershipTransfer
+  (JNIEnv *, jobject, jobject);
+
+/*
+ * Class:     org_iotivity_base_OcSecureResource
+ * Method:    removeDevice
+ * Signature: (ILorg/iotivity/base/OcSecureResource/RemoveDeviceListener;)V
+ */
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcSecureResource_removeDevice
+  (JNIEnv *, jobject, jint, jobject);
+
+/*
+ * Class:     org_iotivity_base_OcSecureResource
+ * Method:    unlinkDevices
+ * Signature: (Ljava/lang/Object;Lorg/iotivity/base/OcSecureResource/UnlinkDevicesListener;)V
+ */
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcSecureResource_unlinkDevices
+  (JNIEnv *, jobject, jobject, jobject);
+
+/*
+ * Class:     org_iotivity_base_OcSecureResource
+ * Method:    provisionCredentials1
+ * Signature: (IILjava/lang/Object;Lorg/iotivity/base/OcSecureResource/ProvisionCredentialsListener;)V
+ */
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcSecureResource_provisionCredentials1
+  (JNIEnv *, jobject, jint, jint, jobject, jobject);
+
+/*
+ * Class:     org_iotivity_base_OcSecureResource
+ * Method:    provisionACL
+ * Signature: (Ljava/lang/Object;Lorg/iotivity/base/OcSecureResource/ProvisionAclListener;)V
+ */
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcSecureResource_provisionACL
+  (JNIEnv *, jobject, jobject, jobject);
+
+/*
+ * Class:     org_iotivity_base_OcSecureResource
+ * Method:    provisionPairwiseDevices1
+ * Signature: (IILjava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Lorg/iotivity/base/OcSecureResource/ProvisionPairwiseDevicesListener;)V
+ */
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcSecureResource_provisionPairwiseDevices1
+  (JNIEnv *, jobject, jint, jint, jobject, jobject, jobject, jobject);
+
+/*
+ * Class:     org_iotivity_base_OcSecureResource
+ * Method:    getLinkedDevices
+ * Signature: ()Ljava/util/List;
+ */
+JNIEXPORT jobject JNICALL Java_org_iotivity_base_OcSecureResource_getLinkedDevices
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_iotivity_base_OcSecureResource
+ * Method:    getIpAddr
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_org_iotivity_base_OcSecureResource_getIpAddr
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_iotivity_base_OcSecureResource
+ * Method:    getDeviceID
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_org_iotivity_base_OcSecureResource_getDeviceID
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_iotivity_base_OcSecureResource
+ * Method:    deviceStatus
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_org_iotivity_base_OcSecureResource_deviceStatus
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_iotivity_base_OcSecureResource
+ * Method:    ownedStatus
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_org_iotivity_base_OcSecureResource_ownedStatus
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_iotivity_base_OcSecureResource
+ * Method:    dispose
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcSecureResource_dispose
+  (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
index 61086b5..affc4dd 100644 (file)
@@ -59,6 +59,9 @@ jclass g_cls_OcPresenceStatus = nullptr;
 jclass g_cls_OcHeaderOption = nullptr;
 jclass g_cls_ObservationInfo = nullptr;
 jclass g_cls_OcResourceIdentifier = nullptr;
+jclass g_cls_OcProvisionResult = nullptr;
+jclass g_cls_OcSecureResource = nullptr;
+jclass g_cls_OcOicSecAcl = nullptr;
 
 jmethodID g_mid_Integer_ctor = nullptr;
 jmethodID g_mid_Double_ctor = nullptr;
@@ -89,6 +92,18 @@ jmethodID g_mid_OcHeaderOption_get_data = nullptr;
 jmethodID g_mid_ObservationInfo_N_ctor = nullptr;
 jmethodID g_mid_OcPresenceStatus_get = nullptr;
 jmethodID g_mid_OcResourceIdentifier_N_ctor = nullptr;
+jmethodID g_mid_OcProvisionResult_ctor = nullptr;
+jmethodID g_mid_OcSecureResource_ctor = nullptr;
+
+jmethodID g_mid_OcOicSecAcl_get_subject = nullptr;
+jmethodID g_mid_OcOicSecAcl_get_resources_cnt = nullptr;
+jmethodID g_mid_OcOicSecAcl_get_resources = nullptr;
+jmethodID g_mid_OcOicSecAcl_get_permission = nullptr;
+jmethodID g_mid_OcOicSecAcl_get_periods_cnt = nullptr;
+jmethodID g_mid_OcOicSecAcl_get_periods = nullptr;
+jmethodID g_mid_OcOicSecAcl_get_recurrences = nullptr;
+jmethodID g_mid_OcOicSecAcl_get_owners_cnt = nullptr;
+jmethodID g_mid_OcOicSecAcl_get_owners = nullptr;
 
 jobject getOcException(JNIEnv* env, const char* file, const char* functionName,
     const int line, const int code, const char* message)
@@ -400,6 +415,55 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved)
     g_mid_OcResourceIdentifier_N_ctor = env->GetMethodID(g_cls_OcResourceIdentifier, "<init>", "(J)V");
     if (!g_mid_OcResourceIdentifier_N_ctor) return JNI_ERR;
 
+    //OcSecureResource
+    clazz = env->FindClass("org/iotivity/base/OcSecureResource");
+    if (!clazz) return JNI_ERR;
+    g_cls_OcSecureResource =  (jclass)env->NewGlobalRef(clazz);
+    env->DeleteLocalRef(clazz);
+    g_mid_OcSecureResource_ctor = env->GetMethodID(g_cls_OcSecureResource, "<init>", "(J)V");
+    if (!g_mid_OcSecureResource_ctor) return JNI_ERR;
+
+    //ProvisionResult
+    clazz = env->FindClass("org/iotivity/base/ProvisionResult");
+    if (!clazz) return JNI_ERR;
+    g_cls_OcProvisionResult =  (jclass)env->NewGlobalRef(clazz);
+    env->DeleteLocalRef(clazz);
+    g_mid_OcProvisionResult_ctor = env->GetMethodID(g_cls_OcProvisionResult, "<init>", "(Ljava/lang/String;I)V");
+    if (!g_mid_OcProvisionResult_ctor) return JNI_ERR;
+
+    //OicSecAcl
+    clazz = env->FindClass("org/iotivity/base/OicSecAcl");
+    if (!clazz) return JNI_ERR;
+    g_cls_OcOicSecAcl =  (jclass)env->NewGlobalRef(clazz);
+    env->DeleteLocalRef(clazz);
+
+    g_mid_OcOicSecAcl_get_subject = env->GetMethodID(g_cls_OcOicSecAcl, "getSubject", "()Ljava/lang/String;");
+    if (!g_mid_OcOicSecAcl_get_subject) return JNI_ERR;
+
+    g_mid_OcOicSecAcl_get_resources_cnt = env->GetMethodID(g_cls_OcOicSecAcl, "getResourcesCount", "()I");
+    if (!g_mid_OcOicSecAcl_get_resources_cnt) return JNI_ERR;
+
+    g_mid_OcOicSecAcl_get_resources = env->GetMethodID(g_cls_OcOicSecAcl, "getResources", "(I)Ljava/lang/String;");
+    if (!g_mid_OcOicSecAcl_get_resources) return JNI_ERR;
+
+    g_mid_OcOicSecAcl_get_permission = env->GetMethodID(g_cls_OcOicSecAcl, "getPermission", "()I");
+    if (!g_mid_OcOicSecAcl_get_permission) return JNI_ERR;
+
+    g_mid_OcOicSecAcl_get_periods_cnt = env->GetMethodID(g_cls_OcOicSecAcl, "getPeriodsCount", "()I");
+    if (!g_mid_OcOicSecAcl_get_periods_cnt) return JNI_ERR;
+
+    g_mid_OcOicSecAcl_get_periods = env->GetMethodID(g_cls_OcOicSecAcl, "getPeriods", "(I)Ljava/lang/String;");
+    if (!g_mid_OcOicSecAcl_get_periods) return JNI_ERR;
+
+    g_mid_OcOicSecAcl_get_recurrences = env->GetMethodID(g_cls_OcOicSecAcl, "getRecurrences", "(I)Ljava/lang/String;");
+    if (!g_mid_OcOicSecAcl_get_recurrences) return JNI_ERR;
+
+    g_mid_OcOicSecAcl_get_owners_cnt = env->GetMethodID(g_cls_OcOicSecAcl, "getOwnersCount", "()I");
+    if (!g_mid_OcOicSecAcl_get_owners_cnt) return JNI_ERR;
+
+    g_mid_OcOicSecAcl_get_owners = env->GetMethodID(g_cls_OcOicSecAcl, "getOwners", "(I)Ljava/lang/String;");
+    if (!g_mid_OcOicSecAcl_get_owners) return JNI_ERR;
+
     return JNI_CURRENT_VERSION;
 }
 
@@ -446,4 +510,7 @@ JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved)
     env->DeleteGlobalRef(g_cls_OcHeaderOption);
     env->DeleteGlobalRef(g_cls_ObservationInfo);
     env->DeleteGlobalRef(g_cls_OcResourceIdentifier);
+    env->DeleteGlobalRef(g_cls_OcSecureResource);
+    env->DeleteGlobalRef(g_cls_OcProvisionResult);
+    env->DeleteGlobalRef(g_cls_OcOicSecAcl);
 }
\ No newline at end of file
index 2731017..79ede36 100644 (file)
@@ -79,6 +79,9 @@ extern jclass g_cls_OcPresenceStatus;
 extern jclass g_cls_OcHeaderOption;
 extern jclass g_cls_ObservationInfo;
 extern jclass g_cls_OcResourceIdentifier;
+extern jclass g_cls_OcProvisionResult;
+extern jclass g_cls_OcSecureResource;
+extern jclass g_cls_OcOicSecAcl;
 
 extern jmethodID g_mid_Integer_ctor;
 extern jmethodID g_mid_Double_ctor;
@@ -109,6 +112,17 @@ extern jmethodID g_mid_OcHeaderOption_get_data;
 extern jmethodID g_mid_ObservationInfo_N_ctor;
 extern jmethodID g_mid_OcPresenceStatus_get;
 extern jmethodID g_mid_OcResourceIdentifier_N_ctor;
+extern jmethodID g_mid_OcProvisionResult_ctor;
+extern jmethodID g_mid_OcSecureResource_ctor;
+extern jmethodID g_mid_OcOicSecAcl_get_subject;
+extern jmethodID g_mid_OcOicSecAcl_get_resources_cnt;
+extern jmethodID g_mid_OcOicSecAcl_get_resources;
+extern jmethodID g_mid_OcOicSecAcl_get_permission;
+extern jmethodID g_mid_OcOicSecAcl_get_periods_cnt;
+extern jmethodID g_mid_OcOicSecAcl_get_periods;
+extern jmethodID g_mid_OcOicSecAcl_get_recurrences;
+extern jmethodID g_mid_OcOicSecAcl_get_owners_cnt;
+extern jmethodID g_mid_OcOicSecAcl_get_owners;
 
 typedef void(*RemoveListenerCallback)(JNIEnv* env, jobject jListener);
 
diff --git a/android/android_api/base/jni/JniPinCheckListener.cpp b/android/android_api/base/jni/JniPinCheckListener.cpp
new file mode 100644 (file)
index 0000000..9a5e35a
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+* //******************************************************************
+* //
+* // Copyright 2015 Samsung Electronics All Rights Reserved.
+* //
+* //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+* //
+* // Licensed 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.
+* //
+* //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+*/
+#include "JniPinCheckListener.h"
+#include "oic_string.h"
+
+JniPinCheckListener::JniPinCheckListener(JNIEnv *env, jobject jListener)
+{
+    m_jListener = env->NewGlobalRef(jListener);
+}
+
+JniPinCheckListener::~JniPinCheckListener()
+{
+    LOGI("~JniPinCheckListener()");
+    if (m_jListener)
+    {
+        jint ret;
+        JNIEnv *env = GetJNIEnv(ret);
+        if (NULL == env) return;
+        env->DeleteWeakGlobalRef(m_jListener);
+        if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+    }
+}
+
+void JniPinCheckListener::PinCallback(char *pinBuf, size_t bufSize)
+{
+    jint ret;
+
+    JNIEnv *env = GetJNIEnv(ret);
+    if (NULL == env) return;
+
+    jclass clsL = env->GetObjectClass(m_jListener);
+
+    if (!clsL)
+    {
+        if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+        return;
+    }
+
+    jmethodID midL = env->GetMethodID(clsL, "pinCallbackListener", "()Ljava/lang/String;");
+    if (!midL)
+    {
+        if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+        return;
+    }
+    jstring jpin = (jstring)env->CallObjectMethod(m_jListener, midL);
+    if (env->ExceptionCheck())
+    {
+        LOGE("Java exception is thrown");
+        if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+        return;
+    }
+
+    char *str = (char*)env->GetStringUTFChars(jpin, NULL);
+    OICStrcpy(pinBuf, bufSize, str);
+    env->ReleaseStringUTFChars(jpin, str);
+
+    if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+}
diff --git a/android/android_api/base/jni/JniPinCheckListener.h b/android/android_api/base/jni/JniPinCheckListener.h
new file mode 100644 (file)
index 0000000..74d150d
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+* //******************************************************************
+* //
+* // Copyright 2015 Samsung Electronics All Rights Reserved.
+* //
+* //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+* //
+* // Licensed 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.
+* //
+* //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+*/
+
+#include "JniOcStack.h"
+#include "OCProvisioningManager.h"
+
+#ifndef _Included_org_iotivity_base_PinCheckListener
+#define _Included_org_iotivity_base_PinCheckListener
+
+typedef std::function<void(JNIEnv* env, jobject jListener)> RemoveCallback;
+class JniPinCheckListener
+{
+    public:
+        JniPinCheckListener(JNIEnv *, jobject);
+        ~JniPinCheckListener();
+
+        void PinCallback(char*, size_t);
+    private:
+        jobject m_jListener;
+};
+#endif
diff --git a/android/android_api/base/jni/JniProvisionResultListner.cpp b/android/android_api/base/jni/JniProvisionResultListner.cpp
new file mode 100644 (file)
index 0000000..6b9fd04
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+* //******************************************************************
+* //
+* // Copyright 2015 Samsung Electronics All Rights Reserved.
+* //
+* //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+* //
+* // Licensed 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.
+* //
+* //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+*/
+#include "JniProvisionResultListner.h"
+#include "JniOcSecureResource.h"
+#include "JniSecureUtils.h"
+
+JniProvisionResultListner::JniProvisionResultListner(JNIEnv *env, jobject jListener,
+    RemoveCallback removeProvisionResultListener)
+{
+    m_jwListener = env->NewWeakGlobalRef(jListener);
+    m_removeProvisionResultListener = removeProvisionResultListener;
+}
+
+JniProvisionResultListner::~JniProvisionResultListner()
+{
+    LOGI("~JniProvisionResultListner()");
+    if (m_jwListener)
+    {
+        jint ret;
+        JNIEnv *env = GetJNIEnv(ret);
+        if (NULL == env) return;
+        env->DeleteWeakGlobalRef(m_jwListener);
+        if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+    }
+}
+
+void JniProvisionResultListner::ProvisionResultCallback(PMResultList_t *result, int hasError,
+      ListenerFunc func)
+{
+    jint ret;
+    JNIEnv *env = GetJNIEnv(ret);
+    if (NULL == env) return;
+
+    jobject jListener = env->NewLocalRef(m_jwListener);
+    if (!jListener)
+    {
+        checkExAndRemoveListener(env);
+        if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+        return;
+    }
+
+    jclass clsL = env->GetObjectClass(jListener);
+
+    if (!clsL)
+    {
+        checkExAndRemoveListener(env);
+        if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+        return;
+    }
+
+
+    jobject jResultList = JniSecureUtils::convertProvisionresultVectorToJavaList(env, result);
+    if (!jResultList)
+    {
+        checkExAndRemoveListener(env);
+        if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+        return;
+    }
+
+    std::string calledFunc;
+    switch (func)
+    {
+        case ListenerFunc::OWNERSHIPTRANSFER:
+        {
+            calledFunc = "doOwnershipTransferListener";
+        }
+        break;
+        case ListenerFunc::PROVISIONACL:
+        {
+            calledFunc = "provisionAclListener";
+        }
+        break;
+        case ListenerFunc::PROVISIONCREDENTIALS:
+        {
+            calledFunc = "provisionCredentialsListener";
+        }
+        break;
+        case ListenerFunc::UNLINKDEVICES:
+        {
+            calledFunc = "unlinkDevicesListener";
+        }
+        break;
+        case ListenerFunc::REMOVEDEVICE:
+        {
+            calledFunc = "removeDeviceListener";
+        }
+        break;
+        case ListenerFunc::PROVISIONPAIRWISEDEVICES:
+        {
+            calledFunc = "provisionPairwiseDevicesListener";
+        }
+        break;
+        default:
+        {
+            checkExAndRemoveListener(env);
+            if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+        }
+        return;
+    }
+
+    jmethodID midL = env->GetMethodID(clsL, calledFunc.c_str(), "(Ljava/util/List;I)V");
+    if (!midL)
+    {
+        checkExAndRemoveListener(env);
+        if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+        return;
+    }
+    env->CallVoidMethod(jListener, midL, jResultList, (jint)hasError);
+    if (env->ExceptionCheck())
+    {
+        LOGE("Java exception is thrown");
+    }
+
+    checkExAndRemoveListener(env);
+    if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+}
+
+void JniProvisionResultListner::checkExAndRemoveListener(JNIEnv* env)
+{
+    if (env->ExceptionCheck())
+    {
+        jthrowable ex = env->ExceptionOccurred();
+        env->ExceptionClear();
+        m_removeProvisionResultListener(env, m_jwListener);
+        env->Throw((jthrowable)ex);
+    }
+    else
+    {
+        m_removeProvisionResultListener(env, m_jwListener);
+    }
+}
diff --git a/android/android_api/base/jni/JniProvisionResultListner.h b/android/android_api/base/jni/JniProvisionResultListner.h
new file mode 100644 (file)
index 0000000..6df56d7
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+* //******************************************************************
+* //
+* // Copyright 2015 Samsung Electronics All Rights Reserved.
+* //
+* //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+* //
+* // Licensed 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.
+* //
+* //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+*/
+#include <jni.h>
+#include "JniOcStack.h"
+#include "OCProvisioningManager.h"
+
+#ifndef _Included_org_iotivity_base_OcProvisioning_JniProvisionResultListner
+#define _Included_org_iotivity_base_OcProvisioning_JniProvisionResultListner
+
+typedef std::function<void(JNIEnv* env, jobject jListener)> RemoveCallback;
+
+enum class ListenerFunc
+{
+    OWNERSHIPTRANSFER = 1,
+    PROVISIONACL,
+    PROVISIONCREDENTIALS,
+    UNLINKDEVICES,
+    REMOVEDEVICE,
+    PROVISIONPAIRWISEDEVICES
+};
+
+class JniProvisionResultListner
+{
+    public:
+        JniProvisionResultListner(JNIEnv *env, jobject jListener,
+                RemoveCallback removeProvisionResultListener);
+        ~JniProvisionResultListner();
+
+        void ProvisionResultCallback(OC::PMResultList_t *result, int hasError, ListenerFunc func);
+
+    private:
+        RemoveCallback m_removeProvisionResultListener;
+        jweak m_jwListener;
+        void checkExAndRemoveListener(JNIEnv* env);
+};
+#endif
diff --git a/android/android_api/base/jni/JniSecureUtils.cpp b/android/android_api/base/jni/JniSecureUtils.cpp
new file mode 100644 (file)
index 0000000..2fb507f
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+* //******************************************************************
+* //
+* // Copyright 2015 Samsung Electronics All Rights Reserved.
+* //
+* //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+* //
+* // Licensed 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.
+* //
+* //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+*/
+
+#include "JniSecureUtils.h"
+#include "JniOcSecureResource.h"
+#include "base64.h"
+
+jobject JniSecureUtils::convertProvisionresultVectorToJavaList(JNIEnv *env, const OC::PMResultList_t *result)
+{
+    jobject jResultList = env->NewObject(g_cls_LinkedList, g_mid_LinkedList_ctor);
+    if (!jResultList)
+    {
+        return nullptr;
+    }
+
+    for (size_t i = 0; i < result->size(); ++i)
+    {
+        jobject jresult = env->NewObject(
+                g_cls_OcProvisionResult,
+                g_mid_OcProvisionResult_ctor,
+                env->NewStringUTF((char*)result->at(i).deviceId.id),
+                static_cast<jint>(result->at(i).res)
+                );
+        if (!jresult)
+        {
+            return nullptr;
+        }
+
+        env->CallBooleanMethod(jResultList, g_mid_LinkedList_add_object, jresult);
+        if (env->ExceptionCheck())
+        {
+            return nullptr;
+        }
+        env->DeleteLocalRef(jresult);
+    }
+    return jResultList;
+}
+
+jobjectArray JniSecureUtils::convertDeviceVectorToJavaArray(JNIEnv *env,
+    std::vector<std::shared_ptr<OC::OCSecureResource>> &deviceListVector)
+{
+    jsize len = static_cast<jsize>(deviceListVector.size());
+    jobjectArray devArr = env->NewObjectArray(len, g_cls_OcSecureResource, NULL);
+
+    if (!devArr)
+    {
+        return nullptr;
+    }
+
+    for (jsize i = 0; i < len; ++i)
+    {
+        JniOcSecureResource *device = new JniOcSecureResource(deviceListVector[i]);
+        jobject jDevice = env->NewObject(g_cls_OcSecureResource, g_mid_OcSecureResource_ctor);
+
+        SetHandle<JniOcSecureResource>(env, jDevice, device);
+        if (!jDevice)
+        {
+            return nullptr;
+        }
+
+        env->SetObjectArrayElement(devArr, i, jDevice);
+        if (env->ExceptionCheck())
+        {
+            return nullptr;
+        }
+        env->DeleteLocalRef(jDevice);
+    }
+    return devArr;
+}
+
+std::string JniSecureUtils::convertUUIDtoStr(OicUuid_t uuid)
+{
+    std::ostringstream deviceId("");
+    char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {0,};
+    uint32_t outLen = 0;
+    B64Result b64Ret = B64_OK;
+
+    b64Ret = b64Encode(uuid.id, sizeof(uuid.id), base64Buff,
+            sizeof(base64Buff), &outLen);
+
+    deviceId << base64Buff;
+    return deviceId.str();
+}
+
+void JniSecureUtils::convertStrToUUID(char *str, OicUuid_t &uuid)
+{
+    unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
+    uint32_t outLen = 0;
+    B64Result b64Ret = B64_OK;
+
+    b64Ret = b64Decode(str, strlen(str), base64Buff, sizeof(base64Buff), &outLen);
+    memcpy(uuid.id, base64Buff, outLen);
+}
+
+jobject JniSecureUtils::convertUUIDVectorToJavaStrList(JNIEnv *env, UuidList_t &vector)
+{
+    jobject jList = env->NewObject(g_cls_LinkedList, g_mid_LinkedList_ctor);
+    if (!jList)
+    {
+        return nullptr;
+    }
+    for (size_t i = 0; i < vector.size(); ++i)
+    {
+        jstring jStr = env->NewStringUTF((convertUUIDtoStr(vector[i])).c_str());
+        if (!jStr)
+        {
+            return nullptr;
+        }
+        env->CallBooleanMethod(jList, g_mid_LinkedList_add_object, jStr);
+        if (env->ExceptionCheck())
+        {
+            return nullptr;
+        }
+        env->DeleteLocalRef(jStr);
+    }
+    return jList;
+}
+
+OCStackResult JniSecureUtils::convertJavaACLToOCAcl(JNIEnv *env, jobject in, OicSecAcl_t *acl)
+{
+    jstring jData;
+    jvalue args[1];
+
+    jData = (jstring) env->CallObjectMethod(in, g_mid_OcOicSecAcl_get_subject);
+    if (!jData || env->ExceptionCheck())
+    {
+        return OC_STACK_ERROR;
+    }
+
+    char *str = (char*) env->GetStringUTFChars(jData, 0);
+    convertStrToUUID(str, acl->subject);
+    env->ReleaseStringUTFChars(jData, str);
+
+    jint jCount = (jint) env->CallIntMethod(in, g_mid_OcOicSecAcl_get_resources_cnt);
+    if (!jCount || env->ExceptionCheck())
+    {
+        return OC_STACK_ERROR;
+    }
+
+    acl->resourcesLen = jCount;
+    acl->resources = new char*[jCount];
+    for (jint i = 0; i < jCount; ++i)
+    {
+        args[0].i = i;
+        jData = (jstring) env->CallObjectMethodA(in, g_mid_OcOicSecAcl_get_resources, args);
+        if (!jData || env->ExceptionCheck())
+        {
+            return OC_STACK_ERROR;
+        }
+
+        acl->resources[i] = (char*) env->GetStringUTFChars(jData, 0);
+    }
+
+    jCount = (jint) env->CallIntMethod(in, g_mid_OcOicSecAcl_get_permission);
+    if (env->ExceptionCheck())
+    {
+        return OC_STACK_ERROR;
+    }
+
+    acl->permission = jCount;
+    jCount = (jint) env->CallIntMethod(in, g_mid_OcOicSecAcl_get_periods_cnt);
+    if (env->ExceptionCheck())
+    {
+        return OC_STACK_ERROR;
+    }
+
+    acl->prdRecrLen = jCount;
+    acl->periods = new char*[jCount];
+    for (jint i = 0; i < jCount; ++i)
+    {
+        args[0].i = i;
+        jData = (jstring) env->CallObjectMethodA(in, g_mid_OcOicSecAcl_get_periods, args);
+        if (!jData || env->ExceptionCheck())
+        {
+            return OC_STACK_ERROR;
+        }
+
+        acl->periods[i] = (char*) env->GetStringUTFChars(jData, 0);
+    }
+
+    acl->recurrences = new char*[jCount]; //TODO:Period Len and Reccurence len is same
+    for (jint i = 0; i < jCount; ++i)
+    {
+        args[0].i = i;
+        jData = (jstring) env->CallObjectMethodA(in, g_mid_OcOicSecAcl_get_recurrences, args);
+        if (!jData ||  env->ExceptionCheck())
+        {
+            return OC_STACK_ERROR;
+        }
+
+        acl->recurrences[i] = (char*) env->GetStringUTFChars(jData, 0);
+    }
+
+    jCount = (jint) env->CallIntMethod(in, g_mid_OcOicSecAcl_get_owners_cnt);
+    if (!jCount ||  env->ExceptionCheck())
+    {
+        return OC_STACK_ERROR;
+    }
+
+    acl->ownersLen = jCount;
+    acl->owners = new OicUuid_t[acl->ownersLen];
+    if (!acl->owners)
+    {
+        return OC_STACK_ERROR;
+    }
+
+    for (jint i = 0; i < jCount; ++i)
+    {
+        args[0].i = i;
+        jData = (jstring) env->CallObjectMethodA(in, g_mid_OcOicSecAcl_get_owners, args);
+        if (!jData ||  env->ExceptionCheck())
+        {
+            return OC_STACK_ERROR;
+        }
+
+        str = (char*) env->GetStringUTFChars(jData, 0);
+        convertStrToUUID(str, acl->owners[i]);
+        env->ReleaseStringUTFChars(jData, str);
+    }
+    return OC_STACK_OK;
+}
diff --git a/android/android_api/base/jni/JniSecureUtils.h b/android/android_api/base/jni/JniSecureUtils.h
new file mode 100644 (file)
index 0000000..c239c44
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+* //******************************************************************
+* //
+* // Copyright 2015 Samsung Electronics All Rights Reserved.
+* //
+* //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+* //
+* // Licensed 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.
+* //
+* //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+*/
+
+#include "JniOcStack.h"
+#include "OCProvisioningManager.h"
+
+class JniSecureUtils
+{
+    private:
+        static std::string convertUUIDtoStr(OicUuid_t uuid);
+        static void convertStrToUUID(char *str, OicUuid_t &uuid);
+    public:
+        static jobject convertProvisionresultVectorToJavaList(JNIEnv *,
+                const OC::PMResultList_t *);
+        static jobjectArray convertDeviceVectorToJavaArray(JNIEnv *env,
+                std::vector<std::shared_ptr<OC::OCSecureResource>>& deviceListVector);
+        static jobject convertUUIDVectorToJavaStrList(JNIEnv *env, OC::UuidList_t &vector);
+        static OCStackResult convertJavaACLToOCAcl(JNIEnv *env, jobject in, OicSecAcl_t *out);
+};
diff --git a/android/android_api/base/src/main/java/org/iotivity/base/CredType.java b/android/android_api/base/src/main/java/org/iotivity/base/CredType.java
new file mode 100644 (file)
index 0000000..bbaeda7
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2015  Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed 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.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+
+package org.iotivity.base;
+
+import java.security.InvalidParameterException;
+import java.util.EnumSet;
+
+public enum CredType {
+
+    NO_SECURITY_MODE                (0),
+
+    SYMMETRIC_PAIR_WISE_KEY         (1 << 0),
+
+    SYMMETRIC_GROUP_KEY             (1 << 1),
+
+    ASYMMETRIC_KEY                  (1 << 2),
+
+    SIGNED_ASYMMETRIC_KEY           (1 << 3),
+
+    PIN_PASSWORD                    (1 << 4),
+
+    ASYMMETRIC_ENCRYPTION_KEY       (1 << 5),
+
+    ;
+    private int value;
+
+    private CredType(int value) {
+        this.value = value;
+    }
+
+    public int getValue() {
+        return this.value;
+    }
+
+    public static EnumSet<CredType> convertToEnumSet(int value) {
+        EnumSet<CredType> typeSet = null;
+
+        for (CredType v : values()) {
+            if (0 != (value & v.getValue())) {
+                if (null == typeSet) {
+                    typeSet = EnumSet.of(v);
+                } else {
+                    typeSet.add(v);
+                }
+            }
+        }
+
+        if (null == typeSet || typeSet.isEmpty()) {
+            throw new InvalidParameterException("Unexpected CredType value:" + value);
+        }
+
+        return typeSet;
+    }
+}
diff --git a/android/android_api/base/src/main/java/org/iotivity/base/DeviceStatus.java b/android/android_api/base/src/main/java/org/iotivity/base/DeviceStatus.java
new file mode 100644 (file)
index 0000000..4bc2e6f
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2015 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed 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.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+
+package org.iotivity.base;
+
+public enum DeviceStatus {
+    ON(0),
+    OFF(1),
+    INVALID(-1);
+
+    private int value;
+
+    private DeviceStatus(int value) {
+        this.value = value;
+    }
+
+    public int getValue() {
+        return this.value;
+    }
+
+    public static DeviceStatus convertDeviceStatus(int value) {
+
+        if (0 == value)
+        {
+            return DeviceStatus.ON;
+        }
+        else if (1 == value)
+        {
+            return DeviceStatus.OFF;
+        }
+        else
+        {
+            return DeviceStatus.INVALID;
+        }
+    }
+}
diff --git a/android/android_api/base/src/main/java/org/iotivity/base/KeySize.java b/android/android_api/base/src/main/java/org/iotivity/base/KeySize.java
new file mode 100644 (file)
index 0000000..6243db6
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2015 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed 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.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+
+package org.iotivity.base;
+
+public enum KeySize {
+    OWNER_PSK_LENGTH_128 (128/8),
+    OWNER_PSK_LENGTH_256 (256/8),;
+
+    private int value;
+
+    private KeySize(int value) {
+        this.value = value;
+    }
+
+    public int getValue() {
+        return this.value;
+    }
+}
diff --git a/android/android_api/base/src/main/java/org/iotivity/base/OcProvisioning.java b/android/android_api/base/src/main/java/org/iotivity/base/OcProvisioning.java
new file mode 100644 (file)
index 0000000..636e590
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2015 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed 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.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+
+package org.iotivity.base;
+
+import java.util.List;
+import java.util.Arrays;
+import java.util.Map;
+
+/**
+ * OcProvisionig represents functions corresponding to the provisioing of
+ * resources.
+ */
+public class OcProvisioning {
+
+    /**
+     * Method to Intialize Provisioning Manager.This will load the provisioning
+     * Manager's persistent database.
+     *
+     * @param dbPath     dbPath file path of the sqlite3 db.
+     * @throws OcException
+     */
+    public static native void provisionInit(String dbPath) throws OcException;
+
+    /**
+     * Method to Discover un-owned devices in its subnet.Un-owned devices need
+     * to be owned by calling ownershipTransferCBdata.
+     *
+     * @param timeout     Timeout in sec.Time to listen for responses before
+     *                    returining the Array.
+     * @return            Array of OcSecureResource class objects.
+     * @throws OcException
+     */
+    public  static List<OcSecureResource> discoverUnownedDevices(int timeout) throws OcException {
+        return Arrays.asList(OcProvisioning.discoverUnownedDevices1(timeout));
+    }
+    private static native OcSecureResource[] discoverUnownedDevices1(int timeout) throws OcException;
+
+    /**
+     * Method to Discover owned devices in its subnet.
+     *
+     * @param timeout     Timeout in sec.Time to listen for responses before
+     *                    returining the Array.
+     * @return            Array of OcSecureResource class objects.
+     * @throws OcException
+     */
+    public static List<OcSecureResource> discoverOwnedDevices(int timeout) throws OcException {
+        return Arrays.asList(OcProvisioning.discoverOwnedDevices1(timeout));
+    }
+    private static native OcSecureResource[] discoverOwnedDevices1(int timeout) throws OcException;
+
+    /**
+     *  API for registering Ownership transfer methods for a particular
+     *  transfer Type
+     *
+     * @param type     OxmType ownership transfer type.
+     * @throws OcException
+     */
+    public static void SetownershipTransferCBdata(OxmType type,
+            PinCallbackListener pinCallbackListener) throws OcException
+    {
+        OcProvisioning.ownershipTransferCBdata(type.getValue(), pinCallbackListener);
+    }
+
+    private  static native void ownershipTransferCBdata(int oxmType,  PinCallbackListener pinCallbackListener);
+
+    public static interface PinCallbackListener {
+        public String pinCallbackListener();
+    }
+
+    /**
+     * Method to get Array of owned and un-owned devices in the current subnet.
+     *
+     * @param timeout    timeout in sec for the API to return.
+     * @retrun           Array of OcSecureResource class objects.
+     *                   be provisioned.
+     * @throws OcException
+     */
+    public static List<OcSecureResource> getDeviceStatusList(int timeout) throws OcException {
+        return Arrays.asList(OcProvisioning.getDeviceStatusList1(timeout));
+    }
+    private static native OcSecureResource[] getDeviceStatusList1(int timeout) throws OcException;
+}
diff --git a/android/android_api/base/src/main/java/org/iotivity/base/OcSecureResource.java b/android/android_api/base/src/main/java/org/iotivity/base/OcSecureResource.java
new file mode 100644 (file)
index 0000000..218b9e2
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2015 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed 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.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+
+package org.iotivity.base;
+
+import java.util.List;
+import java.util.EnumSet;
+import java.util.Map;
+
+public class OcSecureResource {
+
+    private OcSecureResource(long nativeHandle) {
+        this.mNativeHandle = nativeHandle;
+    }
+
+    /**
+     *  Method to Start Ownership Transfer of an un-owned device.
+     *
+     *  @param DoOwnershipTransferListener  Callback function, which will be called after
+     *                                      completion of ownership Transfer.
+     *  @throws OcException
+     */
+    public native void doOwnershipTransfer(DoOwnershipTransferListener doOwnershipTransferListener)
+        throws OcException;
+
+    /**
+     *  Method removes device credential from all devices in subnet
+     *
+     *  @param timeout
+     *  @param RemoveDeviceListener         Callback function, which will be called after
+     *                                      completion of removing device.
+     *  @throws OcException
+     */
+    public native void removeDevice(int timeout,  RemoveDeviceListener removeDeviceListener)
+        throws OcException;
+
+    /**
+     *  Method removes the credential & relationship between the two devices.
+     *
+     *  @param jobject                      Second device
+     *  @param UnlinkDevicesListener        Callback function, which will be called after
+     *                                      completion of removing device.
+     *  @throws OcException
+     */
+    public native void unlinkDevices(Object device2, UnlinkDevicesListener unlinkDevicesListener)
+        throws OcException;
+
+    /**
+     *  Method removes the credential & relationship between the two devices.
+     *
+     *  @param EnumSet<CredType>            OR'ed Cred Types
+     *  @param KeySize                          keySize
+     *  @param Object                       Second device
+     *  @param ProvisionCredentialsListener Callback function, which will be called after
+     *                                      completion of removing device.
+     *  @throws OcException
+     */
+    public void provisionCredentials(EnumSet<CredType> credTypeSet, KeySize keysize, Object device2,
+            ProvisionCredentialsListener provisionCredentialsListener) throws OcException {
+        int credTypeInt = 0;
+
+        for (CredType credType : CredType.values()) {
+            if (credTypeSet.contains(credType))
+                credTypeInt |= credType.getValue();
+        }
+        this.provisionCredentials1(credTypeInt, keysize.getValue(),
+                device2, provisionCredentialsListener);
+    }
+    private native void provisionCredentials1(int type, int keySize, Object device2,
+            ProvisionCredentialsListener provisionCredentialsListener)
+        throws OcException;
+
+    /**
+     *  Method send ACL information to resource.
+     *
+     *  @param jobject                      Acl
+     *  @param ProvisionAclListener         Callback function, which will be called after
+     *                                      completion of removing device.
+     *  @throws OcException
+     */
+    public native void provisionACL(Object acl, ProvisionAclListener provisionACLListener)
+        throws OcException;
+
+
+    /**
+     *  Method provisions credentials between two devices and ACLs for the devices who
+     *  act as a server.
+     *
+     *  @param EnumSet<CredType>            OR'ed Cred Types
+     *  @param KeySize                      keySize
+     *  @param Object                       First acl
+     *  @param Object                       Second device
+     *  @param Object                       Second acl
+     *  @param ProvisionPairwiseDevicesListener Callback function, which will be called after
+     *                                      completion of removing device.
+     *  @throws OcException
+     */
+    public void provisionPairwiseDevices(EnumSet<CredType> credTypeSet, KeySize keysize, Object acl1,
+            Object device2, Object acl2,
+            ProvisionPairwiseDevicesListener provisionPairwiseDevicesListener) throws OcException {
+        int credTypeInt = 0;
+
+        for (CredType credType : CredType.values()) {
+            if (credTypeSet.contains(credType))
+                credTypeInt |= credType.getValue();
+        }
+        this.provisionPairwiseDevices1(credTypeInt, keysize.getValue(), acl1, device2,
+                acl2, provisionPairwiseDevicesListener);
+    }
+    private native void provisionPairwiseDevices1(int type, int keySize, Object acl1,
+            Object device2, Object acl2,
+            ProvisionPairwiseDevicesListener provisionPairwiseDevicesListener) throws OcException;
+
+    /**
+     * doOwnershipTransferListener can be registered with doOwnershipTransfer
+     * call.
+     * Listener notified asynchronously.
+     */
+    public interface DoOwnershipTransferListener {
+        public void doOwnershipTransferListener(List<ProvisionResult> provisionResultList,
+                int hasError);
+    }
+
+    /**
+     * removeDeviceListener can be registered with removeDeviceListener
+     * call.
+     * Listener notified asynchronously.
+     */
+    public interface RemoveDeviceListener {
+        public void removeDeviceListener(List<ProvisionResult> provisionResultList,
+                int hasError);
+    }
+
+    /**
+     * unlinkDevicesListener can be registered with unlinkDevicesListener
+     * call.
+     * Listener notified asynchronously.
+     */
+    public interface UnlinkDevicesListener {
+        public void unlinkDevicesListener(List<ProvisionResult> provisionResultList,
+                int hasError);
+    }
+
+    /**
+     * provisionCredentialsListener can be registered with provisionCredentialsListener
+     * call.
+     * Listener notified asynchronously.
+     */
+    public interface ProvisionCredentialsListener {
+        public void provisionCredentialsListener(List<ProvisionResult> provisionResultList,
+                int hasError);
+    }
+
+    /**
+     * provisionAclListener can be registered with provisionAclListener
+     * call.
+     * Listener notified asynchronously.
+     */
+    public interface ProvisionAclListener {
+        public void provisionAclListener(List<ProvisionResult> provisionResultList,
+                int hasError);
+    }
+
+    /**
+     * provisionPairwiseDevicesListener can be registered with provisionPairwiseDevicesListener
+     * call.
+     * Listener notified asynchronously.
+     */
+    public interface ProvisionPairwiseDevicesListener {
+        public void provisionPairwiseDevicesListener(List<ProvisionResult> provisionResultList,
+                int hasError);
+    }
+
+    /** Method to get List of device ID of devices linked with invoking device.
+     *
+     *  @return Sring List  List of device id's of linked devices.
+     */
+     public native List<String> getLinkedDevices();
+
+     /**
+      * Method to get IP address of sercure discovered device.
+      * @return Stringified IP address.
+      */
+    public native String getIpAddr();
+
+    /**
+     * Method to get device id of a device.
+     * @return  Device ID of the selected device.
+     */
+    public native String getDeviceID();
+
+    /**
+     * Method to get device status (ON/OFF) of a device.
+     * @return      ON/OFF
+     */
+
+    public DeviceStatus getDeviceStatus() throws OcException {
+        return DeviceStatus.convertDeviceStatus(this.deviceStatus());
+    }
+    public native int deviceStatus() throws OcException;
+
+    /**
+     * Method to get device  ownership (OWNED/UNOWNED) status.
+     * @return      OWNED/UNOWNED
+     */
+
+    public OwnedStatus getOwnedStatus() throws OcException {
+        return  OwnedStatus.convertOwnedStatus(this.ownedStatus());
+    }
+    public native int ownedStatus() throws OcException;
+
+    @Override
+    protected void finalize() throws Throwable {
+        super.finalize();
+        dispose();
+    }
+
+    private native void dispose();
+
+    private long mNativeHandle;
+}
diff --git a/android/android_api/base/src/main/java/org/iotivity/base/OicSecAcl.java b/android/android_api/base/src/main/java/org/iotivity/base/OicSecAcl.java
new file mode 100644 (file)
index 0000000..5ca6d96
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2015 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed 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.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+
+package org.iotivity.base;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Arrays;
+
+public class OicSecAcl implements Serializable {
+
+    private String       subject;
+    private int          permission;
+    private List<String> resources;
+    private List<String> periods;
+    private List<String> recurrences;
+    private List<String> owners;
+
+    public OicSecAcl(String subject, List<String> recurrences, List<String> periods, int permission,
+            List<String> resources, List<String> owners) {
+        this.subject = subject;
+        this.recurrences = recurrences;
+        this.periods = periods;
+        this.permission = permission;
+        this.resources = resources;
+        this.owners = owners;
+    }
+
+    public String getSubject() {
+        return this.subject;
+    }
+
+    public void setSubject(String subject) {
+        this.subject = subject;
+    }
+
+    public List<String> getOwners() {
+        return owners;
+    }
+
+    public void setOwners(List<String> owners) {
+        this.owners = owners;
+    }
+
+    public List<String> getRecurrences() {
+        return recurrences;
+    }
+
+    public void setRecurrences(List<String> recurrences) {
+        this.recurrences = recurrences;
+    }
+
+    public List<String> getPeriods() {
+        return periods;
+    }
+
+    public void setPeriods(List<String> periods) {
+        this.periods = periods;
+    }
+
+    public int getPermission() {
+        return this.permission;
+    }
+
+    public void setPermission(int permission) {
+        this.permission = permission;
+    }
+
+    public List<String> getResources() {
+        return resources;
+    }
+
+    public void setResources(List<String> resources) {
+        this.resources = resources;
+    }
+
+    public int getResourcesCount() {
+        return this.resources.size();
+    }
+
+    public String getResources(int i) {
+        return this.resources.get(i);
+    }
+
+    public int getPeriodsCount() {
+        return this.periods.size();
+    }
+
+    public String getPeriods(int i) {
+        return this.periods.get(i);
+    }
+
+    public String getRecurrences(int i) {
+        return this.recurrences.get(i);
+    }
+
+    public int getOwnersCount() {
+        return this.owners.size();
+    }
+
+    public String getOwners(int i) {
+        return this.owners.get(i);
+    }
+}
diff --git a/android/android_api/base/src/main/java/org/iotivity/base/OwnedStatus.java b/android/android_api/base/src/main/java/org/iotivity/base/OwnedStatus.java
new file mode 100644 (file)
index 0000000..1c90578
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * //******************************************************************
+ * //
+ * // Copyright Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed 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.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+
+package org.iotivity.base;
+
+public enum OwnedStatus {
+    OWNED(0),
+    UNOWNED(1),
+    INVALID(-1);
+
+    private int value;
+
+    private OwnedStatus(int value) {
+        this.value = value;
+    }
+
+    public int getValue() {
+        return this.value;
+    }
+
+    public static OwnedStatus convertOwnedStatus(int value) {
+
+        if (0 == value)
+        {
+            return OwnedStatus.UNOWNED;
+        }
+        else if (1 == value)
+        {
+            return OwnedStatus.OWNED;
+        }
+        else
+        {
+            return OwnedStatus.INVALID;
+        }
+    }
+}
diff --git a/android/android_api/base/src/main/java/org/iotivity/base/OxmType.java b/android/android_api/base/src/main/java/org/iotivity/base/OxmType.java
new file mode 100644 (file)
index 0000000..f336076
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2015 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed 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.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+
+package org.iotivity.base;
+
+public enum OxmType {
+    OIC_JUST_WORKS(0),
+    OIC_MODE_SWITCH(1),
+    OIC_RANDOM_DEVICE_PIN(2),
+    OIC_PRE_PROVISIONED_DEVICE_PIN(3),
+    OIC_PRE_PROVISION_STRONG_CREDENTIAL(4),
+    OIC_OXM_COUNT(5);
+
+    private int value;
+
+    private OxmType(int value) {
+        this.value = value;
+    }
+
+    public int getValue() {
+        return this.value;
+    }
+}
diff --git a/android/android_api/base/src/main/java/org/iotivity/base/ProvisionResult.java b/android/android_api/base/src/main/java/org/iotivity/base/ProvisionResult.java
new file mode 100644 (file)
index 0000000..5d46b8f
--- /dev/null
@@ -0,0 +1,41 @@
+/* *****************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed 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.
+ *
+ * *****************************************************************/
+package org.iotivity.base;
+
+public class ProvisionResult {
+
+    private String mDeviceId;
+    private int mResult;
+
+    public ProvisionResult(String deviceId, int result)
+    {
+        this.mDeviceId = deviceId;
+        this.mResult = result;
+    }
+
+    public String getDevId()
+    {
+        return this.mDeviceId;
+    }
+    public int getResult()
+    {
+        return this.mResult;
+    }
+}
diff --git a/android/examples/provisioningclient/build.gradle b/android/examples/provisioningclient/build.gradle
new file mode 100644 (file)
index 0000000..252b151
--- /dev/null
@@ -0,0 +1,24 @@
+apply plugin: 'com.android.application'\r
+\r
+android {\r
+    compileSdkVersion 21\r
+    buildToolsVersion "21.1.2"\r
+\r
+    defaultConfig {\r
+        applicationId "org.iotivity.base.examples.provisioningclient"\r
+        minSdkVersion 19\r
+        targetSdkVersion 21\r
+        versionCode 1\r
+        versionName "1.0"\r
+    }\r
+    buildTypes {\r
+        release {\r
+            minifyEnabled false\r
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\r
+        }\r
+    }\r
+}\r
+\r
+dependencies {\r
+    compile 'com.android.support:appcompat-v7:21.0.3'\r
+}\r
diff --git a/android/examples/provisioningclient/proguard-rules.pro b/android/examples/provisioningclient/proguard-rules.pro
new file mode 100644 (file)
index 0000000..8a79c59
--- /dev/null
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /home/sri/Android/Sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
diff --git a/android/examples/provisioningclient/provisioningclient.iml b/android/examples/provisioningclient/provisioningclient.iml
new file mode 100644 (file)
index 0000000..c44426e
--- /dev/null
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="examples" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
+  <component name="FacetManager">
+    <facet type="android-gradle" name="Android-Gradle">
+      <configuration>
+        <option name="GRADLE_PROJECT_PATH" value=":secureprovisionclient" />
+      </configuration>
+    </facet>
+    <facet type="android" name="Android">
+      <configuration>
+        <option name="SELECTED_BUILD_VARIANT" value="debug" />
+        <option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
+        <option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
+        <option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
+        <option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugTest" />
+        <option name="SOURCE_GEN_TASK_NAME" value="generateDebugSources" />
+        <option name="TEST_SOURCE_GEN_TASK_NAME" value="generateDebugTestSources" />
+        <option name="ALLOW_USER_CONFIGURATION" value="false" />
+        <option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
+        <option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
+        <option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" />
+        <option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
+      </configuration>
+    </facet>
+  </component>
+  <component name="NewModuleRootManager" inherit-compiler-output="false">
+    <output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
+    <output-test url="file://$MODULE_DIR$/build/intermediates/classes/test/debug" />
+    <exclude-output />
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/res/generated/debug" type="java-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/test/debug" isTestSource="true" generated="true" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/test/debug" isTestSource="true" generated="true" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/test/debug" isTestSource="true" generated="true" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/test/debug" isTestSource="true" generated="true" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/test/debug" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/res/generated/test/debug" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/coverage-instrumented-classes" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex-cache" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/jacoco" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaResources" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/libs" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/ndk" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/proguard" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
+      <excludeFolder url="file://$MODULE_DIR$/build/outputs" />
+      <excludeFolder url="file://$MODULE_DIR$/build/tmp" />
+    </content>
+    <orderEntry type="jdk" jdkName="Android API 22 Platform" jdkType="Android SDK" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="library" exported="" name="appcompat-v7-21.0.3" level="project" />
+    <orderEntry type="library" exported="" name="iotivity-armeabi-base-debug-" level="project" />
+    <orderEntry type="library" exported="" name="support-annotations-21.0.3" level="project" />
+    <orderEntry type="library" exported="" name="support-v4-21.0.3" level="project" />
+    <orderEntry type="module" module-name="message" exported="" />
+  </component>
+</module>
+
diff --git a/android/examples/provisioningclient/src/main/AndroidManifest.xml b/android/examples/provisioningclient/src/main/AndroidManifest.xml
new file mode 100644 (file)
index 0000000..93a375b
--- /dev/null
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="org.iotivity.base.examples.provisioningclient" >
+
+    <application
+        android:allowBackup="true"
+        android:icon="@mipmap/ic_launcher"
+        android:label="@string/app_name"
+        android:theme="@style/AppTheme" >
+        <activity
+            android:name=".ProvisioningClient"
+            android:label="@string/app_name" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+</manifest>
diff --git a/android/examples/provisioningclient/src/main/assets/oic_svr_db_client.json b/android/examples/provisioningclient/src/main/assets/oic_svr_db_client.json
new file mode 100644 (file)
index 0000000..17dc43f
--- /dev/null
@@ -0,0 +1,49 @@
+{
+    "acl": [
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/res",
+                "/oic/d",
+                "/oic/p",
+                "/oic/res/types/d",
+                "/oic/ad",
+                "/oic/sec/acl"
+                       ],
+                       "perms": 2,
+                       "ownrs" : ["MjIyMjIyMjIyMjIyMjIyMg=="]
+               },
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/sec/doxm",
+                "/oic/sec/pstat"
+             ],
+             "perms": 2,
+             "ownrs" : ["MjIyMjIyMjIyMjIyMjIyMg=="]
+        }
+       ],
+       "pstat":        {
+               "isop": true,
+               "deviceid":     "ZGV2aWNlaWQAAAAAABhanw==",
+               "ch": 0,
+               "cm":   0,
+               "tm":   0,
+               "om":   3,
+               "sm":   [3]
+       },
+       "doxm": {
+               "oxm":  [0],
+               "oxmsel": 0,
+               "owned": true,
+               "deviceid":     "MjIyMjIyMjIyMjIyMjIyMg==",
+               "ownr": "MjIyMjIyMjIyMjIyMjIyMg=="
+       },
+    "cred":    [{
+               "credid": 1,
+               "sub": "MTExMTExMTExMTExMTExMQ==",
+               "credtyp": 1,
+               "pvdata": "QUFBQUFBQUFBQUFBQUFBQQ==",
+        "ownrs" : ["MjIyMjIyMjIyMjIyMjIyMg=="]
+       }]
+}
diff --git a/android/examples/provisioningclient/src/main/java/org/iotivity/base/examples/provisioningclient/ProvisioningClient.java b/android/examples/provisioningclient/src/main/java/org/iotivity/base/examples/provisioningclient/ProvisioningClient.java
new file mode 100644 (file)
index 0000000..b9758af
--- /dev/null
@@ -0,0 +1,711 @@
+
+package org.iotivity.base.examples.provisioningclient;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Message;
+import android.preference.PreferenceManager;
+import android.text.method.ScrollingMovementMethod;
+import android.util.Log;
+import android.view.Gravity;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+
+import org.iotivity.base.ModeType;
+
+import org.iotivity.base.OcException;
+
+import org.iotivity.base.OcPlatform;
+
+
+import org.iotivity.base.PlatformConfig;
+import org.iotivity.base.QualityOfService;
+import org.iotivity.base.ServiceType;
+import org.iotivity.base.OcProvisioning;
+import org.iotivity.base.OcSecureResource;
+import org.iotivity.base.ProvisionResult;
+import org.iotivity.base.OxmType;
+import org.iotivity.base.OicSecAcl;
+import org.iotivity.base.CredType;
+import org.iotivity.base.KeySize;
+import org.iotivity.base.DeviceStatus;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.EnumSet;
+
+
+import java.util.List;
+
+
+public class ProvisioningClient extends Activity implements
+        OcSecureResource.DoOwnershipTransferListener,
+        OcSecureResource.ProvisionPairwiseDevicesListener {
+    private static final String TAG = "Provisioning Client: ";
+    OcProvisioning.PinCallbackListener pinCallbackListener =
+            new OcProvisioning.PinCallbackListener() {
+                @Override
+                public String pinCallbackListener() {
+
+                    Log.d(TAG, "Inside Pin Callback ");
+                    return "";
+
+                }
+            };
+    OcSecureResource.ProvisionAclListener provisionAclListener =
+            new OcSecureResource.ProvisionAclListener() {
+                @Override
+                public void provisionAclListener(List<ProvisionResult> provisionResults,
+                                                 int hasError) {
+
+                    Log.d(TAG, "Inside ProvisionAclListener ");
+
+                    if (hasError == StringConstants.ERROR_CODE) {
+                        logMessage("Error: ACL Provision failed !!");
+                    } else {
+                        logMessage("ACL Provision Done !!");
+                        new DeviceRevocationAsyncTask().execute();
+                    }
+
+                }
+            };
+    OcSecureResource.ProvisionCredentialsListener provisionCredentialsListener =
+            new OcSecureResource.ProvisionCredentialsListener() {
+                @Override
+                public void provisionCredentialsListener(List<ProvisionResult> provisionResults,
+                                                         int hasError) {
+
+                    Log.d(TAG, "Inside ProvisionCredentialsListener ");
+                    if (hasError == StringConstants.ERROR_CODE) {
+                        logMessage("Error: Provision Credentials failed !!");
+                    } else {
+                        logMessage("Provision Credentials Done !!");
+                        new ProvisionACLAsyncTask().execute();
+                    }
+
+
+                }
+            };
+    OcSecureResource.UnlinkDevicesListener unlinkDevicesListener =
+            new OcSecureResource.UnlinkDevicesListener() {
+                @Override
+                public void unlinkDevicesListener(List<ProvisionResult> provisionResults,
+                                                  int hasError) {
+                    Log.d(TAG, "Inside unlinkDevicesListener ");
+
+                    if (hasError == StringConstants.ERROR_CODE) {
+                        logMessage("Error: UnLinking device !!");
+                    } else {
+                        logMessage("Unlink Done !!");
+                        new ProvisionCredentialAsyncTask().execute();
+                    }
+
+                }
+            };
+
+    OcSecureResource.RemoveDeviceListener removeDeviceListener =
+            new OcSecureResource.RemoveDeviceListener() {
+                @Override
+                public void removeDeviceListener(List<ProvisionResult> provisionResults,
+                                                 int hasError) {
+                    if (hasError == StringConstants.ERROR_CODE) {
+                        logMessage("Error: Remove Fail !!");
+                    } else {
+                        logMessage("Remove Device done !!");
+                    }
+                }
+            };
+    private static final int BUFFER_SIZE = 1024;
+    int unownedDevCount = StringConstants.NUMBER_ZERO;
+    private String filePath = "";
+    private OcSecureResource newSecureResource;
+    private List<OcSecureResource> deviceList;
+    private List<OcSecureResource> ownedDeviceList;
+    //for display
+    private TextView mEventsTextView;
+
+    /**
+     * configure OIC platform and call findResource
+     */
+    private void initOICStack() {
+
+        //create platform config
+        PlatformConfig cfg = new PlatformConfig(
+                this,
+                ServiceType.IN_PROC,
+                ModeType.CLIENT_SERVER,
+                "0.0.0.0", // bind to all available interfaces
+                0,
+                QualityOfService.LOW, filePath + StringConstants.OIC_CLIENT_JSON_DB_FILE);
+        OcPlatform.Configure(cfg);
+
+        try {
+            /*
+             * Initialize DataBase
+             */
+
+            String sqlDbPath = getFilesDir().getAbsolutePath().replace("files", "databases") +
+                    File.separator;
+
+            File file = new File(sqlDbPath);
+            //check files directory exists
+            if (!(file.isDirectory())) {
+                file.mkdirs();
+                Log.d(TAG, "Sql db directory created at " + sqlDbPath);
+            }
+            Log.d(TAG, "Sql db directory exists at " + sqlDbPath);
+
+            OcProvisioning.provisionInit(sqlDbPath + StringConstants.OIC_SQL_DB_FILE);
+        } catch (OcException e) {
+            logMessage(TAG + "provisionInit error: " + e.getMessage());
+            Log.e(TAG, e.getMessage());
+        }
+
+        new DiscoveryOTTransferAsyncTask().execute();
+    }
+
+    @Override
+    synchronized public void doOwnershipTransferListener(List<ProvisionResult> ProvisionResultList,
+                                                         int hasError) {
+
+        ProvisionResult pResult = ProvisionResultList.get(0);
+        if (hasError == StringConstants.ERROR_CODE) {
+            logMessage(TAG + "Ownership Transfer Failed for " + pResult.getDevId());
+        } else {
+            logMessage(TAG + "Ownership Transfer Successful for "
+                    + pResult.getDevId());
+            unownedDevCount--;
+        }
+
+        if (unownedDevCount == 0) { //When done with Ownership Transfer
+            new OwnedDiscoveryAsyncTask().execute();
+        }
+    }
+
+    private void doPairwiseProvisioning() {
+        try {
+            logMessage(TAG + "Pairwise Provisioning b/w " + ownedDeviceList.get(0).getDeviceID()
+                    + " and " + ownedDeviceList.get(1).getDeviceID());
+            newSecureResource = ownedDeviceList.get(0);
+            OcSecureResource newSecureResource2 = ownedDeviceList.get(1);
+            List<String> resources = new ArrayList<String>();
+            List<String> owners = new ArrayList<String>();
+            List<String> periods = new ArrayList<String>();
+            List<String> recurrences = new ArrayList<String>();
+            recurrences.add("Daily");
+            resources.add("*");
+            owners.add("adminDeviceUUID0");
+            periods.add("01-01-15");
+            OicSecAcl acl1 = new OicSecAcl(newSecureResource.getDeviceID(), recurrences, periods,
+                    31, resources, owners);
+            OicSecAcl acl2 = new OicSecAcl(newSecureResource2.getDeviceID(), recurrences, periods,
+                    31, resources, owners);
+            newSecureResource.provisionPairwiseDevices(EnumSet.of(CredType.SYMMETRIC_PAIR_WISE_KEY),
+                    KeySize.OWNER_PSK_LENGTH_128, acl1, newSecureResource2, acl2, this);
+
+        } catch (Exception e) {
+            logMessage(TAG + "Pairwise Provisioning  error: " + e.getMessage());
+            Log.e(TAG, e.getMessage());
+        }
+    }
+
+    @Override
+    public void provisionPairwiseDevicesListener(List<ProvisionResult> ProvisionResultList,
+                                                 int hasError) {
+        if (hasError == StringConstants.ERROR_CODE) {
+            logMessage(TAG + "provisionPairwiseDevices Failed");
+        } else {
+            for (int i = 0; i < ProvisionResultList.size(); i++) {
+                ProvisionResult pResult = ProvisionResultList.get(i);
+                logMessage(TAG + "provisionPairwiseDevices Result for "
+                        + pResult.getDevId() + "is " + pResult.getResult());
+            }
+            new GetLinkedDevicesAsyncTask().execute();
+        }
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_secure_provision_client);
+        mEventsTextView = new TextView(this);
+        mEventsTextView.setGravity(Gravity.BOTTOM);
+        mEventsTextView.setMovementMethod(new ScrollingMovementMethod());
+        LinearLayout layout = (LinearLayout) findViewById(R.id.linearLayout);
+        layout.addView(mEventsTextView, new LinearLayout.LayoutParams(
+                        LinearLayout.LayoutParams.MATCH_PARENT, 0, 1f)
+        );
+
+        filePath = getFilesDir().getPath() + "/"; //  data/data/<package>/files/
+        //copy json when application runs first time
+        SharedPreferences wmbPreference = PreferenceManager.getDefaultSharedPreferences(this);
+        boolean isFirstRun = wmbPreference.getBoolean("FIRSTRUN", true);
+        if (isFirstRun) {
+            copyJsonFromAsset();
+            SharedPreferences.Editor editor = wmbPreference.edit();
+            editor.putBoolean("FIRSTRUN", false);
+            editor.commit();
+        }
+        initOICStack();
+    }
+
+    /**
+     * Copy svr db json file from assets folder to app data files dir
+     */
+    private void copyJsonFromAsset() {
+        InputStream inputStream = null;
+        OutputStream outputStream = null;
+        int length;
+        byte[] buffer = new byte[BUFFER_SIZE];
+
+        try {
+            inputStream = getAssets().open(StringConstants.OIC_CLIENT_JSON_DB_FILE);
+            File file = new File(filePath);
+            //check files directory exists
+            if (!(file.exists() && file.isDirectory())) {
+                file.mkdirs();
+            }
+            outputStream = new FileOutputStream(filePath + StringConstants.OIC_CLIENT_JSON_DB_FILE);
+
+            while ((length = inputStream.read(buffer)) != -1) {
+                outputStream.write(buffer, 0, length);
+            }
+
+
+        } catch (NullPointerException e) {
+            logMessage(TAG + "Null pointer exception " + e.getMessage());
+            Log.e(TAG, e.getMessage());
+        } catch (FileNotFoundException e) {
+            logMessage(TAG + "Json svr db file not found " + e.getMessage());
+            Log.e(TAG, e.getMessage());
+        } catch (IOException e) {
+            logMessage(TAG + StringConstants.OIC_CLIENT_JSON_DB_FILE + " file copy failed");
+            Log.e(TAG, e.getMessage());
+        } finally {
+            if (inputStream != null) {
+                try {
+                    inputStream.close();
+                } catch (IOException e) {
+                    Log.e(TAG, e.getMessage());
+                }
+            }
+            if (outputStream != null) {
+                try {
+                    outputStream.close();
+                } catch (IOException e) {
+                    Log.e(TAG, e.getMessage());
+                }
+            }
+        }
+    }
+
+    public void logMessage(String text) {
+        logMsg(text);
+    }
+
+    public void logMsg(final String text) {
+        runOnUiThread(new Runnable() {
+            public void run() {
+                Message msg = new Message();
+                msg.obj = text;
+                mEventsTextView.append(text);
+                mEventsTextView.append("\n\n");
+            }
+        });
+        Log.i(TAG, text);
+
+        Intent intent = new Intent(getPackageName());
+        intent.putExtra(StringConstants.MESSAGE, text);
+        sendBroadcast(intent);
+    }
+
+    private class DiscoveryOTTransferAsyncTask extends AsyncTask<Void, String, String> {
+
+        @Override
+        protected void onPreExecute() {
+            super.onPreExecute();
+        }
+
+        @Override
+        protected String doInBackground(Void... params) {
+            try {
+                /**
+                 * Discover Un-owned devices
+                 */
+
+                publishProgress(TAG + "Discovering Unowned Devices");
+                deviceList = new ArrayList<OcSecureResource>();
+                deviceList = OcProvisioning.discoverUnownedDevices(5);
+
+
+                if (deviceList.size() > 0) {
+                    unownedDevCount = deviceList.size();
+                    for (int i = 0; i < deviceList.size(); i++) {
+                        publishProgress(TAG + "Un-owned Discovered Device " + (i + 1) + "= " +
+                                deviceList.get(i).getDeviceID());
+                    }
+
+
+                    try {
+
+                        OcProvisioning.SetownershipTransferCBdata(OxmType.OIC_JUST_WORKS,
+                                pinCallbackListener);
+
+                        for (int i = 0; i < deviceList.size(); i++) {
+                            publishProgress(TAG + "Doing Ownership Transfer for " +
+                                    deviceList.get(i).getDeviceID());
+                            deviceList.get(i).doOwnershipTransfer(ProvisioningClient.this);
+                        }
+                    } catch (OcException e) {
+                        publishProgress(TAG + "Ownership Transfer error: " + e.getMessage());
+                        return "Ownership Transfer error: " + e.getMessage();
+
+                    }
+
+
+                } else {
+                    publishProgress(TAG + "No un-owned devices present");
+                }
+
+            } catch (OcException e) {
+                publishProgress(TAG + "Un-owned discovery error: " + e.getMessage());
+                return "Un-owned discovery error:  " + e.getMessage();
+
+            }
+            return "success";
+        }
+
+        @Override
+        protected void onProgressUpdate(String... values) {
+            logMessage(values[0]);
+        }
+
+        @Override
+        protected void onPostExecute(String s) {
+            super.onPostExecute(s);
+        }
+    }
+
+    private class ProvisionACLAsyncTask extends AsyncTask<Void, String, Void> {
+
+        @Override
+        protected void onPreExecute() {
+            super.onPreExecute();
+        }
+
+        @Override
+        protected Void doInBackground(Void... params) {
+            try {
+
+
+                if (ownedDeviceList.size() > 1) {
+                    OcSecureResource ocSecureResource = ownedDeviceList.get(0);
+
+                    OcSecureResource ocSecureResourceDest = ownedDeviceList.get(1);
+
+                    publishProgress(TAG + "ACL Provision for " + ocSecureResource.getDeviceID());
+
+                    List<String> resources = new ArrayList<String>();
+                    List<String> owners = new ArrayList<String>();
+                    List<String> periods = new ArrayList<String>();
+                    List<String> recurrences = new ArrayList<String>();
+                    recurrences.add("Daily");
+                    resources.add("*");
+                    owners.add("adminDeviceUUID0");
+                    periods.add("01-01-15");
+
+                    OicSecAcl aclObject = new OicSecAcl(ocSecureResourceDest.getDeviceID(),
+                            recurrences, periods, 31, resources, owners);
+
+
+                    ocSecureResource.provisionACL(aclObject, provisionAclListener);
+
+                } else {
+                    publishProgress(TAG + "No Owned devices present");
+                }
+
+            } catch (Exception e) {
+                publishProgress(TAG + "ProvisionACL error: " + e.getMessage());
+
+
+            }
+            return null;
+        }
+
+        @Override
+        protected void onProgressUpdate(String... values) {
+            logMessage(values[0]);
+        }
+
+
+    }
+
+    private class ProvisionCredentialAsyncTask extends AsyncTask<Void, String, Void> {
+
+        @Override
+        protected void onPreExecute() {
+            super.onPreExecute();
+        }
+
+        @Override
+        protected Void doInBackground(Void... params) {
+            try {
+
+                if (ownedDeviceList.size() > 1) {
+
+                    OcSecureResource ocSecureResource = ownedDeviceList.get(0);
+                    OcSecureResource ocSecureResourceDest = ownedDeviceList.get(1);
+                    publishProgress(TAG + "ProvisionCredential for " +
+                            ocSecureResource.getDeviceID() + " with " +
+                            ocSecureResourceDest.getDeviceID());
+
+
+                    int credential_type = StringConstants.CREDENTIAL_TYPE; //symmetrical
+                    int psk_length = StringConstants.OWNER_PSK_LENGTH_128;
+
+                    ocSecureResource.provisionCredentials(EnumSet.of(CredType.SYMMETRIC_PAIR_WISE_KEY),
+                            KeySize.OWNER_PSK_LENGTH_128,
+                            ocSecureResourceDest, provisionCredentialsListener);
+
+
+                } else {
+                    publishProgress(TAG + "Cannot perform credentials between devices");
+                }
+
+            } catch (Exception e) {
+                publishProgress(TAG + "ProvisionACL error: " + e.getMessage());
+
+
+            }
+            return null;
+        }
+
+        @Override
+        protected void onProgressUpdate(String... values) {
+            logMessage(values[0]);
+        }
+
+
+    }
+
+    private class GetLinkedDevicesAsyncTask extends AsyncTask<Void, String, String> {
+
+        @Override
+        protected void onPreExecute() {
+            super.onPreExecute();
+        }
+
+        @Override
+        protected String doInBackground(Void... params) {
+            try {
+
+                if (ownedDeviceList.size() > 1) {
+
+                    OcSecureResource ocSecureResource = ownedDeviceList.get(0);
+                    publishProgress(TAG + "Get linked devices of " + ocSecureResource.getDeviceID());
+
+
+                    List<String> linkedDevices= ocSecureResource.getLinkedDevices();
+                    if(linkedDevices.size() >0 )
+                    {
+                        for (int i = 0; i < linkedDevices.size(); i++) {
+                            publishProgress(TAG + "Linked Devices "+
+                                            + (i + 1) + "= " + linkedDevices.get(i)
+                            );
+                        }
+                    }
+                    else
+                    {
+                        publishProgress(TAG + "No linked Devices found");
+                    }
+                } else {
+                    publishProgress(TAG + "Cannot perform linked devices");
+                }
+
+            } catch (Exception e) {
+                publishProgress(TAG + "getLinked device error: " + e.getMessage());
+                return "failed";
+
+
+            }
+            return "success";
+        }
+
+        @Override
+        protected void onProgressUpdate(String... values) {
+            logMessage(values[0]);
+        }
+
+
+        @Override
+        protected void onPostExecute(String s) {
+
+            if ("success".equals(s)) {
+                new ProvisionUnlinkAsyncTask().execute();
+
+            }
+
+
+        }
+
+    }
+
+
+    private class ProvisionUnlinkAsyncTask extends AsyncTask<Void, String, Void> {
+
+        @Override
+        protected void onPreExecute() {
+            super.onPreExecute();
+        }
+
+        @Override
+        protected Void doInBackground(Void... params) {
+            try {
+
+                if (ownedDeviceList.size() > 1) {
+
+                    OcSecureResource ocSecureResource = ownedDeviceList.get(0);
+                    OcSecureResource ocSecureResourceDest = ownedDeviceList.get(1);
+                    publishProgress(TAG + "Un linking  " + ocSecureResource.getDeviceID() +
+                            " with " + ocSecureResourceDest.getDeviceID());
+
+                    ocSecureResource.unlinkDevices(ocSecureResourceDest, unlinkDevicesListener);
+
+
+                } else {
+                    publishProgress(TAG + "Cannot perform unlink devices");
+                }
+
+            } catch (Exception e) {
+                publishProgress(TAG + "Unlink error: " + e.getMessage());
+
+
+            }
+            return null;
+        }
+
+        @Override
+        protected void onProgressUpdate(String... values) {
+            logMessage(values[0]);
+        }
+
+
+    }
+
+
+    private class DeviceRevocationAsyncTask extends AsyncTask<Void, String, Void> {
+
+        @Override
+        protected void onPreExecute() {
+            super.onPreExecute();
+        }
+
+        @Override
+        protected Void doInBackground(Void... params) {
+            try {
+
+                if (ownedDeviceList.size() > 0) {
+
+                    OcSecureResource ocSecureResource = ownedDeviceList.get(0);
+
+                    publishProgress(TAG + "Removing " + ocSecureResource.getDeviceID());
+
+                    ocSecureResource.removeDevice(20, removeDeviceListener);
+
+
+                } else {
+                    publishProgress(TAG + "Cannot remove");
+                }
+
+            } catch (Exception e) {
+                publishProgress(TAG + "Remove Device error: " + e.getMessage());
+
+
+            }
+            return null;
+        }
+
+        @Override
+        protected void onProgressUpdate(String... values) {
+            logMessage(values[0]);
+        }
+
+
+    }
+
+    private class OwnedDiscoveryAsyncTask extends AsyncTask<Void, String, String> {
+
+        @Override
+        protected void onPreExecute() {
+            super.onPreExecute();
+        }
+
+        @Override
+        protected String doInBackground(Void... params) {
+            try {
+                publishProgress(TAG + "Initiate Owned device Discovery");
+
+                ownedDeviceList = OcProvisioning.discoverOwnedDevices(10);
+
+                if (ownedDeviceList.size() > 0) {
+                    for (int i = 0; i < ownedDeviceList.size(); i++) {
+                        publishProgress(TAG + "Owned Discovered Device " + (i + 1) + "= " +
+                                        ownedDeviceList.get(i).getDeviceID()
+                                        + "\nIP Address= " + ownedDeviceList.get(i).getIpAddr()
+                                        + "\nOwned Status= " + ownedDeviceList.get(i).getOwnedStatus()
+                                        + "\nDevice Status= " + ((ownedDeviceList.get(i).
+                                        getDeviceStatus() == DeviceStatus.ON) ? "ON" : "OFF")
+                        );
+                    }
+                } else {
+                    publishProgress(TAG + "No Owned devices present");
+                }
+
+            } catch (OcException e) {
+                publishProgress(TAG + "Owned device Discovery error: " + e.getMessage());
+                return "Owned device Discovery error: " + e.getMessage();
+
+            }
+            return "success";
+        }
+
+        @Override
+        protected void onProgressUpdate(String... values) {
+            logMessage(values[0]);
+        }
+
+        @Override
+        protected void onPostExecute(String s) {
+
+            if (ownedDeviceList.size() > 1 && "success".equals(s)) {
+                doPairwiseProvisioning();
+
+            }
+
+
+        }
+
+    }
+
+    /**
+     * to display on Server Message on Client screen
+     */
+    public class MessageReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            final String message = intent.getStringExtra(StringConstants.MESSAGE);
+            logMessage(message);
+        }
+    }
+}
diff --git a/android/examples/provisioningclient/src/main/java/org/iotivity/base/examples/provisioningclient/StringConstants.java b/android/examples/provisioningclient/src/main/java/org/iotivity/base/examples/provisioningclient/StringConstants.java
new file mode 100644 (file)
index 0000000..0854861
--- /dev/null
@@ -0,0 +1,12 @@
+package org.iotivity.base.examples.provisioningclient;
+
+public interface StringConstants {
+
+    public static final int NUMBER_ZERO =  0;
+    public static final int ERROR_CODE =  1;
+    public static final String OIC_CLIENT_JSON_DB_FILE =  "oic_svr_db_client.json";
+    public static final String MESSAGE = "message";
+    public static final String OIC_SQL_DB_FILE =  "Pdm.db";
+    public static final int  CREDENTIAL_TYPE=1;
+    public static final int  OWNER_PSK_LENGTH_128=128/8;
+}
diff --git a/android/examples/provisioningclient/src/main/res/layout/activity_secure_provision_client.xml b/android/examples/provisioningclient/src/main/res/layout/activity_secure_provision_client.xml
new file mode 100644 (file)
index 0000000..596ac98
--- /dev/null
@@ -0,0 +1,16 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
+    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
+    android:paddingRight="@dimen/activity_horizontal_margin"
+    android:paddingTop="@dimen/activity_vertical_margin"
+    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"
+    android:label="@string/app_name">
+
+    <LinearLayout
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+        android:orientation="vertical"
+        android:id="@+id/linearLayout" >
+    </LinearLayout>
+</RelativeLayout>
+
diff --git a/android/examples/provisioningclient/src/main/res/menu/menu_secure_provision_client.xml b/android/examples/provisioningclient/src/main/res/menu/menu_secure_provision_client.xml
new file mode 100644 (file)
index 0000000..dd57e4d
--- /dev/null
@@ -0,0 +1,5 @@
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools" tools:context=".SecureProvisionClientActivity">
+    <item android:id="@+id/action_settings" android:title="@string/action_settings"
+        android:orderInCategory="100" android:showAsAction="never" />
+</menu>
diff --git a/android/examples/provisioningclient/src/main/res/mipmap-hdpi/ic_launcher.png b/android/examples/provisioningclient/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..cde69bc
Binary files /dev/null and b/android/examples/provisioningclient/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/android/examples/provisioningclient/src/main/res/mipmap-mdpi/ic_launcher.png b/android/examples/provisioningclient/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..c133a0c
Binary files /dev/null and b/android/examples/provisioningclient/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/android/examples/provisioningclient/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/examples/provisioningclient/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..bfa42f0
Binary files /dev/null and b/android/examples/provisioningclient/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/android/examples/provisioningclient/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/examples/provisioningclient/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..324e72c
Binary files /dev/null and b/android/examples/provisioningclient/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/android/examples/provisioningclient/src/main/res/values-v21/styles.xml b/android/examples/provisioningclient/src/main/res/values-v21/styles.xml
new file mode 100644 (file)
index 0000000..dba3c41
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <style name="AppTheme" parent="android:Theme.Material.Light">
+    </style>
+</resources>
diff --git a/android/examples/provisioningclient/src/main/res/values-w820dp/dimens.xml b/android/examples/provisioningclient/src/main/res/values-w820dp/dimens.xml
new file mode 100644 (file)
index 0000000..63fc816
--- /dev/null
@@ -0,0 +1,6 @@
+<resources>
+    <!-- Example customization of dimensions originally defined in res/values/dimens.xml
+         (such as screen margins) for screens with more than 820dp of available width. This
+         would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
+    <dimen name="activity_horizontal_margin">64dp</dimen>
+</resources>
diff --git a/android/examples/provisioningclient/src/main/res/values/dimens.xml b/android/examples/provisioningclient/src/main/res/values/dimens.xml
new file mode 100644 (file)
index 0000000..47c8224
--- /dev/null
@@ -0,0 +1,5 @@
+<resources>
+    <!-- Default screen margins, per the Android Design guidelines. -->
+    <dimen name="activity_horizontal_margin">16dp</dimen>
+    <dimen name="activity_vertical_margin">16dp</dimen>
+</resources>
diff --git a/android/examples/provisioningclient/src/main/res/values/strings.xml b/android/examples/provisioningclient/src/main/res/values/strings.xml
new file mode 100644 (file)
index 0000000..fafb434
--- /dev/null
@@ -0,0 +1,6 @@
+<resources>
+    <string name="app_name">Provisioning Client</string>
+
+    <string name="hello_world">Hello world!</string>
+    <string name="action_settings">Settings</string>
+</resources>
diff --git a/android/examples/provisioningclient/src/main/res/values/styles.xml b/android/examples/provisioningclient/src/main/res/values/styles.xml
new file mode 100644 (file)
index 0000000..ff6c9d2
--- /dev/null
@@ -0,0 +1,8 @@
+<resources>
+
+    <!-- Base application theme. -->
+    <style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+        <!-- Customize your theme here. -->
+    </style>
+
+</resources>
index 388afde..e679784 100755 (executable)
@@ -1 +1 @@
-include ':simpleserver', ':simpleclient', ':message', ':fridgeserver', ':fridgeclient', ':guiclient', ':presenceserver', ':presenceclient', ':devicediscoveryclient', ':devicediscoveryserver', ':iotivity-armeabi-base-debug'
+include ':simpleserver', ':simpleclient', ':message', ':fridgeserver', ':fridgeclient', ':guiclient', ':secureprovisionclient', ':presenceserver', ':presenceclient', ':devicediscoveryclient', ':devicediscoveryserver', ':iotivity-armeabi-base-debug'
index c07f00c..4e1099f 100755 (executable)
@@ -48,10 +48,11 @@ libocsrm_env.PrependUnique(CPPPATH = [
                '../../oc_logger/include',
                '../connectivity/lib/libcoap-4.1.1',
                '../connectivity/external/inc',
+               '../connectivity/common/inc',
                '../connectivity/inc',
                '../connectivity/api',
                '../security/include',
-               '../security/include/internal',
+               '../security/include/internal'
                ])
 
 if target_os not in ['arduino', 'windows', 'winrt']:
@@ -91,6 +92,7 @@ if env.get('SECURED') == '1':
                OCSRM_SRC + 'resourcemanager.c',
                OCSRM_SRC + 'aclresource.c',
                OCSRM_SRC + 'amaclresource.c',
+               OCSRM_SRC + 'amsmgr.c',
                OCSRM_SRC + 'pstatresource.c',
                OCSRM_SRC + 'doxmresource.c',
                OCSRM_SRC + 'credresource.c',
@@ -112,6 +114,7 @@ else:
                OCSRM_SRC + 'resourcemanager.c',
                OCSRM_SRC + 'aclresource.c',
                OCSRM_SRC + 'amaclresource.c',
+               OCSRM_SRC + 'amsmgr.c',
                OCSRM_SRC + 'pstatresource.c',
                OCSRM_SRC + 'doxmresource.c',
                OCSRM_SRC + 'credresource.c',
@@ -134,6 +137,6 @@ libocsrm = libocsrm_env.StaticLibrary('libocsrm', libocsrm_src)
 libocsrm_env.InstallTarget(libocsrm, 'libocsrm')
 libocsrm_env.UserInstallTargetLib(libocsrm, 'libocsrm')
 
-if target_os == 'linux' and env.get('SECURED') == '1':
+if target_os in ['linux', 'android'] and env.get('SECURED') == '1':
        SConscript('provisioning/SConscript')
 
index 216fbd5..564d23f 100644 (file)
@@ -62,6 +62,7 @@ const OicSecAcl_t* GetACLResourceData(const OicUuid_t* subjectId, OicSecAcl_t **
  */
 char* BinToAclJSON(const OicSecAcl_t * acl);
 
+
 /**
  * This function deletes ACL data.
  *
@@ -69,6 +70,16 @@ char* BinToAclJSON(const OicSecAcl_t * acl);
  */
 void DeleteACLList(OicSecAcl_t* acl);
 
+
+/**
+ * This function installs a new ACL.
+ * @param newJsonStr JSON string representing a new ACL.
+ *
+ * @retval  OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult InstallNewACL(const char* newJsonStr);
+
+
 #ifdef __cplusplus
 }
 #endif
index e1f4f5b..9c37a0e 100755 (executable)
@@ -48,17 +48,19 @@ OCStackResult InitAmaclResource();
 void DeInitAmaclResource();
 
 /**
- * This method is used by PolicyEngine to retrieve Amacl for a Subject.
+ * This method is used by PolicyEngine to retrieve amsId for the resource.
+ * If the Amacl is found for the given resource then populate the parameter
+ * amsId with Amacl resource amss id.
  *
- * @param subjectId ID of the subject for which Amacl is required.
- * @param savePtr is used internally by @ref GetAmaclResourceData to maintain index between
- *                successive calls for same subjectId.
+ * @param resource  resource for which AMS service is required.
+ * @param amsId     ID of the ams service for the given resource
  *
- * @retval  reference to @ref OicSecAmacl_t if Amacl is found, else NULL
+ * @retval
+ *  OC_STACK_OK     If Amacl found for the resource
+ *  OC_STACK_ERROR  If no Amacl found for the resource
  *
- * @note On the first call to @ref GetAmaclResourceData, savePtr should point to NULL
  */
-const OicSecAmacl_t* GetAmaclResourceData(const OicUuid_t* subjectId, OicSecAmacl_t **savePtr);
+OCStackResult AmaclGetAmsDeviceId(const char *resource, OicUuid_t *amsId);
 
 /**
  * This function converts Amacl data into JSON format.
diff --git a/resource/csdk/security/include/internal/amsmgr.h b/resource/csdk/security/include/internal/amsmgr.h
new file mode 100644 (file)
index 0000000..c83530f
--- /dev/null
@@ -0,0 +1,135 @@
+//******************************************************************
+//
+// Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef IOTVT_SRM_AMSMGR_H
+#define IOTVT_SRM_AMSMGR_H
+
+#include "ocstack.h"
+#include "logger.h"
+#include "policyengine.h"
+#include "securevirtualresourcetypes.h"
+#include "cainterface.h"
+#include <stdlib.h>
+#include <stdint.h>
+
+typedef struct PEContext PEContext_t;
+/**
+ * @brief   The AMS context..
+ */
+typedef struct AmsMgrContext
+{
+    OicUuid_t           amsDeviceId;  /**< DeviceID of the oic.sec.ams service. */
+    CAEndpoint_t        *endpoint;
+    CARequestInfo_t     *requestInfo;
+} AmsMgrContext_t;
+
+
+/**
+ * @brief This method updates AmsMgr context's endpoint & requestInfo
+ *
+ * @param context          Policy engine context.
+ * @param endpoint         CA Endpoint info of the requester
+ * @param requestInfo      CA RequestInfo of the requester
+ */
+OCStackResult UpdateAmsMgrContext(PEContext_t *context, const CAEndpoint_t *endpoint,
+                       const CARequestInfo_t *requestInfo);
+
+/**
+ *
+ * This method is called by PolicyEngine to Discover AMS service.
+ * It sends muticast discovery request such as
+ * /oic/sec/doxm?deviceid="AMSSrvcDeviceID" to discover AMS service
+ * with deviceId="AMSSrvcDeviceID"
+ *
+ * @param context   Policy engine context.
+ *
+ * @retval
+ *  OC_STACK_OK     If able to successfully send multicast discovery request.
+ *  OC_STACK_ERROR  If unable to successfully send multicast discovery request due to error.
+ *
+ */
+OCStackResult DiscoverAmsService(PEContext_t *context);
+
+
+/**
+ *
+ * This method sends unicast request to retrieve the secured port info of the
+ * discovered AMS service. It sends unicast discovery request such as
+ * /oic/res?rt="oic.sec.doxm" to the discovered AMS service
+ *
+ * @param context   Policy engine context.
+ *
+ * @retval
+ *  OC_STACK_OK     If able to successfully send unicast discovery request
+ *  OC_STACK_ERROR  If unable to successfully send unicast discovery request due to error
+ *
+ */
+OCStackResult SendUnicastSecurePortDiscovery(PEContext_t *context,OCDevAddr *devAddr,
+                                      OCConnectivityType connType);
+
+
+/**
+ *
+ * This method sends unicast request to AMS service to get ACL for
+ * the Subject and/or Resource. It sends unicast request such as
+ * /oic/sec/acl?sub="subjectId";rsrc="/a/led" to get the ACL for
+ * the subject & resource
+ *
+ * @param context   Policy engine context.
+ *
+ * @retval
+ *  OC_STACK_OK     If able to successfully send unicast ACL request
+ *  OC_STACK_ERROR  If unable to successfully send unicast ACL request due to error
+ *
+ */
+OCStackResult SendAclReq(PEContext_t *context, OCDevAddr *devAddr, OCConnectivityType connType,
+        uint16_t securedPort);
+
+
+/*
+ * Cleanup CARequestInfo_t object
+ * @param requestInfo        pointer to RequestInfo_t object
+ */
+void FreeCARequestInfo(CARequestInfo_t *requestInfo);
+
+
+/*
+ * This method is used by Policy engine to checks Amacl resource.
+ * If Amacl is found then it fills up context->amsMgrContext->amsDeviceId
+ * with amsID of the Amacl else leaves it empty.
+ *
+ * @param context   Policy engine context.
+ *
+ * @return          true if AMacl for the resource is found
+ *                  false if AMacl for the resource is not found
+ */
+bool FoundAmaclForRequest(PEContext_t *context);
+
+
+/*
+ * This method is used by Policy engine to process AMS request
+ * *
+ * @param context   Policy engine context.
+ *
+ * @return          None
+ */
+void ProcessAMSRequest(PEContext_t *context);
+
+#endif //IOTVT_SRM_AMSMGR_H
index a792bfa..ba40d68 100644 (file)
 #include "logger.h"
 #include "securevirtualresourcetypes.h"
 #include "cainterface.h"
+#include "amsmgr.h"
 #include <stdlib.h>
 #include <stdint.h>
 
+typedef struct AmsMgrContext AmsMgrContext_t;
+
 
 typedef enum PEState
 {
-    STOPPED = 0,
-    AWAITING_REQUEST,
-    BUSY
+    STOPPED = 0,              //Policy engine state machine is not running
+    AWAITING_REQUEST,         //Can process new request
+    AWAITING_AMS_RESPONSE,    //Can't process new request; waiting for AMS response
+    BUSY                      //Can't process new request as processing other requests
 } PEState_t;
 
+
 typedef struct PEContext
 {
     PEState_t   state;
-    OicUuid_t   *subject;
-    char        *resource;
+    OicUuid_t   subject;
+    char        resource[MAX_URI_LENGTH];
     uint16_t    permission;
     bool        matchingAclFound;
+    bool        amsProcessing;
     SRMAccessResponse_t retVal;
+    AmsMgrContext_t     *amsMgrContext;
 } PEContext_t;
 
 /**
@@ -85,4 +92,16 @@ void DeInitPolicyEngine(PEContext_t *context);
  */
 uint16_t GetPermissionFromCAMethod_t(const CAMethod_t method);
 
+
+/*
+ * This method reset Policy Engine context to default state and update
+ * it's state to @param state.
+ *
+ * @param context  Policy engine context.
+ * @param state    Set Policy engine state to this.
+ *
+ * @return         none
+ */
+void SetPolicyEngineState(PEContext_t *context, const PEState_t state);
+
 #endif //IOTVT_SRM_PE_H
index 750da2d..eb2643b 100644 (file)
@@ -21,6 +21,8 @@
 #ifndef SECURITYRESOURCEMANAGER_H_
 #define SECURITYRESOURCEMANAGER_H_
 
+#include "securevirtualresourcetypes.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -101,6 +103,14 @@ void SRMRegisterProvisioningResponseHandler(SPResponseCallback respHandler);
  */
 bool SRMIsSecurityResourceURI(const char* uri);
 
+/**
+ * @brief   Sends Response
+ * @param   resposeVal       SRMAccessResponse_t value
+ * @return  NONE
+ */
+void SRMSendResponse(SRMAccessResponse_t responseVal);
+
+
 #ifdef __cplusplus
 }
 #endif
index 2221c37..2533a78 100644 (file)
@@ -62,6 +62,8 @@ extern "C" {
 #define RESOURCE_NOT_FOUND_DEF        (1 << 4)
 #define POLICY_ENGINE_ERROR_DEF       (1 << 5)
 #define INVALID_PERIOD_DEF            (1 << 6)
+#define ACCESS_WAITING_DEF            (1 << 7)
+#define AMS_SERVICE_DEF               (1 << 8)
 #define REASON_MASK_DEF               (INSUFFICIENT_PERMISSION_DEF | \
                                        INVALID_PERIOD_DEF | \
                                        SUBJECT_NOT_FOUND_DEF | \
@@ -117,6 +119,10 @@ typedef enum
         | RESOURCE_NOT_FOUND_DEF,
     ACCESS_DENIED_POLICY_ENGINE_ERROR = ACCESS_DENIED_DEF
         | POLICY_ENGINE_ERROR_DEF,
+    ACCESS_WAITING_FOR_AMS = ACCESS_WAITING_DEF
+        | AMS_SERVICE_DEF,
+    ACCESS_DENIED_AMS_SERVICE_ERROR = ACCESS_DENIED
+        | AMS_SERVICE_DEF
 } SRMAccessResponse_t;
 
 /**
index 5515fc6..55058c7 100644 (file)
@@ -409,6 +409,7 @@ static bool UpdatePersistentStorage(const OicSecAcl_t *acl)
     }
     return false;
 }
+
 /*
  * This method removes ACE for the subject and resource from the ACL
  *
@@ -520,6 +521,7 @@ static bool GetSubjectFromQueryString(const char *query, OicUuid_t *subject)
 
     ParseQueryIterInit((unsigned char *)query, &parseIter);
 
+
     while(GetNextQuery(&parseIter))
     {
         if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_SUBJECT_NAME, parseIter.attrLen) == 0)
@@ -969,3 +971,34 @@ const OicSecAcl_t* GetACLResourceData(const OicUuid_t* subjectId, OicSecAcl_t **
     *savePtr = NULL;
     return NULL;
 }
+
+
+OCStackResult InstallNewACL(const char* newJsonStr)
+{
+    OCStackResult ret = OC_STACK_ERROR;
+
+    // Convert JSON ACL data into binary. This will also validate the ACL data received.
+    OicSecAcl_t* newAcl = JSONToAclBin(newJsonStr);
+
+    if (newAcl)
+    {
+        // Append the new ACL to existing ACL
+        LL_APPEND(gAcl, newAcl);
+
+        // Convert ACL data into JSON for update to persistent storage
+        char *jsonStr = BinToAclJSON(gAcl);
+        if (jsonStr)
+        {
+            cJSON *jsonAcl = cJSON_Parse(jsonStr);
+            OICFree(jsonStr);
+
+            if (jsonAcl)
+            {
+                ret = UpdateSVRDatabase(OIC_JSON_ACL_NAME, jsonAcl);
+            }
+            cJSON_Delete(jsonAcl);
+        }
+    }
+
+    return ret;
+}
index e0ba0b2..ff7bdb4 100644 (file)
@@ -401,3 +401,28 @@ void DeInitAmaclResource()
     DeleteAmaclList(gAmacl);
     gAmacl = NULL;
 }
+
+
+OCStackResult AmaclGetAmsDeviceId(const char *resource, OicUuid_t *amsDeviceId)
+{
+    OicSecAmacl_t *amacl = NULL;
+
+    VERIFY_NON_NULL(TAG, resource, ERROR);
+    VERIFY_NON_NULL(TAG, amsDeviceId, ERROR);
+
+    LL_FOREACH(gAmacl, amacl)
+    {
+        for(size_t i = 0; i < amacl->resourcesLen; i++)
+        {
+            if (strncmp((amacl->resources[i]), resource, strlen(amacl->resources[i])) == 0)
+            {
+                //Returning the ID of the first AMS service for the resource
+                memcpy(amsDeviceId, &amacl->amss[0], sizeof(*amsDeviceId));
+                return OC_STACK_OK;
+            }
+        }
+    }
+
+exit:
+    return OC_STACK_ERROR;
+}
diff --git a/resource/csdk/security/src/amsmgr.c b/resource/csdk/security/src/amsmgr.c
new file mode 100644 (file)
index 0000000..365cb10
--- /dev/null
@@ -0,0 +1,423 @@
+//******************************************************************
+//
+// Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include "oic_malloc.h"
+#include "amsmgr.h"
+#include "resourcemanager.h"
+#include "securevirtualresourcetypes.h"
+#include "srmresourcestrings.h"
+#include "logger.h"
+#include "ocrandom.h"
+#include "aclresource.h"
+#include "amaclresource.h"
+#include "srmutility.h"
+#include "base64.h"
+#include "secureresourcemanager.h"
+#include "doxmresource.h"
+#include "policyengine.h"
+#include "oic_string.h"
+#include "caremotehandler.h"
+#include <string.h>
+
+#define TAG "SRM-AMSMGR"
+
+
+ //Callback for AMS service multicast discovery request.
+static OCStackApplicationResult AmsMgrDiscoveryCallback(void *ctx, OCDoHandle handle,
+                         OCClientResponse * clientResponse);
+
+//Callback for unicast secured port discovery request.
+static OCStackApplicationResult SecurePortDiscoveryCallback(void *ctx, OCDoHandle handle,
+                         OCClientResponse * clientResponse);
+
+//Callback for unicast ACL request
+static OCStackApplicationResult AmsMgrAclReqCallback(void *ctx, OCDoHandle handle,
+    OCClientResponse * clientResponse);
+
+
+OCStackResult DiscoverAmsService(PEContext_t *context)
+{
+    OC_LOG(INFO, TAG, "IN DiscoverAmsService");
+
+    OCStackResult ret = OC_STACK_ERROR;
+    const char DOXM_DEVICEID_QUERY_FMT[] = "%s?%s=%s";
+    char uri[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {};
+    OCCallbackData cbData = {.context=NULL};
+    char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {};
+    uint32_t outLen = 0;
+    B64Result b64Ret;
+
+    VERIFY_NON_NULL(TAG, context, ERROR);
+    b64Ret = b64Encode(context->amsMgrContext->amsDeviceId.id,
+          sizeof(context->amsMgrContext->amsDeviceId.id), base64Buff, sizeof(base64Buff), &outLen);
+    VERIFY_SUCCESS(TAG, B64_OK == b64Ret, ERROR);
+    snprintf(uri, sizeof(uri), DOXM_DEVICEID_QUERY_FMT, OIC_RSRC_DOXM_URI,
+                                       OIC_JSON_DEVICE_ID_NAME, base64Buff);
+
+    cbData.cb = &AmsMgrDiscoveryCallback;
+    cbData.context = (void*)context;
+
+    /* TODO
+     * If no good response was received for this discovery request,
+     * PE would be blocked forever waiting for AMS service to respond with the ACE.
+     * Need logic to reset the PE state and send ACCESS_DENIED response,
+     * when discovery response from AMS service is not received within certain time.
+     */
+    OC_LOG_V(INFO, TAG,"AMS Manager Sending Multicast Discovery with URI = %s", uri);
+    ret = OCDoResource(NULL, OC_REST_DISCOVER, uri, NULL, NULL,
+                       CT_DEFAULT, OC_LOW_QOS, &cbData, NULL, 0);
+
+exit:
+    OC_LOG(INFO, TAG, "Leaving DiscoverAmsService");
+    return ret;
+}
+
+
+static OCStackApplicationResult AmsMgrDiscoveryCallback(void *ctx, OCDoHandle handle,
+                         OCClientResponse * clientResponse)
+{
+    OC_LOG_V(INFO, TAG, "%s Begin", __func__ );
+
+    if (!ctx ||
+        !clientResponse ||
+        !clientResponse->payload||
+        (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type)||
+        (OC_STACK_OK != clientResponse->result))
+    {
+        OC_LOG_V(ERROR, TAG, "%s Invalid Response ", __func__);
+        return OC_STACK_KEEP_TRANSACTION;
+    }
+
+    (void)handle;
+    PEContext_t *context = (PEContext_t *) ctx;
+    if (context->state != AWAITING_AMS_RESPONSE)
+    {
+        OC_LOG_V(ERROR, TAG, "%s Invalid PE State ", __func__);
+        return OC_STACK_DELETE_TRANSACTION;
+    }
+
+    OicSecDoxm_t *doxm = NULL;
+    OC_LOG_V(INFO, TAG, "Doxm DeviceId Discovery response = %s\n",
+          ((OCSecurityPayload*)clientResponse->payload)->securityData);
+    doxm = JSONToDoxmBin(((OCSecurityPayload*)clientResponse->payload)->securityData);
+
+    //As doxm is NULL amsmgr can't test if response from trusted AMS service
+    //so keep the transaction.
+    if(NULL == doxm)
+    {
+        OC_LOG_V(ERROR, TAG, "%s : Unable to convert JSON to Binary",__func__);
+        return OC_STACK_KEEP_TRANSACTION;
+    }
+
+    OicUuid_t deviceId = {.id={}};
+    memcpy(&deviceId, &doxm->deviceID, sizeof(deviceId));
+    OICFree(doxm);
+
+    /* TODO : By assuming that the first response received is the actual
+     * AMS service, a 'bad device' can cause DoS attack.
+     */
+    if (memcmp(&context->amsMgrContext->amsDeviceId, &deviceId,
+            sizeof(context->amsMgrContext->amsDeviceId)) == 0)
+    {
+        OC_LOG(INFO, TAG, "AMS Manager Sending unicast discovery to get secured port info");
+        //Sending Unicast discovery to get secure port information
+        if(OC_STACK_OK == SendUnicastSecurePortDiscovery(context, &clientResponse->devAddr,
+                clientResponse->connType))
+        {
+            context->retVal = ACCESS_WAITING_FOR_AMS;
+            return OC_STACK_DELETE_TRANSACTION;
+        }
+    }
+    context->retVal = ACCESS_DENIED_AMS_SERVICE_ERROR;
+    SRMSendResponse(context->retVal);
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+
+OCStackResult SendUnicastSecurePortDiscovery(PEContext_t *context,OCDevAddr *devAddr,
+                                      OCConnectivityType connType)
+{
+    OC_LOG(INFO, TAG, "IN SendUnicastSecurePortDiscovery");
+
+    const char RES_DOXM_QUERY_FMT[] = "%s?%s=%s";
+    OCCallbackData cbData = {.context=NULL};
+    char uri[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {};
+    snprintf(uri, sizeof(uri), RES_DOXM_QUERY_FMT, OC_RSRVD_WELL_KNOWN_URI,
+            OC_RSRVD_RESOURCE_TYPE, OIC_RSRC_TYPE_SEC_DOXM);
+
+    cbData.cb = &SecurePortDiscoveryCallback;
+    cbData.context = context;
+
+    OC_LOG_V(INFO, TAG, "AMS Manager Sending Unicast Discovery with URI = %s", uri);
+
+    return  OCDoResource(NULL, OC_REST_DISCOVER, uri, devAddr, NULL,
+                         connType, OC_LOW_QOS, &cbData, NULL, 0);
+}
+
+static OCStackApplicationResult SecurePortDiscoveryCallback(void *ctx, OCDoHandle handle,
+                         OCClientResponse * clientResponse)
+{
+    OC_LOG(INFO, TAG, "In SecurePortDiscoveryCallback");
+
+    if (!ctx ||
+        !clientResponse ||
+        !clientResponse->payload||
+        (PAYLOAD_TYPE_DISCOVERY != clientResponse->payload->type)||
+        (OC_STACK_OK != clientResponse->result))
+        {
+            OC_LOG_V(ERROR, TAG, "%s Invalid Response ", __func__);
+            SRMSendResponse(ACCESS_DENIED_AMS_SERVICE_ERROR);
+            return OC_STACK_DELETE_TRANSACTION;
+        }
+
+    PEContext_t *context = (PEContext_t *) ctx;
+    (void)handle;
+    if (context->state != AWAITING_AMS_RESPONSE)
+    {
+        OC_LOG_V(ERROR, TAG, "%s Invalid PE State ", __func__);
+        context->retVal = ACCESS_DENIED_AMS_SERVICE_ERROR;
+        SRMSendResponse(context->retVal);
+        return OC_STACK_DELETE_TRANSACTION;
+    }
+    OCResourcePayload* resPayload = ((OCDiscoveryPayload*)clientResponse->payload)->resources;
+
+    //Verifying if the ID of the sender is an AMS service that this device trusts.
+    if(memcmp(context->amsMgrContext->amsDeviceId.id, resPayload->sid,
+                    sizeof(context->amsMgrContext->amsDeviceId.id)) != 0)
+    {
+        context->retVal = ACCESS_DENIED_AMS_SERVICE_ERROR;
+        SRMSendResponse(context->retVal);
+        return OC_STACK_DELETE_TRANSACTION;
+    }
+
+    if (resPayload && resPayload->secure)
+    {
+        if(OC_STACK_OK == SendAclReq(context, &clientResponse->devAddr, clientResponse->connType,
+                resPayload->port))
+        {
+            return OC_STACK_DELETE_TRANSACTION;
+        }
+    }
+    OC_LOG(INFO, TAG, "Can not find secure port information");
+    context->retVal = ACCESS_DENIED_AMS_SERVICE_ERROR;
+    SRMSendResponse(context->retVal);
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+
+OCStackResult SendAclReq(PEContext_t *context, OCDevAddr *devAddr, OCConnectivityType connType,
+        uint16_t securedPort)
+{
+    OCStackResult ret = OC_STACK_ERROR;
+    const char GET_ACE_QUERY_FMT[] = "%s?%s=%s;%s=%s";
+    char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {};
+    uint32_t outLen = 0;
+    char uri[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {};
+    OCCallbackData cbData = {.context=NULL};
+    OCDevAddr destAddr = {.adapter = OC_ADAPTER_IP};
+    B64Result b64Ret;
+
+    VERIFY_NON_NULL(TAG, context, ERROR);
+    VERIFY_NON_NULL(TAG, devAddr, ERROR);
+
+    b64Ret = b64Encode(context->subject.id, sizeof(context->subject.id),
+                       base64Buff, sizeof(base64Buff), &outLen);
+    VERIFY_SUCCESS(TAG, B64_OK == b64Ret, ERROR);
+
+    snprintf(uri, sizeof(uri), GET_ACE_QUERY_FMT, OIC_RSRC_ACL_URI,
+                                    OIC_JSON_SUBJECT_NAME, base64Buff,
+                                    OIC_JSON_RESOURCES_NAME, context->resource);
+
+    cbData.cb = &AmsMgrAclReqCallback;
+    cbData.context = context;
+
+    destAddr = *devAddr;
+    //update port info
+    destAddr.flags = (OCTransportFlags)(destAddr.flags | OC_FLAG_SECURE);
+    destAddr.port = securedPort;
+
+    OC_LOG_V(INFO, TAG, "AMS Manager Sending Unicast ACL request with URI = %s", uri);
+    ret = OCDoResource(NULL, OC_REST_GET, uri, &destAddr, NULL,
+            connType, OC_LOW_QOS, &cbData, NULL, 0);
+
+exit:
+    OC_LOG_V(INFO, TAG, "%s returns %d ", __func__, ret);
+    return ret;
+}
+
+
+static OCStackApplicationResult AmsMgrAclReqCallback(void *ctx, OCDoHandle handle,
+    OCClientResponse * clientResponse)
+{
+    OC_LOG_V(INFO, TAG, "%s Begin", __func__ );
+
+    (void)handle;
+    PEContext_t *context = (PEContext_t *) ctx;
+    SRMAccessResponse_t rsps;
+
+    if (!ctx ||
+        !clientResponse ||
+        !clientResponse->payload||
+        (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type) ||
+        (clientResponse->result != OC_STACK_OK))
+    {
+        SRMSendResponse(ACCESS_DENIED_AMS_SERVICE_ERROR);
+        goto exit;
+    }
+
+    if (context->state != AWAITING_AMS_RESPONSE)
+    {
+        OC_LOG_V(ERROR, TAG, "%s Invalid State ", __func__);
+        context->retVal = ACCESS_DENIED_AMS_SERVICE_ERROR;
+        SRMSendResponse(context->retVal);
+        return OC_STACK_DELETE_TRANSACTION;
+    }
+
+    // Verify before installing ACL if the ID of the sender of this ACL is an AMS
+    //service that this device trusts.
+    rsps = ACCESS_DENIED;
+    if((UUID_LENGTH == clientResponse->identity.id_length) &&
+        memcmp(context->amsMgrContext->amsDeviceId.id, clientResponse->identity.id,
+                       sizeof(context->amsMgrContext->amsDeviceId.id)) == 0)
+    {
+        OCStackResult ret =
+                InstallNewACL(((OCSecurityPayload*)clientResponse->payload)->securityData);
+        VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
+
+        OC_LOG_V(INFO, TAG, "%s : Calling checkPermission", __func__);
+        rsps = CheckPermission(context, &context->subject, context->resource, context->permission);
+        VERIFY_SUCCESS(TAG, (true == IsAccessGranted(rsps)), ERROR);
+
+        OC_LOG_V(INFO, TAG, "%sAccess granted, Calling SRMCallCARequestHandler", __func__);
+        context->retVal = ACCESS_GRANTED;
+        SRMSendResponse(context->retVal);
+        return OC_STACK_DELETE_TRANSACTION;
+    }
+
+exit:
+    context->retVal = ACCESS_DENIED_AMS_SERVICE_ERROR;
+    SRMSendResponse(context->retVal);
+    FreeCARequestInfo(context->amsMgrContext->requestInfo);
+    OICFree(context->amsMgrContext->endpoint);
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+
+OCStackResult UpdateAmsMgrContext(PEContext_t *context, const CAEndpoint_t *endpoint,
+                        const CARequestInfo_t *requestInfo)
+{
+    OCStackResult ret = OC_STACK_ERROR;
+
+    //The AmsMgr context endpoint and requestInfo will be free from ,
+    //AmsMgrAclReqCallback function
+    if(context->amsMgrContext->endpoint)
+    {
+        OICFree(context->amsMgrContext->endpoint);
+        context->amsMgrContext->endpoint = NULL;
+    }
+    context->amsMgrContext->endpoint = (CAEndpoint_t *)OICCalloc(1, sizeof(CAEndpoint_t ));
+    VERIFY_NON_NULL(TAG, context->amsMgrContext->endpoint, ERROR);
+    *context->amsMgrContext->endpoint = *endpoint;
+
+    if(context->amsMgrContext->requestInfo)
+    {
+        FreeCARequestInfo(context->amsMgrContext->requestInfo);
+        context->amsMgrContext->requestInfo = NULL;
+    }
+    context->amsMgrContext->requestInfo = CACloneRequestInfo(requestInfo);
+    VERIFY_NON_NULL(TAG, context->amsMgrContext->requestInfo, ERROR);
+    ret = OC_STACK_OK;
+exit:
+    return ret;
+}
+
+void FreeCARequestInfo(CARequestInfo_t *requestInfo)
+{
+    OICFree(requestInfo->info.token);
+    OICFree(requestInfo->info.options);
+    OICFree(requestInfo->info.payload);
+    OICFree(requestInfo->info.resourceUri);
+    OICFree(requestInfo);
+}
+
+
+//This method checks for Amacl resource. If Amacl is found then it fills up
+//context->amsMgrContext->amsDeviceId with amsID of the Amacl else leaves it empty.
+bool FoundAmaclForRequest(PEContext_t *context)
+{
+    OC_LOG_V(INFO, TAG, "%s:no ACL found. Searching for AMACL",__func__);
+
+    bool ret = false;
+    VERIFY_NON_NULL(TAG, context, ERROR);
+    memset(&context->amsMgrContext->amsDeviceId, 0, sizeof(context->amsMgrContext->amsDeviceId));
+
+    //Call amacl resource function to get the AMS service deviceID for the resource
+    if(OC_STACK_OK == AmaclGetAmsDeviceId(context->resource, &context->amsMgrContext->amsDeviceId))
+    {
+        OC_LOG_V(INFO, TAG, "%s:AMACL found for the requested resource %s",
+                __func__, context->resource);
+        ret = true;
+    }
+    else
+    {
+        OC_LOG_V(INFO, TAG, "%s:AMACL found for the requested resource %s",
+                __func__, context->resource);
+        ret = false;
+    }
+
+ exit:
+     return ret;
+}
+
+
+void ProcessAMSRequest(PEContext_t *context)
+{
+    OicUuid_t  emptyUuid = {.id={}};
+    OC_LOG_V(INFO, TAG, "Entering %s", __func__);
+    if(NULL != context)
+    {
+        if((false == context->matchingAclFound) && (false == context->amsProcessing))
+        {
+            context->amsProcessing = true;
+
+            //Checking if context AMS deviceId is empty
+            if(memcmp(&context->amsMgrContext->amsDeviceId, &emptyUuid, sizeof(OicUuid_t)) != 0 )
+            {
+                if(OC_STACK_OK == DiscoverAmsService(context))
+                {
+                    context->retVal = ACCESS_WAITING_FOR_AMS;
+                }
+                else
+                {
+                    context->retVal = ACCESS_DENIED_AMS_SERVICE_ERROR;
+                }
+            }
+        }
+    }
+    else
+    {
+        OC_LOG_V(INFO, TAG, "Leaving %s(context is NULL)", __func__);
+    }
+
+    if(ACCESS_WAITING_FOR_AMS == context->retVal )
+    {
+        OC_LOG_V(INFO, TAG, "Leaving %s(WAITING_FOR_AMS)", __func__);
+    }
+}
index 00fe55b..ff9a415 100644 (file)
@@ -20,6 +20,7 @@
 
 #include "oic_malloc.h"
 #include "policyengine.h"
+#include "amsmgr.h"
 #include "resourcemanager.h"
 #include "securevirtualresourcetypes.h"
 #include "srmresourcestrings.h"
@@ -78,20 +79,19 @@ bool UuidCmp(OicUuid_t *firstId, OicUuid_t *secondId)
     return true;
 }
 
-
 /**
  * Set the state and clear other stateful context vars.
  */
 void SetPolicyEngineState(PEContext_t *context, const PEState_t state)
 {
     // Clear stateful context variables.
-    OICFree(context->subject);
-    context->subject = NULL;
-    OICFree(context->resource);
-    context->resource = NULL;
+    memset(&context->subject, 0, sizeof(context->subject));
+    memset(&context->resource, 0, sizeof(context->resource));
     context->permission = 0x0;
     context->matchingAclFound = false;
+    context->amsProcessing = false;
     context->retVal = ACCESS_DENIED_POLICY_ENGINE_ERROR;
+    memset(context->amsMgrContext, 0, sizeof(AmsMgrContext_t));
 
     // Set state.
     context->state = state;
@@ -109,12 +109,21 @@ bool IsRequestFromDevOwner(PEContext_t *context)
 
     if(OC_STACK_OK == GetDoxmDevOwnerId(&owner))
     {
-        retVal = UuidCmp(context->subject, &owner);
+        retVal = UuidCmp(&context->subject, &owner);
     }
 
     return retVal;
 }
 
+
+inline static bool IsRequestSubjectEmpty(PEContext_t *context)
+{
+    OicUuid_t emptySubject = {.id={}};
+    return (memcmp(&context->subject, &emptySubject, sizeof(OicUuid_t)) == 0) ?
+            true : false;
+}
+
+
 /**
  * Bitwise check to see if 'permission' contains 'request'.
  * @param   permission  The allowed CRUDN permission.
@@ -162,31 +171,21 @@ void CopyParamsToContext(
 {
     size_t length = 0;
 
-    // Free any existing subject.
-    OICFree(context->subject);
-    // Copy the subjectId into context.
-    context->subject = (OicUuid_t*)OICMalloc(sizeof(OicUuid_t));
-    VERIFY_NON_NULL(TAG, context->subject, ERROR);
-    memcpy(context->subject, subjectId, sizeof(OicUuid_t));
+     memcpy(&context->subject, subjectId, sizeof(OicUuid_t));
 
     // Copy the resource string into context.
     length = strlen(resource) + 1;
     if(0 < length)
     {
-        OICFree(context->resource);
-        context->resource = (char*)OICMalloc(length);
-        VERIFY_NON_NULL(TAG, context->resource, ERROR);
         strncpy(context->resource, resource, length);
         context->resource[length - 1] = '\0';
     }
 
     // Assign the permission field.
     context->permission = requestedPermission;
-
-exit:
-    return;
 }
 
+
 /**
  * Check whether 'resource' is getting accessed within the valid time period.
  * @param   acl         The ACL to check.
@@ -239,10 +238,13 @@ static bool IsAccessWithinValidTime(const OicSecAcl_t *acl)
     return false;
 }
 
+
 /**
  * Find ACLs containing context->subject.
  * Search each ACL for requested resource.
- * If resource found, check for context->permission.
+ * If resource found, check for context->permission and period validity.
+ * If the ACL is not found locally and AMACL for the resource is found
+ * then sends the request to AMS service for the ACL
  * Set context->retVal to result from first ACL found which contains
  * correct subject AND resource.
  *
@@ -258,22 +260,25 @@ void ProcessAccessRequest(PEContext_t *context)
 
         // Start out assuming subject not found.
         context->retVal = ACCESS_DENIED_SUBJECT_NOT_FOUND;
+
+        // Loop through all ACLs with a matching Subject searching for the right
+        // ACL for this request.
         do
         {
-            OC_LOG(INFO, TAG, "ProcessAccessRequest(): getting ACL...");
-            currentAcl = GetACLResourceData(context->subject, &savePtr);
+            OC_LOG_V(INFO, TAG, ("%s: getting ACL..."),__func__);
+            currentAcl = GetACLResourceData(&context->subject, &savePtr);
+
             if(NULL != currentAcl)
             {
                 // Found the subject, so how about resource?
-                OC_LOG(INFO, TAG, "ProcessAccessRequest(): \
-                    found ACL matching subject.");
+                OC_LOG_V(INFO, TAG, ("%s:found ACL matching subject"),__func__);
+
+                // Subject was found, so err changes to Rsrc not found for now.
                 context->retVal = ACCESS_DENIED_RESOURCE_NOT_FOUND;
-                OC_LOG(INFO, TAG, "ProcessAccessRequest(): \
-                    Searching for resource...");
+                OC_LOG_V(INFO, TAG, ("%s:Searching for resource..."),__func__);
                 if(IsResourceInAcl(context->resource, currentAcl))
                 {
-                    OC_LOG(INFO, TAG, "ProcessAccessRequest(): \
-                        found matching resource in ACL.");
+                    OC_LOG_V(INFO, TAG, ("%s:found matching resource in ACL"),__func__);
                     context->matchingAclFound = true;
 
                     // Found the resource, so it's down to valid period & permission.
@@ -281,8 +286,7 @@ void ProcessAccessRequest(PEContext_t *context)
                     if(IsAccessWithinValidTime(currentAcl))
                     {
                         context->retVal = ACCESS_DENIED_INSUFFICIENT_PERMISSION;
-                        if(IsPermissionAllowingRequest(currentAcl->permission, \
-                        context->permission))
+                        if(IsPermissionAllowingRequest(currentAcl->permission, context->permission))
                         {
                             context->retVal = ACCESS_GRANTED;
                         }
@@ -291,29 +295,24 @@ void ProcessAccessRequest(PEContext_t *context)
             }
             else
             {
-                OC_LOG(INFO, TAG, "ProcessAccessRequest(): \
-                    no ACL found matching subject .");
+                OC_LOG_V(INFO, TAG, ("%s:no ACL found matching subject for resource %s"),__func__, context->resource);
             }
         }
         while((NULL != currentAcl) && (false == context->matchingAclFound));
 
         if(IsAccessGranted(context->retVal))
         {
-            OC_LOG(INFO, TAG, "ProcessAccessRequest(): \
-                Leaving ProcessAccessRequest(ACCESS_GRANTED)");
+            OC_LOG_V(INFO, TAG, ("%s:Leaving ProcessAccessRequest(ACCESS_GRANTED)"), __func__);
         }
         else
         {
-            OC_LOG(INFO, TAG, "ProcessAccessRequest(): \
-                Leaving ProcessAccessRequest(ACCESS_DENIED)");
+            OC_LOG_V(INFO, TAG, ("%s:Leaving ProcessAccessRequest(ACCESS_DENIED)"), __func__);
         }
     }
     else
     {
-        OC_LOG(INFO, TAG, "ProcessAccessRequest(): \
-            Leaving ProcessAccessRequest(context is NULL)");
+        OC_LOG_V(INFO, TAG, ("%s:Leaving ProcessAccessRequest(context is NULL)"), __func__);
     }
-
 }
 
 /**
@@ -338,12 +337,16 @@ SRMAccessResponse_t CheckPermission(
     VERIFY_NON_NULL(TAG, resource, ERROR);
 
     // Each state machine context can only be processing one request at a time.
-    // Therefore if the context is not in AWAITING_REQUEST state, return error.
-    // Otherwise, change to BUSY state and begin processing request.
-    if(AWAITING_REQUEST == context->state)
+    // Therefore if the context is not in AWAITING_REQUEST or AWAITING_AMS_RESPONSE
+    // state, return error. Otherwise, change to BUSY state and begin processing request.
+    if(AWAITING_REQUEST == context->state || AWAITING_AMS_RESPONSE == context->state)
     {
-        SetPolicyEngineState(context, BUSY);
-        CopyParamsToContext(context, subjectId, resource, requestedPermission);
+        if(AWAITING_REQUEST == context->state)
+        {
+            SetPolicyEngineState(context, BUSY);
+            CopyParamsToContext(context, subjectId, resource, requestedPermission);
+        }
+
         // Before doing any processing, check if request coming
         // from DevOwner and if so, always GRANT.
         if(IsRequestFromDevOwner(context))
@@ -352,19 +355,46 @@ SRMAccessResponse_t CheckPermission(
         }
         else
         {
+            OicUuid_t saveSubject = {.id={}};
+            bool isSubEmpty = IsRequestSubjectEmpty(context);
+
             ProcessAccessRequest(context);
+
             // If matching ACL not found, and subject != wildcard, try wildcard.
             if((false == context->matchingAclFound) && \
-                (false == IsWildCardSubject(context->subject)))
+              (false == IsWildCardSubject(&context->subject)))
             {
-                OICFree(context->subject);
-                context->subject = (OicUuid_t*)OICMalloc(sizeof(OicUuid_t));
-                VERIFY_NON_NULL(TAG, context->subject, ERROR);
-                memcpy(context->subject, &WILDCARD_SUBJECT_ID,
-                    sizeof(OicUuid_t));
+                //Saving subject for Amacl check
+                memcpy(&saveSubject, &context->subject,sizeof(OicUuid_t));
+
+                //Setting context subject to WILDCARD_SUBJECT_ID
+                //TODO: change ProcessAccessRequest method signature to
+                //ProcessAccessRequest(context, subject) so that context
+                //subject is not tempered.
+                memset(&context->subject, 0, sizeof(context->subject));
+                memcpy(&context->subject, &WILDCARD_SUBJECT_ID,sizeof(OicUuid_t));
                 ProcessAccessRequest(context); // TODO anonymous subj can result
                                                // in confusing err code return.
             }
+
+            //No local ACE found for the request so checking Amacl resource
+            if(ACCESS_GRANTED != context->retVal)
+            {
+                //If subject is not empty then restore the original subject
+                //else keep the subject to WILDCARD_SUBJECT_ID
+                if(!isSubEmpty)
+                {
+                    memcpy(&context->subject, &saveSubject, sizeof(OicUuid_t));
+                }
+
+                //FoundAmaclForRequest method checks for Amacl and fills up
+                //context->amsMgrContext->amsDeviceId with the AMS deviceId
+                //if Amacl was found for the requested resource.
+                if(FoundAmaclForRequest(context))
+                {
+                    ProcessAMSRequest(context);
+                }
+            }
         }
     }
     else
@@ -374,7 +404,19 @@ SRMAccessResponse_t CheckPermission(
 
     // Capture retVal before resetting state for next request.
     retVal = context->retVal;
-    SetPolicyEngineState(context, AWAITING_REQUEST);
+
+    //Change the state of PE to "AWAITING_AMS_RESPONSE", if waiting
+    //for response from AMS service else to "AWAITING_REQUEST"
+    if(ACCESS_WAITING_FOR_AMS == retVal)
+    {
+        OC_LOG(INFO, TAG, ("Setting PE State to AWAITING_AMS_RESPONSE"));
+        context->state = AWAITING_AMS_RESPONSE;
+    }
+    else if(!context->amsProcessing)
+    {
+        OC_LOG(INFO, TAG, ("Resetting PE context and PE State to AWAITING_REQUEST"));
+        SetPolicyEngineState(context, AWAITING_REQUEST);
+    }
 
 exit:
     return retVal;
@@ -387,6 +429,7 @@ exit:
  */
 OCStackResult InitPolicyEngine(PEContext_t *context)
 {
+    context->amsMgrContext = (AmsMgrContext_t *)OICMalloc(sizeof(AmsMgrContext_t));
     if(NULL != context)
     {
         SetPolicyEngineState(context, AWAITING_REQUEST);
@@ -407,6 +450,6 @@ void DeInitPolicyEngine(PEContext_t *context)
     {
         SetPolicyEngineState(context, STOPPED);
     }
-
+    OICFree(context->amsMgrContext);
     return;
 }
index 434d4d6..13ff964 100644 (file)
 #include "ocstack.h"
 #include "logger.h"
 #include "cainterface.h"
-#include "secureresourcemanager.h"
 #include "resourcemanager.h"
 #include "credresource.h"
 #include "policyengine.h"
+#include "srmutility.h"
+#include "amsmgr.h"
 #include "oic_string.h"
+#include "oic_malloc.h"
+#include "securevirtualresourcetypes.h"
+#include "secureresourcemanager.h"
 #include "srmresourcestrings.h"
 
 #define TAG  "SRM"
@@ -60,6 +64,55 @@ void SRMRegisterProvisioningResponseHandler(SPResponseCallback respHandler)
 {
     gSPResponseHandler = respHandler;
 }
+
+
+static void SRMSendUnAuthorizedAccessresponse(PEContext_t *context)
+{
+    CAResponseInfo_t responseInfo = {.result = CA_EMPTY};
+    memcpy(&responseInfo.info, &(context->amsMgrContext->requestInfo->info),
+            sizeof(responseInfo.info));
+    responseInfo.info.payload = NULL;
+    responseInfo.result = CA_UNAUTHORIZED_REQ;
+    if (CA_STATUS_OK != CASendResponse(context->amsMgrContext->endpoint, &responseInfo))
+    {
+        OC_LOG(ERROR, TAG, "Failed in sending response to a unauthorized request!");
+    }
+    else
+    {
+        OC_LOG(INFO, TAG, "Succeed in sending response to a unauthorized request!");
+    }
+}
+
+
+void SRMSendResponse(SRMAccessResponse_t responseVal)
+{
+    OC_LOG(INFO, TAG, "Sending response to remote device");
+
+    if (IsAccessGranted(responseVal) && gRequestHandler)
+    {
+        OC_LOG_V(INFO, TAG, "%s : Access granted. Passing Request to RI layer", __func__);
+        if (!g_policyEngineContext.amsMgrContext->endpoint ||
+                !g_policyEngineContext.amsMgrContext->requestInfo)
+        {
+            OC_LOG_V(ERROR, TAG, "%s : Invalid arguments", __func__);
+            SRMSendUnAuthorizedAccessresponse(&g_policyEngineContext);
+            goto exit;
+        }
+        gRequestHandler(g_policyEngineContext.amsMgrContext->endpoint,
+                g_policyEngineContext.amsMgrContext->requestInfo);
+    }
+    else
+    {
+        OC_LOG_V(INFO, TAG, "%s : ACCESS_DENIED.", __func__);
+        SRMSendUnAuthorizedAccessresponse(&g_policyEngineContext);
+    }
+
+exit:
+    //Resting PE state to AWAITING_REQUEST
+    SetPolicyEngineState(&g_policyEngineContext, AWAITING_REQUEST);
+}
+
+
 /**
  * @brief   Handle the request from the SRM.
  * @param   endPoint       [IN] Endpoint object from which the response is received.
@@ -85,42 +138,55 @@ void SRMRequestHandler(const CAEndpoint_t *endPoint, const CARequestInfo_t *requ
     int position = 0;
     if (uri)
     {
+        //Skip query and pass the resource uri
         position = uri - requestInfo->info.resourceUri;
     }
-    if (position > MAX_URI_LENGTH)
+    else
+    {
+        position = strlen(requestInfo->info.resourceUri);
+    }
+    if (MAX_URI_LENGTH < position  || 0 > position)
     {
-        OC_LOG(ERROR, TAG, "URI length is too long");
+        OC_LOG(ERROR, TAG, "Incorrect URI length");
         return;
     }
     SRMAccessResponse_t response = ACCESS_DENIED;
-    if (position > 0)
+    char newUri[MAX_URI_LENGTH + 1];
+    OICStrcpyPartial(newUri, MAX_URI_LENGTH + 1, requestInfo->info.resourceUri, position);
+
+    //New request are only processed if the policy engine state is AWAITING_REQUEST.
+    if(AWAITING_REQUEST == g_policyEngineContext.state)
     {
-        char newUri[MAX_URI_LENGTH + 1];
-        OICStrcpyPartial(newUri, MAX_URI_LENGTH + 1, requestInfo->info.resourceUri, position);
-        //Skip query and pass the newUri.
-        response = CheckPermission(&g_policyEngineContext, &subjectId,
-                              newUri,
-                              GetPermissionFromCAMethod_t(requestInfo->method));
+        OC_LOG_V(INFO, TAG, "Processing request with uri, %s for method, %d",
+                requestInfo->info.resourceUri, requestInfo->method);
+        response = CheckPermission(&g_policyEngineContext, &subjectId, newUri,
+                GetPermissionFromCAMethod_t(requestInfo->method));
     }
     else
     {
-        //Pass resourceUri if there is no query info.
-        response = CheckPermission(&g_policyEngineContext, &subjectId,
-                              requestInfo->info.resourceUri,
-                              GetPermissionFromCAMethod_t(requestInfo->method));
+        OC_LOG_V(INFO, TAG, "PE state %d. Ignoring request with uri, %s for method, %d",
+                g_policyEngineContext.state, requestInfo->info.resourceUri, requestInfo->method);
     }
+
     if (IsAccessGranted(response) && gRequestHandler)
     {
         return (gRequestHandler(endPoint, requestInfo));
     }
 
-    // Form a 'access deny' or 'Error' response and send to peer
+    // Form a 'Error', 'slow response' or 'access deny' response and send to peer
     CAResponseInfo_t responseInfo = {.result = CA_EMPTY};
     memcpy(&responseInfo.info, &(requestInfo->info), sizeof(responseInfo.info));
     responseInfo.info.payload = NULL;
-    if (!gRequestHandler)
+
+    VERIFY_NON_NULL(TAG, gRequestHandler, ERROR);
+
+    if(ACCESS_WAITING_FOR_AMS == response)
     {
-        responseInfo.result = CA_INTERNAL_SERVER_ERROR;
+        OC_LOG(INFO, TAG, "Sending slow response");
+
+        UpdateAmsMgrContext(&g_policyEngineContext, endPoint, requestInfo);
+        responseInfo.result = CA_EMPTY;
+        responseInfo.info.type = CA_MSG_ACKNOWLEDGE;
     }
     else
     {
@@ -129,6 +195,7 @@ void SRMRequestHandler(const CAEndpoint_t *endPoint, const CARequestInfo_t *requ
          * CA_UNAUTHORIZED_REQ or CA_FORBIDDEN_REQ depending
          * upon SRMAccessResponseReasonCode_t
          */
+        OC_LOG(INFO, TAG, "Sending for regular response");
         responseInfo.result = CA_UNAUTHORIZED_REQ;
     }
 
@@ -136,6 +203,13 @@ void SRMRequestHandler(const CAEndpoint_t *endPoint, const CARequestInfo_t *requ
     {
         OC_LOG(ERROR, TAG, "Failed in sending response to a unauthorized request!");
     }
+    return;
+exit:
+    responseInfo.result = CA_INTERNAL_SERVER_ERROR;
+    if (CA_STATUS_OK != CASendResponse(endPoint, &responseInfo))
+    {
+        OC_LOG(ERROR, TAG, "Failed in sending response to a unauthorized request!");
+    }
 }
 
 /**
@@ -174,7 +248,8 @@ void SRMResponseHandler(const CAEndpoint_t *endPoint, const CAResponseInfo_t *re
  */
 void SRMErrorHandler(const CAEndpoint_t *endPoint, const CAErrorInfo_t *errorInfo)
 {
-    OC_LOG(INFO, TAG, "Received error from remote device");
+    OC_LOG_V(INFO, TAG, "Received error from remote device with result, %d for request uri, %s",
+            errorInfo->result, errorInfo->info.resourceUri);
     if (gErrorHandler)
     {
         gErrorHandler(endPoint, errorInfo);
index 8ad43a8..6890530 100644 (file)
@@ -102,8 +102,6 @@ TEST(PolicyEngineCore, DeInitPolicyEngine)
 {
     DeInitPolicyEngine(&g_peContext);
     EXPECT_EQ(STOPPED, g_peContext.state);
-    EXPECT_EQ(NULL, g_peContext.subject);
-    EXPECT_EQ(NULL, g_peContext.resource);
     EXPECT_EQ((uint16_t)0, g_peContext.permission);
     EXPECT_FALSE(g_peContext.matchingAclFound);
     EXPECT_EQ(ACCESS_DENIED_POLICY_ENGINE_ERROR, g_peContext.retVal);
diff --git a/resource/csdk/stack/samples/linux/secure/README b/resource/csdk/stack/samples/linux/secure/README
new file mode 100644 (file)
index 0000000..e874653
--- /dev/null
@@ -0,0 +1,14 @@
+Testing AMS service:
+1. Copy subjectID ("NDQ0NDMzMzMyMjIyMTExMQ==") of ACE with resource "/a/led" from AMS service 
+   database file, "oic_amss_db.json" into client Doxm resource deviceID located in file 
+   "oic_svr_client.json".
+2. Start ocserverbasicops
+3. start ocamsservice
+4. Start occlientbasicops
+
+
+Expected Result:
+1. New ACE with subjectID="NDQ0NDMzMzMyMjIyMTExMQ==" and rsrc="/a/led/" will be appended to the
+   server ACL resource in file "oic_svr_db_server.json".
+2. GET request made by occlientbasicops will be received successfully
+3. PUT reuest will received with result "OC_STACK_UNAUTHORIZED_REQ"
index 038c998..db10b49 100644 (file)
@@ -66,8 +66,9 @@ samples_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
 
 ocserverbasicops = samples_env.Program('ocserverbasicops', ['common.cpp', 'ocserverbasicops.cpp'])
 occlientbasicops = samples_env.Program('occlientbasicops', ['common.cpp', 'occlientbasicops.cpp'])
+ocamsservice = samples_env.Program('ocamsservice', ['common.cpp', 'ocamsservice.cpp'])
 
-Alias("samples", [ocserverbasicops, occlientbasicops])
+Alias("samples", [ocserverbasicops, occlientbasicops, ocamsservice])
 
 env.AppendTarget('samples')
 
@@ -79,4 +80,6 @@ samples_env.Alias("install", samples_env.Install( sec_samples_build_dir,
     sec_samples_src_dir + 'oic_svr_db_server.json'))
 samples_env.Alias("install", samples_env.Install( sec_samples_build_dir,
     sec_samples_src_dir + 'oic_svr_db_client.json'))
+samples_env.Alias("install", samples_env.Install( sec_samples_build_dir,
+    sec_samples_src_dir + 'oic_amss_db.json'))
 
diff --git a/resource/csdk/stack/samples/linux/secure/ocamsservice.cpp b/resource/csdk/stack/samples/linux/secure/ocamsservice.cpp
new file mode 100644 (file)
index 0000000..c22d371
--- /dev/null
@@ -0,0 +1,76 @@
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <pthread.h>
+#include "ocstack.h"
+#include "logger.h"
+#include "common.h"
+
+#define TAG  PCF("SRM-AMSS")
+
+int gQuitFlag = 0;
+
+//AMS service database, hold AMS service Identity and
+//the PSK credentials of trusted devices
+static char AMSS_DB_FILE[] = "oic_amss_db.json";
+
+/* SIGINT handler: set gQuitFlag to 1 for graceful termination */
+void handleSigInt(int signum)
+{
+    if (signum == SIGINT)
+    {
+        gQuitFlag = 1;
+    }
+}
+
+FILE* service_fopen(const char *path, const char *mode)
+{
+    (void)path;
+    return fopen(AMSS_DB_FILE, mode);
+}
+
+int main(int /*argc*/, char* /*argv*/[])
+{
+    struct timespec timeout;
+
+    OC_LOG(DEBUG, TAG, "OCAMS service is starting...");
+
+    // Initialize Persistent Storage for SVR database
+    OCPersistentStorage ps = { service_fopen, fread, fwrite, fclose, unlink };
+    OCRegisterPersistentStorageHandler(&ps);
+
+    if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "OCStack init error");
+        return 0;
+    }
+
+    timeout.tv_sec  = 0;
+    timeout.tv_nsec = 100000000L;
+
+    // Break from loop with Ctrl-C
+    OC_LOG(INFO, TAG, "Entering ocamsservice main loop...");
+    signal(SIGINT, handleSigInt);
+    while (!gQuitFlag)
+    {
+        if (OCProcess() != OC_STACK_OK)
+        {
+            OC_LOG(ERROR, TAG, "OCStack process error");
+            return 0;
+        }
+        nanosleep(&timeout, NULL);
+    }
+
+    OC_LOG(INFO, TAG, "Exiting ocamsservice main loop...");
+
+    if (OCStop() != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "OCStack process error");
+    }
+
+    return 0;
+}
diff --git a/resource/csdk/stack/samples/linux/secure/oic_amss_db.json b/resource/csdk/stack/samples/linux/secure/oic_amss_db.json
new file mode 100644 (file)
index 0000000..9543a87
--- /dev/null
@@ -0,0 +1,64 @@
+{
+    "acl": [
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/res",
+                "/oic/d",
+                "/oic/p",
+                "/oic/res/types/d",
+                "/oic/ad",
+                "/oic/sec/acl",
+                "/oic/sec/amacl"
+                       ],
+                       "perms": 2,
+                       "ownrs" : ["MTExMTExMTExMTExMTExMQ=="]
+               },
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/sec/doxm",
+                "/oic/sec/pstat"
+             ],
+             "perms": 2,
+             "ownrs" : ["MTExMTExMTExMTExMTExMQ=="]
+        },
+        {
+            "sub": "MjIyMjIyMjIyMjIyMjIyMg==",
+            "rsrc": ["/oic/sec/acl",
+                      "/oic/sec/cred"],
+            "perms": 8,
+            "ownrs" : ["MjIyMjIyMjIyMjIyMjIyMg=="]
+        },
+        {
+            "sub": "NDQ0NDMzMzMyMjIyMTExMQ==",
+            "rsrc": ["/a/led"],
+            "perms": 6,
+            "ownrs" : ["MjIyMjIyMjIyMjIyMjIyMg=="]
+        }
+       ],
+       "pstat":        {
+               "isop": true,
+               "deviceid":     "ZGV2aWNlaWQAAAAAABhanw==",
+               "ch": 0,
+               "cm":   0,
+               "tm":   0,
+               "om":   3,
+               "sm":   [3]
+       },
+       "doxm": {
+               "oxm":  [0],
+               "oxmsel": 0,
+               "sct": 1,
+               "owned": true,
+               "deviceid":     "MTkxOTE5MTkxOTE5MTkxOQ==",
+               "ownr": "YWRtaW5EZXZpY2VVVUlEAA=="
+       },
+       "cred": [{
+               "credid": 1,
+               "sub": "MTExMTExMTExMTExMTExMQ==",
+               "credtyp": 1,
+               "pvdata": "QkJCQkJCQkJCQkJCQkJCQg==",
+        "ownrs" : ["MjIyMjIyMjIyMjIyMjIyMg=="]
+       }]
+}
index 4211ee3..9456b41 100644 (file)
             "ownrs" : ["MjIyMjIyMjIyMjIyMjIyMg=="]
         }
        ],
+       "amacl": [{
+               "rsrc" : ["/a/led"],
+               "amss" : ["MTkxOTE5MTkxOTE5MTkxOQ=="],
+               "ownrs" : ["MjIyMjIyMjIyMjIyMjIyMg=="]
+       }],
        "pstat":        {
                "isop": true,
                "deviceid":     "ZGV2aWNlaWQAAAAAABhanw==",
            "credtyp": 1,
            "pvdata": "QUFBQUFBQUFBQUFBQUFBQQ==",
         "ownrs" : ["MjIyMjIyMjIyMjIyMjIyMg=="]
+       },
+       {
+           "credid": 4,
+           "sub": "NDQ0NDMzMzMyMjIyMTExMQ==",
+           "credtyp": 1,
+           "pvdata": "QUFBQUFBQUFBQUFBQUFBQQ==",
+        "ownrs" : ["MjIyMjIyMjIyMjIyMjIyMg=="]
+       },
+       {
+           "credid": 5,
+           "sub": "MTkxOTE5MTkxOTE5MTkxOQ==",
+           "credtyp": 1,
+           "pvdata": "QkJCQkJCQkJCQkJCQkJCQg==",
+        "ownrs" : ["MjIyMjIyMjIyMjIyMjIyMg=="]
        }]
 }
index a8c259f..184a73a 100644 (file)
@@ -49,7 +49,7 @@ if target_os not in ['windows', 'winrt']:
        # Note: 'pthread' is in libc for android. On other platform, if use
        # new gcc(>4.9?) it isn't required, otherwise, it's required
        if target_os != 'android':
-               examples_env.AppendUnique(LIBS = ['-lpthread'])
+               examples_env.AppendUnique(LIBS = ['-lpthread', '-ldl'])
 
 examples_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
 examples_env.AppendUnique(RPATH = [env.get('BUILD_DIR')])
index 1ecb759..20f2a19 100644 (file)
@@ -47,7 +47,7 @@ provisiontests_env.PrependUnique(CPPPATH = [
                ])
 
 provisiontests_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-pthread'])
-provisiontests_env.AppendUnique(LIBS = ['-lpthread'])
+provisiontests_env.AppendUnique(LIBS = ['-lpthread', '-ldl'])
 provisiontests_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
 provisiontests_env.AppendUnique(LIBPATH = [src_dir + '/extlibs/gtest/gtest-1.7.0/lib/.libs'])
 provisiontests_env.PrependUnique(LIBS = [