Add an additional callback in security provisioning of easy setup
authorJihun Ha <jihun.ha@samsung.com>
Fri, 9 Dec 2016 06:08:54 +0000 (15:08 +0900)
committerUze Choi <uzchoi@samsung.com>
Wed, 14 Dec 2016 05:39:07 +0000 (05:39 +0000)
after secure resource is discovered.

Right after a target secure resource is discovered, Mediator may need to
confirm which ownership tranfer method is used or set a pre-configured pin
number for MOT use case.
For that, it adds an additional ESResult, ES_SECURE_RESOURCE_IS_DISCOVERED,
which indicates the event. And if some user inputs are needed, user can
pass its inputs as a form of ESOwnershipTransferData object which can store
an ownership transfer method to be used and pre-configured pin to be used
for a MOT case.

Note that, related APIs for MOT was merged
: https://gerrit.iotivity.org/gerrit/#/c/14221/

Change-Id: Ic17f50693a6c4073eb5208da861506230f817f0e
Signed-off-by: Jihun Ha <jihun.ha@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/15161
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Uze Choi <uzchoi@samsung.com>
(cherry picked from commit 80884027f52113cdeb2673877d2a3d338630e371)
Reviewed-on: https://gerrit.iotivity.org/gerrit/15467

service/easy-setup/inc/escommon.h
service/easy-setup/mediator/richsdk/inc/ESRichCommon.h
service/easy-setup/mediator/richsdk/inc/RemoteEnrollee.h
service/easy-setup/mediator/richsdk/src/EnrolleeSecurity.cpp
service/easy-setup/mediator/richsdk/src/EnrolleeSecurity.h
service/easy-setup/mediator/richsdk/src/RemoteEnrollee.cpp
service/easy-setup/sampleapp/enrollee/linux/oic_svr_db_server.dat
service/easy-setup/sampleapp/mediator/linux/richsdk_sample/SConscript
service/easy-setup/sampleapp/mediator/linux/richsdk_sample/mediator.cpp [moved from service/easy-setup/sampleapp/mediator/linux/richsdk_sample/mediator_cpp.cpp with 90% similarity]
service/easy-setup/sampleapp/mediator/linux/richsdk_sample/oic_svr_db_subclient.dat [new file with mode: 0644]
service/easy-setup/sampleapp/mediator/linux/richsdk_sample/submediator.cpp [new file with mode: 0755]

index c350109..51928b9 100755 (executable)
@@ -136,6 +136,11 @@ typedef enum
     ES_OK = 0,
 
     /**
+     * Secure resource is discovered.
+     */
+    ES_SECURE_RESOURCE_IS_DISCOVERED = 1,
+
+    /**
      * Enrollee discovery fails in cloud provisioning
      */
     ES_ENROLLEE_DISCOVERY_FAILURE = 11,
@@ -176,6 +181,16 @@ typedef enum
     ES_CERT_PROVISIONING_FAILURE,
 
     /**
+     * MOT method selection is failed
+     */
+    ES_MOT_METHOD_SELECTION_FAILURE,
+
+    /**
+     * A provisioning of Pre-configured pin number for MOT is failed
+     */
+    ES_PRE_CONFIG_PIN_PROVISIONING_FAILURE,
+
+    /**
      * Provisioning fails for some reason.
      */
     ES_ERROR = 255
index 41fc10c..0dac2fb 100755 (executable)
 #include "OCPlatform.h"
 #include "ocstack.h"
 #include "octypes.h"
+#ifdef __WITH_DTLS__
+#include "securevirtualresourcetypes.h"
+#include "OCProvisioningManager.hpp"
+#endif
 
 #include "escommon.h"
 
@@ -454,13 +458,48 @@ namespace OIC
             SecProvisioningStatus(string deviceUUID, ESResult result) :
                 m_devUUID(deviceUUID), m_result(result)
             {
+#ifdef __WITH_DTLS__
+                m_selectedOTMethod = OIC_JUST_WORKS;
+                m_isMOTEnabled = false;
+                m_isOwned = false;
+#endif
+            }
+#ifdef __WITH_DTLS__
+            SecProvisioningStatus(std::shared_ptr<OCSecureResource> resource, ESResult result) :
+                m_result(result)
+            {
+                m_isMOTEnabled = false;
+                if(resource.get() != nullptr)
+                {
+                    m_devUUID = resource->getDeviceID();
+                    m_isOwned = resource->getOwnedStatus();
+
+                    // TODO
+                    // When severAPIs in OCSecureResource for getting a list of supported methods or
+                    // status of MOT support, a code for setting this information will be implemeted.
+                    m_selectedOTMethod = OIC_JUST_WORKS;
+                }
+            }
+
+            OicSecOxm_t getSelectedOTMethod() const
+            {
+                return m_selectedOTMethod;
             }
 
-            const string getDeviceUUID()
+            bool isMOTEnabled() const
             {
-                return m_devUUID;
+                return m_isMOTEnabled;
             }
 
+            bool isOwnedDevice() const
+            {
+                return m_isOwned;
+            }
+#endif
+            const std::string getDeviceUUID()
+            {
+                return m_devUUID;
+            }
             /**
              * Get a result for about security provisioning is success or not.
              *
@@ -477,6 +516,11 @@ namespace OIC
         private:
             string m_devUUID;
             ESResult m_result;
+#ifdef __WITH_DTLS__
+            OicSecOxm_t m_selectedOTMethod;
+            bool m_isMOTEnabled;
+            bool m_isOwned;
+#endif
         };
 
         /**
@@ -854,6 +898,73 @@ namespace OIC
             ESResult m_result;
         };
 
+        class ESOwnershipTransferData
+        {
+        public:
+#ifdef __WITH_DTLS__
+            ESOwnershipTransferData() :
+                m_MOTMethod(OIC_JUST_WORKS), m_preconfiguredPin("")
+            {
+            }
+
+            ESOwnershipTransferData(const ESOwnershipTransferData& data) :
+                m_MOTMethod(data.getMOTMethod()),
+                m_preconfiguredPin(data.getPreConfiguredPin())
+            {
+            }
+
+            ESResult setMOTMethod(OicSecOxm_t method)
+            {
+#ifdef MULTIPLE_OWNER
+                if(OIC_RANDOM_DEVICE_PIN != method)
+                {
+                    return ES_ERROR;
+                }
+
+                m_MOTMethod = method;
+                return ES_OK;
+#else
+                (void) method;
+
+                return ES_ERROR;
+#endif
+            }
+
+            ESResult setMOTMethod(OicSecOxm_t method, const std::string& pin)
+            {
+#ifdef MULTIPLE_OWNER
+                if(OIC_PRECONFIG_PIN != method || pin.empty())
+                {
+                    return ES_ERROR;
+                }
+
+                m_preconfiguredPin = pin;
+                m_MOTMethod = method;
+                return ES_OK;
+#else
+                (void) method;
+                (void) pin;
+
+                return ES_ERROR;
+#endif
+            }
+
+            OicSecOxm_t getMOTMethod() const
+            {
+                return m_MOTMethod;
+            }
+
+            std::string getPreConfiguredPin() const
+            {
+                return m_preconfiguredPin;
+            }
+
+        private:
+            OicSecOxm_t m_MOTMethod;
+            std::string m_preconfiguredPin;
+#endif
+        };
+
         /**
          * Callback function definition for providing Enrollee status
          */
@@ -880,6 +991,14 @@ namespace OIC
         typedef function< void(shared_ptr<SecProvisioningStatus>) > SecurityProvStatusCb;
 
         /**
+         * Callback function definition for providing Enrollee security provisioning status.
+         * This callback is an overloaded version of SecurityProvStatusCb, which has
+         * ESOwnershipTransferData as a return value.
+         */
+        typedef function< ESOwnershipTransferData(shared_ptr<SecProvisioningStatus>) >
+                                                                    SecurityProvStatusCbWithOption;
+
+        /**
          * Callback definition to be invoked when the security stack expects a pin from application
          */
         typedef function< void(string&) > SecurityPinCb;
index 30ef55c..5f1008f 100755 (executable)
@@ -76,7 +76,7 @@ namespace OIC
              */
             void getConfiguration(const GetConfigurationStatusCb callback);
 
-             /**
+            /**
              * Do security provisioning such as ownership tranfer to Enrollee.
              *
              * @param callback will give the result if the security provisioning succeeds or fails for some reasons
@@ -88,6 +88,19 @@ namespace OIC
             void provisionSecurity(const SecurityProvStatusCb callback);
 
             /**
+             * Do security provisioning such as ownership tranfer to Enrollee which may require more
+             * specific user selections like a type of ownership transfer method or pre-configured
+             * pin number used to Pre-configured pin-based MOT.
+             *
+             * @param callback will give the result if the security provisioning succeeds or fails for some reasons.
+             *
+             * @throws ESBadRequestException If RemoteEnrollee device not created prior to this call.
+             *
+             * @see SecurityProvStatusCb
+             */
+            void provisionSecurity(const SecurityProvStatusCbWithOption callback);
+
+            /**
              * Provision WiFi AP information and device configuration to Enrollee
              * 1. WiFi AP information includes a SSID, password, auth type, and encryption type.
              * 2. Device configuration includes a language (IETF language tags) and country (ISO 3166-1 Alpha-2)
@@ -143,6 +156,8 @@ namespace OIC
                 (const std::shared_ptr< CloudPropProvisioningStatus > status) const;
             void securityStatusHandler
                 (const std::shared_ptr< SecProvisioningStatus > status) const;
+            ESOwnershipTransferData securityStatusWithOptionHandler
+                (const std::shared_ptr< SecProvisioningStatus > status) const;
 
         private:
             std::shared_ptr< OC::OCResource > m_ocResource;
@@ -157,6 +172,7 @@ namespace OIC
             std::condition_variable m_cond;
 
             SecurityProvStatusCb m_securityProvStatusCb;
+            SecurityProvStatusCbWithOption m_securityProvStatusCbWithOption;
             GetStatusCb m_getStatusCb;
             GetConfigurationStatusCb m_getConfigurationStatusCb;
             SecurityPinCb m_securityPinCb;
index da70c09..fac771a 100755 (executable)
@@ -65,6 +65,7 @@ namespace OIC
         {
             (void) secDbPath;
             m_ocResource = resource;
+            m_ownershipTransferData = {};
         }
 
         void EnrolleeSecurity::convertUUIDToString(const uint8_t uuid[UUID_SIZE],
@@ -150,6 +151,69 @@ namespace OIC
             }
         }
 
+#ifdef MULTIPLE_OWNER
+        void EnrolleeSecurity::SelectMOTMethodCB(PMResultList_t *result, int hasError)
+        {
+            OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "SelectMOTMethodCB IN");
+            if (hasError)
+            {
+                OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG,
+                                "selectMOTMethod API is failed with error %d", hasError);
+                MOTMethodProvResult = false;
+            }
+            else
+            {
+                OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "selectMOTMethod API is succeeded");
+                MOTMethodProvResult = true;
+            }
+
+            delete result;
+            m_cond.notify_all();
+        }
+
+        void EnrolleeSecurity::PreconfigPinProvCB(PMResultList_t *result, int hasError)
+        {
+            OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "PreconfigPinProvCB IN");
+            if (hasError)
+            {
+                OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG,
+                                "provisionPreconfPin API is failed with error %d", hasError);
+                PreConfigPinProvResult = false;
+            }
+            else
+            {
+                OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "provisionPreconfPin API is succeeded");
+                PreConfigPinProvResult = true;
+            }
+
+            delete result;
+            m_cond.notify_all();
+        }
+
+        void EnrolleeSecurity::MultipleOwnershipTransferCb(OC::PMResultList_t *result, int hasError)
+        {
+            OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "MultipleOwnershipTransferCb IN");
+            if (hasError)
+            {
+                OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "MultipleOwnershipTransferCb is failed with code(%d)", hasError);
+                OTMResult = false;
+                m_cond.notify_all();
+            }
+            else
+            {
+                OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "MultipleOwnershipTransfer is succeeded");
+                for (unsigned int i = 0; i < result->size(); i++)
+                {
+                    OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Result is = %d for device", result->at(i).res);
+                }
+
+                delete result;
+                OTMResult = true;
+                m_cond.notify_all();
+            }
+        }
+#endif
+
         void EnrolleeSecurity::ownershipTransferCb(OC::PMResultList_t *result, int hasError)
         {
             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "ownershipTransferCb IN");
@@ -165,13 +229,14 @@ namespace OIC
                 {
                     OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Result is = %d for device", result->at(i).res);
                 }
-                delete result;
                 OTMResult = true;
             }
+
+            delete result;
             m_cond.notify_all();
         }
 
-        ESResult EnrolleeSecurity::provisionOwnership()
+        ESResult EnrolleeSecurity::provisionOwnership(SecurityProvStatusCbWithOption callback)
         {
             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "provisionOwnership IN");
 
@@ -225,19 +290,33 @@ namespace OIC
                 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "SID: %s", m_securedResource->getDeviceID().c_str());
                 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Owned status: %d", m_securedResource->getOwnedStatus());
 
-                if (m_securedResource->getOwnedStatus()) // owned check logic
+                if(callback != NULL)
                 {
-                    if(isOwnedDeviceRegisteredInSVRDB())
+                    std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
+                             std::make_shared< SecProvisioningStatus >
+                                           (m_securedResource,
+                                           ESResult::ES_SECURE_RESOURCE_IS_DISCOVERED);
+                    m_ownershipTransferData = callback(securityProvisioningStatus);
+
+                    if(OIC_RANDOM_DEVICE_PIN == m_ownershipTransferData.getMOTMethod())
                     {
-                        OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG,
-                                "The found device is already owned by Mediator.(SUCCESS)");
-                        res = ESResult::ES_OK;
+                        OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Selected MOT Method: OIC_RANDOM_DEVICE_PIN");
                     }
-                    else
+#ifdef MULTIPLE_OWNER
+                    else if(OIC_PRECONFIG_PIN == m_ownershipTransferData.getMOTMethod())
                     {
-                        OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "The found device is not one in SVR DB");
-                        res = ESResult::ES_ERROR;
+                        OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Selected MOT Method: OIC_PRECONFIG_PIN");
+                        OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Pre-configured PIN: %s",
+                                            m_ownershipTransferData.getPreConfiguredPin().c_str());
                     }
+#endif
+                }
+
+                if(m_securedResource->getOwnedStatus() && isOwnedDeviceRegisteredInSVRDB()) // owned check logic
+                {
+                    OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG,
+                            "The found device is already owned by Mediator.(SUCCESS)");
+                    res = ESResult::ES_OK;
                     return res;
                 }
                 else // unowned check logic
@@ -273,23 +352,115 @@ namespace OIC
                         OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Removing device is succeeded.");
                     }
 
-                    res = performOwnershipTransfer();
-
-                    if(res != ESResult::ES_OK)
+                    if(!m_securedResource->getOwnedStatus())
                     {
-                        OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "Ownership-Transfer failed. (%d)", res);
-                        res = ESResult::ES_OWNERSHIP_TRANSFER_FAILURE;
-                        return res;
+                        res = performOwnershipTransfer();
+
+                        if(res != ESResult::ES_OK)
+                        {
+                            OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "Ownership-Transfer failed. (%d)", res);
+                            res = ESResult::ES_OWNERSHIP_TRANSFER_FAILURE;
+                            return res;
+                        }
+
+                        std::unique_lock<std::mutex> lck(m_mtx);
+                        m_cond.wait(lck);
+
+                        if(!OTMResult)
+                        {
+                            OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Ownership-Transfer failed.");
+                            res = ESResult::ES_OWNERSHIP_TRANSFER_FAILURE;
+                            return res;
+                        }
+#ifdef MULTIPLE_OWNER
+                        if( // m_securedResource->isMOTSupported() && //not provided, yet
+                            OIC_PRECONFIG_PIN == m_ownershipTransferData.getMOTMethod() &&
+                                !m_ownershipTransferData.getPreConfiguredPin().empty())
+                        {
+                            OC::ResultCallBack preconfigPinProvCB = std::bind(
+                                    &EnrolleeSecurity::PreconfigPinProvCB, this, std::placeholders::_1,
+                                    std::placeholders::_2);
+
+                            std::string pin = m_ownershipTransferData.getPreConfiguredPin();
+
+                            OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "provisionPreconfPin is called.");
+                            if(OC_STACK_OK != m_securedResource->provisionPreconfPin(
+                                                    pin.c_str(), pin.length(), preconfigPinProvCB))
+                            {
+                                OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "provisionPreconfPin API error");
+                                res = ESResult:: ES_PRE_CONFIG_PIN_PROVISIONING_FAILURE;
+                                return res;
+                            }
+
+                            m_cond.wait(lck);
+
+                            if(!PreConfigPinProvResult)
+                            {
+                                OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "provisionPreconfPin is failed.");
+                                res = ESResult:: ES_PRE_CONFIG_PIN_PROVISIONING_FAILURE;
+                                return res;
+                            }
+                        }
+
+                        if(// m_securedResource->isMOTSupported() && //not provided, yet
+                            OIC_PRECONFIG_PIN == m_ownershipTransferData.getMOTMethod() ||
+                            OIC_RANDOM_DEVICE_PIN == m_ownershipTransferData.getMOTMethod())
+                        {
+
+                            OC::ResultCallBack selectMOTMethodCB = std::bind(
+                                &EnrolleeSecurity::SelectMOTMethodCB, this, std::placeholders::_1,
+                                std::placeholders::_2);
+
+                            OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "selectMOTMethod is called.");
+                            if(OC_STACK_OK != m_securedResource->selectMOTMethod(
+                                                    m_ownershipTransferData.getMOTMethod(),
+                                                    selectMOTMethodCB))
+                            {
+                                OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "selectMOTMethod API error");
+                                res = ESResult:: ES_MOT_METHOD_SELECTION_FAILURE;
+                                return res;
+                            }
+
+                            m_cond.wait(lck);
+
+                            if(!MOTMethodProvResult)
+                            {
+                                OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "selectMOTMethod is failed.");
+                                res = ESResult:: ES_MOT_METHOD_SELECTION_FAILURE;
+                                return res;
+                            }
+                        }
+#endif
                     }
+#ifdef MULTIPLE_OWNER
+                    else
+                    {
+                        res = performMultipleOwnershipTransfer();
 
-                    std::unique_lock<std::mutex> lck(m_mtx);
-                    m_cond.wait(lck);
+                        if(res != ESResult::ES_OK)
+                        {
+                            OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "Multiple Ownership-Transfer failed. (%d)", res);
+                            res = ESResult::ES_OWNERSHIP_TRANSFER_FAILURE;
+                            return res;
+                        }
+
+                        std::unique_lock<std::mutex> lck(m_mtx);
+                        m_cond.wait(lck);
 
-                    if(!OTMResult)
+                        if(!OTMResult)
+                        {
+                            OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Multiple Ownership-Transfer failed.");
+                            res = ESResult::ES_OWNERSHIP_TRANSFER_FAILURE;
+                            return res;
+                        }
+                    }
+#else
+                    else
                     {
-                        OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Ownership-Transfer failed.");
-                        res = ESResult::ES_OWNERSHIP_TRANSFER_FAILURE;
+                        OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "The found device is already owned by other PT");
+                        res = ESResult::ES_ERROR;
                     }
+#endif
                 }
             }
             else
@@ -309,14 +480,11 @@ namespace OIC
             OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Transfering ownership for : %s ",
                     m_securedResource->getDeviceID().c_str());
 
-            //In case of random pin, argument should be inputPinCallback func.
-            // for justwork, not required(NULL)
-            OCSecure::setInputPinCallback(NULL);
-
             OC::ResultCallBack ownershipTransferCb = std::bind(
                     &EnrolleeSecurity::ownershipTransferCb, this, std::placeholders::_1,
                     std::placeholders::_2);
 
+            OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "doOwnershipTransfer is excuted");
             result = m_securedResource->doOwnershipTransfer(ownershipTransferCb);
             if (result != OC_STACK_OK)
             {
@@ -326,6 +494,48 @@ namespace OIC
             return ESResult::ES_OK;
         }
 
+#ifdef MULTIPLE_OWNER
+        ESResult EnrolleeSecurity::performMultipleOwnershipTransfer()
+        {
+            OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "performMultipleOwnershipTransfer IN.");
+
+            OCStackResult result = OC_STACK_ERROR;
+
+            OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Transfering sub-ownership for : %s ",
+                    m_securedResource->getDeviceID().c_str());
+
+            if( // m_securedResource->isMOTSupported() && //not provided, yet
+                    OIC_PRECONFIG_PIN == m_ownershipTransferData.getMOTMethod() &&
+                        !m_ownershipTransferData.getPreConfiguredPin().empty())
+            {
+                std::string pin = m_ownershipTransferData.getPreConfiguredPin();
+
+                result = m_securedResource->addPreconfigPIN(pin.c_str(), pin.length());
+                if(OC_STACK_OK != result)
+                {
+                    OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "addPreconfigPIN is failed");
+                    return ESResult::ES_ERROR;
+                }
+
+                OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Preconfig PIN : %s", pin.c_str());
+            }
+
+            OC::ResultCallBack multipleOwnershipTransferCb = std::bind(
+                        &EnrolleeSecurity::MultipleOwnershipTransferCb, this, std::placeholders::_1,
+                        std::placeholders::_2);
+
+            OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "doMultipleOwnershipTransfer is excuted");
+
+            result = m_securedResource->doMultipleOwnershipTransfer(multipleOwnershipTransferCb);
+            if(OC_STACK_OK != result)
+            {
+                OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "doMultipleOwnershipTransfer is failed");
+                return ESResult::ES_ERROR;
+            }
+            return ESResult::ES_OK;
+        }
+#endif
+
         void EnrolleeSecurity::removeDeviceWithUuidCB(OC::PMResultList_t *result, int hasError)
         {
             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "removeDeviceWithUuidCB IN");
index 0c4f8c3..76d0c8e 100755 (executable)
@@ -52,7 +52,7 @@ namespace OIC
         public:
             EnrolleeSecurity(std::shared_ptr< OC::OCResource > resource,
             const std::string secDbPath);
-            ESResult provisionOwnership();
+            ESResult provisionOwnership(SecurityProvStatusCbWithOption callback);
             std::string getUUID() const;
 
         private:
@@ -64,15 +64,25 @@ namespace OIC
             std::mutex m_mtx;
             std::condition_variable m_cond;
             std::atomic<bool> OTMResult;
+            std::atomic<bool> MOTMethodProvResult;
+            std::atomic<bool> PreConfigPinProvResult;
             std::atomic<bool> removeDeviceResult;
             std::atomic<bool> aclResult;
             std::atomic<bool> certResult;
 
             std::shared_ptr< OC::OCSecureResource > m_securedResource;
 
+            ESOwnershipTransferData m_ownershipTransferData;
+
             ESResult performOwnershipTransfer();
             bool isOwnedDeviceRegisteredInSVRDB();
             void removeDeviceWithUuidCB(OC::PMResultList_t *result, int hasError);
+#ifdef MULTIPLE_OWNER
+            ESResult performMultipleOwnershipTransfer();
+            void SelectMOTMethodCB(PMResultList_t *result, int hasError);
+            void PreconfigPinProvCB(PMResultList_t *result, int hasError);
+            void MultipleOwnershipTransferCb(OC::PMResultList_t *result, int hasError);
+#endif
             void ownershipTransferCb(OC::PMResultList_t *result, int hasError);
             void convertUUIDToString(const uint8_t uuid[UUID_SIZE],
                                                 std::string& uuidString);
index 15dbf43..c78ed96 100755 (executable)
@@ -73,6 +73,17 @@ namespace OIC
             OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "securityStatusHandlr OUT");
         }
 
+        ESOwnershipTransferData RemoteEnrollee::securityStatusWithOptionHandler(
+                const std::shared_ptr< SecProvisioningStatus > status) const
+        {
+            OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "securityStatusWithOptionHandler IN");
+            OIC_LOG_V(DEBUG, ES_REMOTE_ENROLLEE_TAG, "UUID = %s, ESResult = %d",
+                    status->getDeviceUUID().c_str(), status->getESResult());
+
+            OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "securityStatusWithOptionHandler OUT");
+            return m_securityProvStatusCbWithOption(status);
+        }
+
         void RemoteEnrollee::getStatusHandler(
                 const std::shared_ptr< GetEnrolleeStatus > status) const
         {
@@ -238,7 +249,7 @@ namespace OIC
                 m_enrolleeSecurity = std::make_shared <EnrolleeSecurity> (m_ocResource, "");
             }
 
-            res = m_enrolleeSecurity->provisionOwnership();
+            res = m_enrolleeSecurity->provisionOwnership(NULL);
 
             std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
                             std::make_shared< SecProvisioningStatus >(m_enrolleeSecurity->getUUID(), res);
@@ -259,6 +270,48 @@ namespace OIC
             OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "provisionSecurity OUT");
         }
 
+        void RemoteEnrollee::provisionSecurity(const SecurityProvStatusCbWithOption callback)
+        {
+            OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "provisionSecurity IN");
+#ifdef __WITH_DTLS__
+            ESResult res = ESResult::ES_ERROR;
+            if(!callback)
+            {
+                throw ESInvalidParameterException("Callback is empty");
+            }
+            m_securityProvStatusCbWithOption = callback;
+
+            SecurityProvStatusCbWithOption securityProvStatusCbWithOption = std::bind(
+                                    &RemoteEnrollee::securityStatusWithOptionHandler,
+                                    this,
+                                    std::placeholders::_1);
+
+            if(!m_enrolleeSecurity.get())
+            {
+                m_enrolleeSecurity = std::make_shared <EnrolleeSecurity> (m_ocResource, "");
+            }
+
+            res = m_enrolleeSecurity->provisionOwnership(securityProvStatusCbWithOption);
+
+            std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
+                            std::make_shared< SecProvisioningStatus >(m_enrolleeSecurity->getUUID(), res);
+            securityProvStatusCbWithOption(securityProvisioningStatus);
+            m_enrolleeSecurity.reset();
+#else
+            OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG,"Mediator is unsecured built.");
+
+            if(!callback)
+            {
+                throw ESInvalidParameterException("Callback is empty");
+            }
+            std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
+                     std::make_shared< SecProvisioningStatus >
+                                   ("", ESResult::ES_SEC_OPERATION_IS_NOT_SUPPORTED);
+            callback(securityProvisioningStatus);
+#endif
+            OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "provisionSecurity OUT");
+        }
+
         void RemoteEnrollee::getStatus(const GetStatusCb callback)
         {
             OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "getStatus IN");
@@ -381,13 +434,6 @@ namespace OIC
 
             m_cloudPropProvStatusCb = callback;
 
-            if(cloudProp.getAuthCode().empty() ||
-                cloudProp.getAuthProvider().empty() ||
-                cloudProp.getCiServer().empty())
-            {
-                throw ESBadRequestException ("Invalid Cloud Provisiong Info.");
-            }
-
             try
             {
                 initCloudResource();
index 82b4e40..ae81a11 100644 (file)
Binary files a/service/easy-setup/sampleapp/enrollee/linux/oic_svr_db_server.dat and b/service/easy-setup/sampleapp/enrollee/linux/oic_svr_db_server.dat differ
index 2f422a2..ccbc795 100644 (file)
@@ -66,13 +66,17 @@ mediator_env.PrependUnique(LIBS = ['ESMediatorRich', 'oc', 'octbstack', 'oc_logg
 if env.get('SECURED') == '1':
        mediator_env.PrependUnique(LIBS = ['ocpmapi', 'ocprovision'])
 
-mediator = mediator_env.Program('mediator_rich', 'mediator_cpp.cpp')
+mediator = mediator_env.Program('mediator', 'mediator.cpp')
+submediator = mediator_env.Program('submediator', 'submediator.cpp')
 
-i_mediator = mediator_env.Install(env.get('BUILD_DIR'), mediator)
+i_mediator = mediator_env.Install(env.get('BUILD_DIR'), [mediator, submediator])
 
 clientdat = mediator_env.Install(env.get('BUILD_DIR') + '/service/easy-setup/sampleapp/mediator/linux/richsdk_sample',
                                     env.get('SRC_DIR') + '/service/easy-setup/sampleapp/mediator/linux/richsdk_sample/oic_svr_db_client.dat')
 
+subclientdat = mediator_env.Install(env.get('BUILD_DIR') + '/service/easy-setup/sampleapp/mediator/linux/richsdk_sample',
+                                    env.get('SRC_DIR') + '/service/easy-setup/sampleapp/mediator/linux/richsdk_sample/oic_svr_db_subclient.dat')
 
-Alias('mediator_rich', [i_mediator, clientdat])
+
+Alias('mediator_rich', [i_mediator, clientdat, subclientdat])
 env.AppendTarget('mediator_rich')
@@ -24,6 +24,7 @@
 #include "OCPlatform.h"
 #include "OCApi.h"
 #include "OCProvisioningManager.hpp"
+#include "securevirtualresourcetypes.h"
 
 #include "EasySetup.h"
 #include "ESRichCommon.h"
@@ -88,18 +89,38 @@ void printStatus(EnrolleeStatus status)
     cout << "===========================================" << endl;
 }
 
-void provisionSecurityStatusCallback(std::shared_ptr<SecProvisioningStatus> secProvisioningStatus)
+ESOwnershipTransferData provisionSecurityStatusCallback(std::shared_ptr<SecProvisioningStatus> secProvisioningStatus)
 {
-    if(secProvisioningStatus->getESResult() != ES_OK)
+    cout << "provisionSecurityStatusCallback IN" << endl;
+    cout << "ESResult : " << secProvisioningStatus->getESResult() << std::endl;
+    cout << "Device ID : " << secProvisioningStatus->getDeviceUUID() << std::endl;
+
+    if(secProvisioningStatus->getESResult() == ES_SECURE_RESOURCE_IS_DISCOVERED)
     {
-      cout << "provisionSecurity is failed." << endl;
-      return;
+#if defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
+        cout << "Owned Status : " << secProvisioningStatus->isOwnedDevice() << std::endl;
+        cout << "OT Method : " << secProvisioningStatus->getSelectedOTMethod() << std::endl;
+
+        // TEST
+        ESOwnershipTransferData OTData;
+        OTData.setMOTMethod(OIC_PRECONFIG_PIN, "12345678");
+
+        cout << "Enter!" << std::endl;
+        getchar();
+
+        return OTData;
+#endif
+    }
+    else if(secProvisioningStatus->getESResult() == ES_OK)
+    {
+        cout << "provisionSecurity is success." << std::endl;
     }
     else
     {
-      cout << "provisionSecurity is success." << endl;
-      cout << "uuid : " << secProvisioningStatus->getDeviceUUID()<< endl;
+        cout << "provisionSecurity is failed." << endl;
     }
+
+    return {};
 }
 
 void provisionSecurity()
@@ -112,7 +133,7 @@ void provisionSecurity()
 
     try
     {
-        remoteEnrollee->provisionSecurity(provisionSecurityStatusCallback);
+        remoteEnrollee->provisionSecurity((SecurityProvStatusCbWithOption)provisionSecurityStatusCallback);
     }
     catch (OCException &e)
     {
diff --git a/service/easy-setup/sampleapp/mediator/linux/richsdk_sample/oic_svr_db_subclient.dat b/service/easy-setup/sampleapp/mediator/linux/richsdk_sample/oic_svr_db_subclient.dat
new file mode 100644 (file)
index 0000000..ae130bc
Binary files /dev/null and b/service/easy-setup/sampleapp/mediator/linux/richsdk_sample/oic_svr_db_subclient.dat differ
diff --git a/service/easy-setup/sampleapp/mediator/linux/richsdk_sample/submediator.cpp b/service/easy-setup/sampleapp/mediator/linux/richsdk_sample/submediator.cpp
new file mode 100755 (executable)
index 0000000..7e98942
--- /dev/null
@@ -0,0 +1,463 @@
+//******************************************************************
+//
+// 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 <iostream>
+#include <condition_variable>
+
+#include "OCPlatform.h"
+#include "OCApi.h"
+#include "OCProvisioningManager.hpp"
+#include "securevirtualresourcetypes.h"
+
+#include "EasySetup.h"
+#include "ESRichCommon.h"
+
+#define ES_SAMPLE_APP_TAG "ES_SAMPLE_APP_TAG"
+#define DECLARE_MENU(FUNC, ...) { #FUNC, FUNC }
+
+#define JSON_DB_PATH "./oic_svr_db_subclient.dat"
+
+using namespace OC;
+using namespace OIC::Service;
+
+static std::shared_ptr<RemoteEnrollee> remoteEnrollee = nullptr;
+static std::shared_ptr<OC::OCResource> curResource = nullptr;
+
+static std::mutex g_discoverymtx;
+static std::condition_variable g_cond;
+
+typedef void (*Runner)();
+
+Runner g_currentRun;
+
+int processUserInput(int min = std::numeric_limits<int>::min(),
+        int max = std::numeric_limits<int>::max())
+{
+    assert(min <= max);
+
+    int input;
+
+    std::cin >> input;
+    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
+
+    if (!std::cin.fail() && min <= input && input <= max) return input;
+
+    std::cin.clear();
+    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
+
+    throw std::runtime_error("Invalid Input, please try again");
+}
+
+void printConfiguration(EnrolleeConf conf)
+{
+    cout << "===========================================" << endl;
+    cout << "\tDevice Name : " << conf.getDeviceName() << endl;
+    cout << "\tModel Number : " << conf.getModelNumber() << endl;
+
+    for(auto it : conf.getWiFiModes())
+    {
+        cout << "\tSupported WiFi modes : " << it << endl;
+    }
+
+    cout << "\tSupported WiFi freq : " << static_cast<int>(conf.getWiFiFreq()) << endl;
+    cout << "\tCloud accessibility: " << conf.isCloudAccessible() << endl;
+    cout << "===========================================" << endl;
+}
+
+void printStatus(EnrolleeStatus status)
+{
+    cout << "===========================================" << endl;
+    cout << "\tProvStatus : " << status.getProvStatus() << endl;
+    cout << "\tLastErrCode : " << status.getLastErrCode() << endl;
+    cout << "===========================================" << endl;
+}
+
+ESOwnershipTransferData provisionSecurityStatusCallback(std::shared_ptr<SecProvisioningStatus> secProvisioningStatus)
+{
+    cout << "provisionSecurityStatusCallback IN" << endl;
+    cout << "ESResult : " << secProvisioningStatus->getESResult() << std::endl;
+    cout << "Device ID : " << secProvisioningStatus->getDeviceUUID() << std::endl;
+
+    if(secProvisioningStatus->getESResult() == ES_SECURE_RESOURCE_IS_DISCOVERED)
+    {
+#if defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
+        cout << "Owned Status : " << secProvisioningStatus->isOwnedDevice() << std::endl;
+        cout << "OT Method : " << secProvisioningStatus->getSelectedOTMethod() << std::endl;
+
+        // TEST
+        ESOwnershipTransferData OTData;
+        OTData.setMOTMethod(OIC_PRECONFIG_PIN, "12345678");
+
+        cout << "Enter!" << std::endl;
+        getchar();
+
+        return OTData;
+#endif
+    }
+    else if(secProvisioningStatus->getESResult() == ES_OK)
+    {
+        cout << "provisionSecurity is success." << std::endl;
+    }
+    else
+    {
+        cout << "provisionSecurity is failed." << endl;
+    }
+
+    return {};
+}
+
+void provisionSecurity()
+{
+    if(!remoteEnrollee)
+    {
+        std::cout << "RemoteEnrollee is null, retry Discovery EnrolleeResource." << endl;
+        return;
+    }
+
+    try
+    {
+        remoteEnrollee->provisionSecurity((SecurityProvStatusCbWithOption)provisionSecurityStatusCallback);
+    }
+    catch (OCException &e)
+    {
+        std::cout << "Exception during provisionSecurity call" << e.reason();
+        return;
+    }
+}
+
+void getStatusCallback(std::shared_ptr< GetEnrolleeStatus > getEnrolleeStatus)
+{
+    if(getEnrolleeStatus->getESResult() != ES_OK)
+    {
+      cout << "getStatus is failed." << endl;
+      return;
+    }
+    else
+    {
+      cout << "getStatus is success." << endl;
+      printStatus(getEnrolleeStatus->getEnrolleeStatus());
+    }
+}
+
+
+void getStatus()
+{
+    if(!remoteEnrollee)
+    {
+        std::cout << "RemoteEnrollee is null, retry Discovery EnrolleeResource." << endl;
+        return;
+    }
+
+    try
+    {
+        remoteEnrollee->getStatus(getStatusCallback);
+    }
+    catch (OCException &e)
+    {
+        std::cout << "Exception during getConfiguration call" << e.reason();
+        return;
+    }
+}
+
+void getConfigurationCallback(std::shared_ptr< GetConfigurationStatus > getConfigurationStatus)
+{
+    if(getConfigurationStatus->getESResult() != ES_OK)
+    {
+      cout << "GetConfigurationStatus is failed." << endl;
+      return;
+    }
+    else
+    {
+      cout << "GetConfigurationStatus is success." << endl;
+      printConfiguration(getConfigurationStatus->getEnrolleeConf());
+    }
+}
+
+void getConfiguration()
+{
+    if(!remoteEnrollee)
+    {
+        std::cout << "RemoteEnrollee is null, retry Discovery EnrolleeResource." << endl;
+        return;
+    }
+
+    try
+    {
+        remoteEnrollee->getConfiguration(getConfigurationCallback);
+    }
+    catch (OCException &e)
+    {
+        std::cout << "Exception during getConfiguration call" << e.reason();
+        return;
+    }
+}
+
+void deviceProvisioningStatusCallback(std::shared_ptr< DevicePropProvisioningStatus > provStatus)
+{
+    if(provStatus->getESResult() != ES_OK)
+    {
+      cout << "Device Provisioning is failed." << endl;
+      return;
+    }
+    else
+    {
+      cout << "Device Provisioning is success." << endl;
+    }
+}
+
+void provisionDeviceProperty()
+{
+    if(!remoteEnrollee)
+    {
+        std::cout << "RemoteEnrollee is null, retry Discovery EnrolleeResource." << endl;
+        return;
+    }
+
+    DeviceProp devProp;
+    devProp.setWiFiProp("Iotivity_SSID", "Iotivity_PWD", WPA2_PSK, TKIP_AES);
+    devProp.setDevConfProp("korean", "Korea", "Location");
+
+    try
+    {
+        remoteEnrollee->provisionDeviceProperties(devProp, deviceProvisioningStatusCallback);
+    }
+    catch (OCException &e)
+    {
+        std::cout << "Exception during provisionDeviceProperties call" << e.reason();
+        return;
+    }
+}
+
+void cloudProvisioningStatusCallback(std::shared_ptr< CloudPropProvisioningStatus > provStatus)
+{
+    switch (provStatus->getESResult())
+    {
+        case ES_OK:
+            cout << "Cloud Provisioning is success." << endl;
+            break;
+        case ES_SECURE_RESOURCE_DISCOVERY_FAILURE:
+            cout << "Enrollee is not found in a given network." << endl;
+            break;
+        case ES_ACL_PROVISIONING_FAILURE:
+            cout << "ACL provisioning is failed." << endl;
+            break;
+        case ES_CERT_PROVISIONING_FAILURE:
+            cout << "CERT provisioning is failed." << endl;
+            break;
+        default:
+            cout << "Cloud Provisioning is failed." << endl;
+            break;
+    }
+}
+
+void provisionCloudProperty()
+{
+    if(!remoteEnrollee)
+    {
+        std::cout << "RemoteEnrollee is null, retry Discovery EnrolleeResource." << endl;
+        return;
+    }
+
+    CloudProp cloudProp;
+    cloudProp.setCloudProp("authCode", "authProvider", "ciServer");
+    cloudProp.setCloudID("f002ae8b-c42c-40d3-8b8d-1927c17bd1b3");
+    cloudProp.setCredID(1);
+
+    try
+    {
+        remoteEnrollee->provisionCloudProperties(cloudProp, cloudProvisioningStatusCallback);
+    }
+    catch (OCException &e)
+    {
+        std::cout << "Exception during provisionCloudProperties call" << e.reason();
+        return;
+    }
+}
+
+// Callback to found resources
+void foundResource(std::shared_ptr<OC::OCResource> resource)
+{
+    std::string resourceURI;
+    std::string hostAddress;
+    try
+    {
+        // Do some operations with resource object.
+        if(resource &&
+           !curResource &&
+           resource->getResourceTypes().at(0) == OC_RSRVD_ES_RES_TYPE_PROV)
+        {
+            std::cout<<"DISCOVERED Resource:"<<std::endl;
+            // Get the resource URI
+            resourceURI = resource->uri();
+            std::cout << "\tURI of the resource: " << resourceURI << std::endl;
+
+            // Get the resource host address
+            hostAddress = resource->host();
+            std::cout << "\tHost address of the resource: " << hostAddress << std::endl;
+
+            // Get the resource types
+            std::cout << "\tList of resource types: " << std::endl;
+            for(auto &resourceTypes : resource->getResourceTypes())
+            {
+                std::cout << "\t\t" << resourceTypes << std::endl;
+            }
+
+            // Get the resource interfaces
+            std::cout << "\tList of resource interfaces: " << std::endl;
+            for(auto &resourceInterfaces : resource->getResourceInterfaces())
+            {
+                std::cout << "\t\t" << resourceInterfaces << std::endl;
+            }
+
+            if(curResource == nullptr)
+            {
+                remoteEnrollee = EasySetup::getInstance()->createRemoteEnrollee(resource);
+                if(!remoteEnrollee)
+                {
+                    std::cout << "RemoteEnrollee object is failed for some reasons!" << std::endl;
+                }
+                else
+                {
+                    curResource = resource;
+                    std::cout << "RemoteEnrollee object is successfully created!" << std::endl;
+                    g_cond.notify_all();
+                }
+            }
+        }
+    }
+    catch(std::exception& e)
+    {
+        std::cerr << "Exception in foundResource: "<< e.what() << std::endl;
+    }
+}
+
+void discoveryEnrolleeResource()
+{
+       try
+       {
+           std::ostringstream requestURI;
+        requestURI << OC_RSRVD_WELL_KNOWN_URI << "?rt=" << OC_RSRVD_ES_RES_TYPE_PROV;
+        OCPlatform::findResource("", requestURI.str(), CT_DEFAULT, &foundResource);
+        std::cout<< "Finding Resource... " <<std::endl;
+
+        std::unique_lock<std::mutex> lck(g_discoverymtx);
+        g_cond.wait_for(lck, std::chrono::seconds(5));
+       }
+       catch (OCException& e)
+       {
+               std::cout << "Exception in discoveryEnrolleeResource: "<<e.what();
+       }
+}
+
+void DisplayMenu()
+{
+       constexpr int DISCOVERY_ENROLLEE = 1;
+    constexpr int PROVISION_SECURITY = 2;
+    constexpr int GET_STATUS = 3;
+    constexpr int GET_CONFIGURATION = 4;
+    constexpr int PROVISION_DEVICE_PROPERTY = 5;
+    constexpr int PROVISION_CLOUD_PROPERTY = 6;
+
+    std::cout << "========================================================\n";
+    std::cout << DISCOVERY_ENROLLEE << ". Discovery Enrollee Resource \n";
+    std::cout << PROVISION_SECURITY << ". Provision Security to Enrollee  \n";
+    std::cout << GET_STATUS << ". Get Status from Enrollee  \n";
+    std::cout << GET_CONFIGURATION << ". Get Configuration from Enrollee  \n";
+    std::cout << PROVISION_DEVICE_PROPERTY << ". Provision Device Property\n";
+    std::cout << PROVISION_CLOUD_PROPERTY << ". Provision Cloud Property  \n";
+    std::cout << "========================================================\n";
+
+    int selection = processUserInput(DISCOVERY_ENROLLEE, PROVISION_CLOUD_PROPERTY);
+
+    switch (selection)
+    {
+        case DISCOVERY_ENROLLEE:
+            discoveryEnrolleeResource();
+            break;
+        case PROVISION_SECURITY:
+            provisionSecurity();
+            break;
+        case GET_STATUS:
+            getStatus();
+            break;
+        case GET_CONFIGURATION:
+            getConfiguration();
+            break;
+        case PROVISION_DEVICE_PROPERTY:
+            provisionDeviceProperty();
+            break;
+        case PROVISION_CLOUD_PROPERTY:
+            provisionCloudProperty();
+            break;
+        default:
+            break;
+    };
+}
+
+static FILE* client_open(const char *UNUSED_PARAM, const char *mode)
+{
+    (void)UNUSED_PARAM;
+    return fopen(JSON_DB_PATH, mode);
+}
+
+int main()
+{
+    OCPersistentStorage ps {client_open, fread, fwrite, fclose, unlink };
+
+    PlatformConfig config
+    {
+        OC::ServiceType::InProc, ModeType::Both, "0.0.0.0", 0, OC::QualityOfService::HighQos, &ps
+    };
+
+    OCPlatform::Configure(config);
+
+    try
+    {
+#ifdef __WITH_DTLS__
+        //Initializing the provisioning client stack using the db path provided by the application.
+        OCStackResult result = OCSecure::provisionInit("PDM_sub.db");
+
+        if (result != OC_STACK_OK)
+        {
+            return -1;
+        }
+#endif
+    }catch(OCException& e)
+    {
+        std::cout << "Exception in main: "<<e.what();
+    }
+
+    while (true)
+    {
+        try
+        {
+            DisplayMenu();
+        }
+        catch (const std::exception& e)
+        {
+            std::cout << "Exception caught in main " << e.what() << std::endl;
+        }
+    }
+
+    std::cout << "Stopping the client" << std::endl;
+
+    return 0;
+}
+