Modify OTM & SRM according to spec CR document.
authorleechul <chuls.lee@samsung.com>
Thu, 3 Mar 2016 08:36:08 +0000 (17:36 +0900)
committerRandeep Singh <randeep.s@samsung.com>
Wed, 9 Mar 2016 09:21:06 +0000 (09:21 +0000)
NOTE : This patch is modified based on ownership transfer CR document.
Please refer to https://workspace.openinterconnect.org/apps/org/workgroup/security_tg/download.php/4703/STG008_OIC%20CR%20Ownership%20Transfer%20sequence%20diagram%20v2.docx
This CR document seems to be applied to next spec.
I'd like to apply CR to save time for prepare 1.1.0 release.

This patch includes the following modifications :
   1. Modify not to include private data when OBT sends owner credential.
        - Please see the step 19 of CR document.

   2. Modify to re-establish secure session using owner credential
      when owner credential was successfully exchanged.
        - We can verify owner credential through re-establish secure session.
        - Please see the step 38,39 of CR docuemnt.

   3. Add logic to handle errors that occurred during ownership transfer.

[Patch #1] Initial upload.
[Patch #2] Add logic to handle errors
[Patch #3] Remove the compile errors and warnings.
[Patch #4] Retrigger
[Patch #5] Retrigger
[Patch #6] Rebase
[Patch #7] Rebase
[Patch #8] Update based on self-review.
[Patch #9] Rebase
[Patch #10] Retrigger
[Patch #11] Modify according to Mr.JongSung Lee's comment.

Change-Id: If3d8f21ef686db86dbfcc1b15382eeebaa232a9d
Signed-off-by: leechul <chuls.lee@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/5341
Reviewed-by: Randeep Singh <randeep.s@samsung.com>
Tested-by: Randeep Singh <randeep.s@samsung.com>
resource/csdk/security/include/internal/doxmresource.h
resource/csdk/security/include/internal/pstatresource.h
resource/csdk/security/provisioning/src/ownershiptransfermanager.c
resource/csdk/security/src/credresource.c
resource/csdk/security/src/doxmresource.c
resource/csdk/security/src/pstatresource.c

index e0f2fc9..237da64 100644 (file)
@@ -94,6 +94,11 @@ OCStackResult GetDoxmDevOwnerId(OicUuid_t *devOwner);
  */
 void DeleteDoxmBinData(OicSecDoxm_t* doxm);
 
+/**
+ * Function to restore doxm resurce to initial status.
+ * This function will use in case of error while ownership transfer
+ */
+void RestoreDoxmToInitState();
 
 #ifdef __cplusplus
 }
index 40c41ab..3134788 100644 (file)
@@ -61,6 +61,11 @@ char * BinToPstatJSON(const OicSecPstat_t * pstat);
  */
 void DeletePstatBinData(OicSecPstat_t* pstat);
 
+/**
+ * Function to restore pstat resurce to initial status.
+ * This function will use in case of error while ownership transfer
+ */
+void RestorePstatToInitState();
 
 #ifdef __cplusplus
 }
index ba284f6..5011ea6 100644 (file)
@@ -323,65 +323,84 @@ static void SetResult(OTMContext_t* otmCtx, const OCStackResult res)
  */
 void DTLSHandshakeCB(const CAEndpoint_t *endpoint, const CAErrorInfo_t *info)
 {
-    if(g_otmCtx && endpoint && info)
+    if(NULL != g_otmCtx && NULL != g_otmCtx->selectedDeviceInfo &&
+       NULL != endpoint && NULL != info)
     {
         OIC_LOG_V(INFO, TAG, "Received status from remote device(%s:%d) : %d",
                  endpoint->addr, endpoint->port, info->result);
 
-        //Make sure the address matches.
-        if(strncmp(g_otmCtx->selectedDeviceInfo->endpoint.addr,
-           endpoint->addr,
-           sizeof(endpoint->addr)) == 0 &&
-           g_otmCtx->selectedDeviceInfo->securePort == endpoint->port)
+        OicSecDoxm_t* newDevDoxm = g_otmCtx->selectedDeviceInfo->doxm;
+
+        if(NULL != newDevDoxm)
         {
-            OCStackResult res = OC_STACK_ERROR;
+            OicUuid_t emptyUuid = {.id={0}};
 
-            //In case of success, send next coaps request.
-            if(CA_STATUS_OK == info->result)
+            //Make sure the address matches.
+            if(strncmp(g_otmCtx->selectedDeviceInfo->endpoint.addr,
+               endpoint->addr,
+               sizeof(endpoint->addr)) == 0 &&
+               g_otmCtx->selectedDeviceInfo->securePort == endpoint->port)
             {
-                //Send request : PUT /oic/sec/doxm [{... , "devowner":"PT's UUID"}]
-                res = PutOwnerUuid(g_otmCtx);
-                if(OC_STACK_OK != res)
-                {
-                    OIC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to send owner information");
-                    SetResult(g_otmCtx, res);
-                }
-            }
-            //In case of failure, re-start the ownership transfer in case of PIN OxM
-            else if(CA_DTLS_AUTHENTICATION_FAILURE == info->result)
-            {
-                g_otmCtx->selectedDeviceInfo->doxm->owned = false;
-                g_otmCtx->attemptCnt++;
+                OCStackResult res = OC_STACK_ERROR;
 
-                if(g_otmCtx->selectedDeviceInfo->doxm->oxmSel == OIC_RANDOM_DEVICE_PIN)
+                //If temporal secure sesstion established successfully
+                if(CA_STATUS_OK == info->result &&
+                   false == newDevDoxm->owned &&
+                   memcmp(&(newDevDoxm->owner), &emptyUuid, sizeof(OicUuid_t)) == 0)
                 {
-                    /*
-                    res = RemoveCredential(&g_otmCtx->subIdForPinOxm);
-                    if(OC_STACK_RESOURCE_DELETED != res)
+                    //Send request : PUT /oic/sec/doxm [{... , "devowner":"PT's UUID"}]
+                    res = PutOwnerUuid(g_otmCtx);
+                    if(OC_STACK_OK != res)
                     {
-                        OIC_LOG_V(ERROR, TAG, "Failed to remove temporal PSK : %d", res);
+                        OIC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to send owner information");
                         SetResult(g_otmCtx, res);
-                        return;
-                    }*/
+                    }
+                }
+                //In case of authentication failure
+                else if(CA_DTLS_AUTHENTICATION_FAILURE == info->result)
+                {
+                    //in case of error from owner credential
+                    if(memcmp(&(newDevDoxm->owner), &emptyUuid, sizeof(OicUuid_t)) != 0 &&
+                        true == newDevDoxm->owned)
+                    {
+                        OIC_LOG(ERROR, TAG, "The owner credential may incorrect.");
 
-                    if(WRONG_PIN_MAX_ATTEMP > g_otmCtx->attemptCnt)
+                        if(OC_STACK_OK != RemoveCredential(&(newDevDoxm->deviceID)))
+                        {
+                            OIC_LOG(WARNING, TAG, "Failed to remove the invaild owner credential");
+                        }
+                        SetResult(g_otmCtx, OC_STACK_AUTHENTICATION_FAILURE);
+                    }
+                    //in case of error from wrong PIN, re-start the ownership transfer
+                    else if(OIC_RANDOM_DEVICE_PIN == newDevDoxm->oxmSel)
                     {
-                        res = StartOwnershipTransfer(g_otmCtx, g_otmCtx->selectedDeviceInfo);
-                        if(OC_STACK_OK != res)
+                        OIC_LOG(ERROR, TAG, "The PIN number may incorrect.");
+
+                        memcpy(&(newDevDoxm->owner), &emptyUuid, sizeof(OicUuid_t));
+                        newDevDoxm->owned = false;
+                        g_otmCtx->attemptCnt++;
+
+                        if(WRONG_PIN_MAX_ATTEMP > g_otmCtx->attemptCnt)
+                        {
+                            res = StartOwnershipTransfer(g_otmCtx, g_otmCtx->selectedDeviceInfo);
+                            if(OC_STACK_OK != res)
+                            {
+                                SetResult(g_otmCtx, res);
+                                OIC_LOG(ERROR, TAG, "Failed to Re-StartOwnershipTransfer");
+                            }
+                        }
+                        else
                         {
-                            SetResult(g_otmCtx, res);
-                            OIC_LOG(ERROR, TAG, "Failed to Re-StartOwnershipTransfer");
+                            OIC_LOG(ERROR, TAG, "User has exceeded the number of authentication attempts.");
+                            SetResult(g_otmCtx, OC_STACK_AUTHENTICATION_FAILURE);
                         }
                     }
                     else
                     {
+                        OIC_LOG(ERROR, TAG, "Failed to establish secure session.");
                         SetResult(g_otmCtx, OC_STACK_AUTHENTICATION_FAILURE);
                     }
                 }
-                else
-                {
-                    SetResult(g_otmCtx, OC_STACK_AUTHENTICATION_FAILURE);
-                }
             }
         }
     }
@@ -711,6 +730,46 @@ static OCStackApplicationResult OwnerCredentialHandler(void *ctx, OCDoHandle UNU
     {
         if(otmCtx && otmCtx->selectedDeviceInfo)
         {
+            //Close the temporal secure session to verify the owner credential
+            CAEndpoint_t* endpoint = (CAEndpoint_t *)&otmCtx->selectedDeviceInfo->endpoint;
+            endpoint->port = otmCtx->selectedDeviceInfo->securePort;
+            CAResult_t caResult = CACloseDtlsSession(endpoint);
+            if(CA_STATUS_OK != caResult)
+            {
+                OIC_LOG(ERROR, TAG, "Failed to close DTLS session");
+                SetResult(otmCtx, caResult);
+                return OC_STACK_DELETE_TRANSACTION;
+            }
+
+            /**
+             * If we select NULL cipher,
+             * client will select appropriate cipher suite according to server's cipher-suite list.
+             */
+            caResult = CASelectCipherSuite(TLS_NULL_WITH_NULL_NULL);
+            if(CA_STATUS_OK != caResult)
+            {
+                OIC_LOG(ERROR, TAG, "Failed to select TLS_NULL_WITH_NULL_NULL");
+                SetResult(otmCtx, caResult);
+                return OC_STACK_DELETE_TRANSACTION;
+            }
+
+            /**
+             * in case of random PIN based OxM,
+             * revert get_psk_info callback of tinyDTLS to use owner credential.
+             */
+            if(OIC_RANDOM_DEVICE_PIN == otmCtx->selectedDeviceInfo->doxm->oxmSel)
+            {
+                OicUuid_t emptyUuid = { .id={0}};
+                SetUuidForRandomPinOxm(&emptyUuid);
+
+                if(CA_STATUS_OK != CARegisterDTLSCredentialsHandler(GetDtlsPskCredentials))
+                {
+                    OIC_LOG(ERROR, TAG, "Failed to revert DTLS credential handler.");
+                    SetResult(otmCtx, OC_STACK_INVALID_CALLBACK);
+                    return OC_STACK_DELETE_TRANSACTION;
+                }
+            }
+
             //PUT /oic/sec/doxm [{ ..., "owned":"TRUE" }]
             res = PutOwnershipInformation(otmCtx);
             if(OC_STACK_OK != res)
@@ -907,8 +966,13 @@ static OCStackResult PutOwnerCredential(OTMContext_t* otmCtx)
         OicSecCred_t newCredential;
         memcpy(&newCredential, ownerCredential, sizeof(OicSecCred_t));
         newCredential.next = NULL;
+
+        //Set subject ID as PT's ID
         memcpy(&(newCredential.subject), &credSubjectId, sizeof(OicUuid_t));
 
+        //Fill private data as empty string
+        newCredential.privateData.data = NULL;
+
         //Send owner credential to new device : PUT /oic/sec/cred [ owner credential ]
         secPayload->securityData = BinToCredJSON(&newCredential);
         if (NULL == secPayload->securityData)
index ac172f7..4bc220b 100644 (file)
 #include "iotvticalendar.h"
 #include "ocserverrequest.h"
 
+#ifdef __WITH_DTLS__
+#include "global.h"
+#endif //__WITH_DTLS__
+
 #ifdef WITH_ARDUINO
 #include <string.h>
 #else
@@ -306,8 +310,10 @@ OicSecCred_t * JSONToCredBin(const char * jsonStr)
                 (cred->credType & SYMMETRIC_GROUP_KEY) ||
                 (cred->credType & PIN_PASSWORD))
             {
-                VERIFY_NON_NULL(TAG, jsonObj, ERROR);
-                VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR);
+                if(jsonObj)
+                {
+                    VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR);
+                }
             }
 #ifdef __WITH_X509__
             else if (cred->credType & SIGNED_ASYMMETRIC_KEY)
@@ -333,6 +339,10 @@ OicSecCred_t * JSONToCredBin(const char * jsonStr)
                 }
 #endif // __WITH_X509__
             }
+            else
+            {
+                cred->privateData.data = NULL;
+            }
 
             //PublicData is mandatory only for SIGNED_ASYMMETRIC_KEY credentials type.
             jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_PUBLICDATA_NAME);
@@ -662,29 +672,19 @@ OCStackResult RemoveAllCredentials(void)
 
 #ifdef __WITH_DTLS__
 /**
- * Internal function to verify recevied owner PSK.
+ * Internal function to fill private data of owner PSK.
  *
- * @param receviedCred recevied Owner Credential from OBT(PT)
+ * @param receviedCred recevied owner credential from OBT(PT)
  * @param ownerAdd address of OBT(PT)
  * @param doxm current device's doxm resource
  *
  * @retval
- *     true valid ower psk
- *     false Invalid owner psk or failed to owner psk verification
+ *     true successfully done and valid ower psk information
+ *     false Invalid owner psk information or failed to owner psk generation
  */
-static bool isValidOwnerPSK(const OicSecCred_t* receviedCred, const CAEndpoint_t* ownerAddr,
+static bool FillPrivateDataOfOwnerPSK(OicSecCred_t* receviedCred, const CAEndpoint_t* ownerAddr,
                            const OicSecDoxm_t* doxm)
 {
-    //Decode received PSK to verify OwnerPSKs match
-    uint32_t privLen = strlen(receviedCred->privateData.data);
-    size_t b64BufSize = B64DECODE_OUT_SAFESIZE((privLen + 1) * sizeof(char));
-    uint8_t* decodeBuff = OICMalloc(b64BufSize);
-    VERIFY_NON_NULL(TAG, decodeBuff, ERROR);
-    uint32_t decodedSize = 0;
-    B64Result b64Ret = b64Decode(receviedCred->privateData.data, privLen,
-                                 decodeBuff, b64BufSize, &decodedSize);
-    VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
-
     //Derive OwnerPSK locally
     const char* oxmLabel = GetOxmString(doxm->oxmSel);
     VERIFY_NON_NULL(TAG, oxmLabel, ERROR);
@@ -697,20 +697,38 @@ static bool isValidOwnerPSK(const OicSecCred_t* receviedCred, const CAEndpoint_t
         ownerPSK, OWNER_PSK_LENGTH_128);
     VERIFY_SUCCESS(TAG, pskRet == CA_STATUS_OK, ERROR);
 
-    OIC_LOG_V(DEBUG, TAG, "Oxm Label = %s", oxmLabel);
-    OIC_LOG_V(DEBUG, TAG, "PSK size compare : %s",
-              OWNER_PSK_LENGTH_128 == decodedSize ? "TRUE" : "FALSE");
-    OIC_LOG_V(DEBUG, TAG, "SubjectID compare = %s",
-              memcmp(&(receviedCred->subject), &(doxm->owner), sizeof(OicUuid_t)) == 0 ?
-              "TRUE" : "FALSE");
-    OIC_LOG_V(DEBUG, TAG, "Owner PSK compare = %s",
-              memcmp(ownerPSK, decodeBuff, OWNER_PSK_LENGTH_128) == 0 ? "TRUE" : "FALSE");
-
-    //Verify OwnerPSKs match
-    return (OWNER_PSK_LENGTH_128 == decodedSize &&
-            memcmp(ownerPSK, decodeBuff, OWNER_PSK_LENGTH_128) == 0 &&
-            memcmp(&(receviedCred->subject), &(doxm->owner), sizeof(OicUuid_t)) == 0);
+    OIC_LOG(DEBUG, TAG, "OwnerPSK dump :");
+    OIC_LOG_BUFFER(DEBUG, TAG, ownerPSK, OWNER_PSK_LENGTH_128);
+
+    //Generate owner credential based on recevied credential information
+    size_t b64BufSize = B64ENCODE_OUT_SAFESIZE(OWNER_PSK_LENGTH_128 * sizeof(char));
+    uint8_t* encodeBuff = OICMalloc((b64BufSize + 1) * sizeof(char));
+    VERIFY_NON_NULL(TAG, encodeBuff, ERROR);
+    uint32_t encodedSize = 0;
+    B64Result b64Ret = b64Encode(ownerPSK, OWNER_PSK_LENGTH_128,
+                                 (char*)encodeBuff, b64BufSize + 1, &encodedSize);
+    VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
+    encodeBuff[encodedSize] = '\0';
+
+    //memory re-allocation for private data
+    OICFree(receviedCred->privateData.data);
+    receviedCred->privateData.data = (char*)OICMalloc((encodedSize + 1) * sizeof(char));
+    VERIFY_NON_NULL(TAG, receviedCred->privateData.data, ERROR);
+
+    //fill the base64 encoded private data
+    strncpy(receviedCred->privateData.data, (char*)encodeBuff, b64BufSize + 1);
+
+    OIC_LOG(INFO, TAG, "PrivateData of OwnerPSK was calculated successfully");
+
+    //deallocate local memory
+    OICFree(encodeBuff);
+
+    //Verify OwnerPSK information
+    return (memcmp(&(receviedCred->subject), &(doxm->owner), sizeof(OicUuid_t)) == 0 &&
+            receviedCred->credType == SYMMETRIC_PAIR_WISE_KEY);
 exit:
+    //receviedCred->privateData.data will be deallocated when deleting credential.
+    OICFree(encodeBuff);
     return false;
 }
 
@@ -736,9 +754,14 @@ static OCEntityHandlerResult HandlePutRequest(const OCEntityHandlerRequest * ehR
                 case SYMMETRIC_PAIR_WISE_KEY:
                 {
                     OCServerRequest *request = (OCServerRequest *)ehRequest->requestHandle;
-                    if(isValidOwnerPSK(cred, (CAEndpoint_t *)&request->devAddr, doxm))
+                    if(FillPrivateDataOfOwnerPSK(cred, (CAEndpoint_t *)&request->devAddr, doxm))
                     {
-                        OIC_LOG(ERROR, TAG, "OwnerPKS is matched");
+                        if(OC_STACK_RESOURCE_DELETED == RemoveCredential(&cred->subject))
+                        {
+                            OIC_LOG(WARNING, TAG, "The credential with the same subject ID was detected!");
+                        }
+
+                        OIC_LOG(ERROR, TAG, "OwnerPSK was generated successfully.");
                         if(OC_STACK_OK == AddCredential(cred))
                         {
                             ret = OC_EH_RESOURCE_CREATED;
@@ -755,6 +778,44 @@ static OCEntityHandlerResult HandlePutRequest(const OCEntityHandlerRequest * ehR
                         ret = OC_EH_ERROR;
                     }
 
+                    if(OC_EH_RESOURCE_CREATED == ret)
+                    {
+                        /**
+                         * in case of random PIN based OxM,
+                         * revert get_psk_info callback of tinyDTLS to use owner credential.
+                         */
+                        if(OIC_RANDOM_DEVICE_PIN == doxm->oxmSel)
+                        {
+                            OicUuid_t emptyUuid = { .id={0}};
+                            SetUuidForRandomPinOxm(&emptyUuid);
+
+                            if(CA_STATUS_OK != CARegisterDTLSCredentialsHandler(GetDtlsPskCredentials))
+                            {
+                                OIC_LOG(ERROR, TAG, "Failed to revert DTLS credential handler.");
+                                ret = OC_EH_ERROR;
+                                break;
+                            }
+                        }
+
+                        //Select cipher suite to use owner PSK
+                        if(CA_STATUS_OK != CAEnableAnonECDHCipherSuite(false))
+                        {
+                            OIC_LOG(ERROR, TAG, "Failed to disable anonymous cipher suite");
+                            ret = OC_EH_ERROR;
+                        }
+                        else
+                        {
+                            OIC_LOG(INFO, TAG, "Anonymous cipher suite is DISABLED");
+                        }
+
+                        if(CA_STATUS_OK !=
+                           CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256))
+                        {
+                            OIC_LOG(ERROR, TAG, "Failed to select cipher suite");
+                            ret = OC_EH_ERROR;
+                        }
+                    }
+
                     break;
                 }
                 case SYMMETRIC_GROUP_KEY:
@@ -774,6 +835,16 @@ static OCEntityHandlerResult HandlePutRequest(const OCEntityHandlerRequest * ehR
                     break;
                 }
             }
+
+            if(OC_EH_RESOURCE_CREATED != ret)
+            {
+                /*
+                  * If some error is occured while ownership transfer,
+                  * ownership transfer related resource should be revert back to initial status.
+                  */
+                RestoreDoxmToInitState();
+                RestorePstatToInitState();
+            }
         }
         else
         {
@@ -796,6 +867,15 @@ static OCEntityHandlerResult HandlePutRequest(const OCEntityHandlerRequest * ehR
 #endif//__WITH_DTLS__
     }
 
+    if(OC_EH_RESOURCE_CREATED != ret)
+    {
+        if(OC_STACK_OK != RemoveCredential(&cred->subject))
+        {
+            OIC_LOG(WARNING, TAG, "Failed to remove the invalid credential");
+        }
+        FreeCred(cred);
+    }
+
     return ret;
 }
 
@@ -812,7 +892,7 @@ static OCEntityHandlerResult HandlePostRequest(const OCEntityHandlerRequest * eh
         //discarded and the next available credId will be assigned
         //to it before getting appended to the existing credential
         //list and updating svr database.
-        ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_RESOURCE_CREATED : OC_EH_ERROR;\r
+        ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_RESOURCE_CREATED : OC_EH_ERROR;
     }
 
     return ret;
index 22688d6..30d3d97 100644 (file)
@@ -24,6 +24,7 @@
 #include "cJSON.h"
 #include "resourcemanager.h"
 #include "doxmresource.h"
+#include "pstatresource.h"
 #include "psinterface.h"
 #include "utlist.h"
 #include "srmresourcestrings.h"
@@ -576,7 +577,6 @@ static OCEntityHandlerResult HandleDoxmPutRequest (const OCEntityHandlerRequest
                          */
                         caRes = CARegisterDTLSCredentialsHandler(GetDtlsPskForRandomPinOxm);
                         VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
-
                         ehRet = OC_EH_OK;
                     }
                     else
@@ -592,12 +592,6 @@ static OCEntityHandlerResult HandleDoxmPutRequest (const OCEntityHandlerRequest
                     //Save the owner's UUID to derive owner credential
                     memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
 
-//                    OCServerRequest * request = (OCServerRequest *)ehRequest->requestHandle;
-//                    //Generate new credential for provisioning tool
-//                    ehRet = AddOwnerPSK((CAEndpoint_t*)(&request->devAddr), newDoxm,
-//                                        (uint8_t*)OXM_RANDOM_DEVICE_PIN, strlen(OXM_RANDOM_DEVICE_PIN));
-//                    VERIFY_SUCCESS(TAG, OC_EH_OK == ehRet, ERROR);
-
                     //Update new state in persistent storage
                     if((UpdatePersistentStorage(gDoxm) == true))
                     {
@@ -623,7 +617,7 @@ static OCEntityHandlerResult HandleDoxmPutRequest (const OCEntityHandlerRequest
         {
             gDoxm->owned = true;
             // Update new state in persistent storage
-            if (true == UpdatePersistentStorage(gDoxm))
+            if (UpdatePersistentStorage(gDoxm))
             {
                 ehRet = OC_EH_OK;
             }
@@ -642,17 +636,11 @@ exit:
                             "DOXM will be reverted.");
 
         /*
-         * If persistent storage update failed, revert back the state
-         * for global variable.
+         * If some error is occured while ownership transfer,
+         * ownership transfer related resource should be revert back to initial status.
          */
-        gDoxm->owned = false;
-        gDoxm->oxmSel = OIC_JUST_WORKS;
-        memset(&(gDoxm->owner), 0, sizeof(OicUuid_t));
-
-        if(!UpdatePersistentStorage(gDoxm))
-        {
-            OIC_LOG(ERROR, TAG, "Failed to revert DOXM in persistent storage");
-        }
+        RestoreDoxmToInitState();
+        RestorePstatToInitState();
     }
 
     //Send payload to request originator
@@ -813,6 +801,14 @@ OCStackResult InitDoxmResource()
     {
         gDoxm = GetDoxmDefault();
     }
+
+    //In case of the server is shut down unintentionally, we should initialize the owner
+    if(false == gDoxm->owned)
+    {
+        OicUuid_t emptyUuid = {.id={0}};
+        memcpy(&gDoxm->owner, &emptyUuid, sizeof(OicUuid_t));
+    }
+
     ret = CheckDeviceID();
     if (ret == OC_STACK_OK)
     {
@@ -887,3 +883,25 @@ OCStackResult GetDoxmDevOwnerId(OicUuid_t *devOwner)
     }
     return retVal;
 }
+
+/**
+ * Function to restore doxm resurce to initial status.
+ * This function will use in case of error while ownership transfer
+ */
+void RestoreDoxmToInitState()
+{
+    if(gDoxm)
+    {
+        OIC_LOG(INFO, TAG, "DOXM resource will revert back to initial status.");
+
+        OicUuid_t emptyUuid = {.id={0}};
+        memcpy(&(gDoxm->owner), &emptyUuid, sizeof(OicUuid_t));
+        gDoxm->owned = false;
+        gDoxm->oxmSel = OIC_JUST_WORKS;
+
+        if(!UpdatePersistentStorage(gDoxm))
+        {
+            OIC_LOG(ERROR, TAG, "Failed to revert DOXM in persistent storage");
+        }
+    }
+}
index f5c4746..4bada31 100644 (file)
@@ -24,6 +24,7 @@
 #include "cJSON.h"
 #include "resourcemanager.h"
 #include "pstatresource.h"
+#include "doxmresource.h"
 #include "psinterface.h"
 #include "utlist.h"
 #include "base64.h"
@@ -48,7 +49,9 @@ static OicSecPstat_t gDefaultPstat =
     &gSm,                                     // OicSecDpom_t *sm
     0,                                        // uint16_t commitHash
 };
+
 static OicSecPstat_t    *gPstat = NULL;
+
 static OCResourceHandle gPstatHandle = NULL;
 
 void DeletePstatBinData(OicSecPstat_t* pstat)
@@ -191,6 +194,35 @@ exit:
 }
 
 /**
+ * Function to update persistent storage
+ */
+static bool UpdatePersistentStorage(OicSecPstat_t * pstat)
+{
+    bool bRet = false;
+
+    if (pstat)
+    {
+        // Convert pstat data into JSON for update to persistent storage
+        char *jsonStr = BinToPstatJSON(pstat);
+        if (jsonStr)
+        {
+            cJSON *jsonPstat = cJSON_Parse(jsonStr);
+            OICFree(jsonStr);
+
+            if (jsonPstat &&
+                (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_PSTAT_NAME, jsonPstat)))
+            {
+                bRet = true;
+            }
+            cJSON_Delete(jsonPstat);
+        }
+    }
+
+    return bRet;
+}
+
+
+/**
  * The entity handler determines how to process a GET request.
  */
 static OCEntityHandlerResult HandlePstatGetRequest (const OCEntityHandlerRequest * ehRequest)
@@ -264,18 +296,22 @@ static OCEntityHandlerResult HandlePstatPutRequest(const OCEntityHandlerRequest
             }
         }
         // Convert pstat data into JSON for update to persistent storage
-        char *jsonStr = BinToPstatJSON(gPstat);
-        if (jsonStr)
+        if(UpdatePersistentStorage(gPstat))
         {
-            cJSON *jsonPstat = cJSON_Parse(jsonStr);
-            OICFree(jsonStr);
-            if (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_PSTAT_NAME, jsonPstat))
-            {
-                ehRet = OC_EH_OK;
-            }
+            ehRet = OC_EH_OK;
         }
     }
  exit:
+    if(OC_EH_OK != ehRet)
+    {
+        /*
+          * If some error is occured while ownership transfer,
+          * ownership transfer related resource should be revert back to initial status.
+          */
+        RestoreDoxmToInitState();
+        RestorePstatToInitState();
+    }
+
     //Send payload to request originator
     if(OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL))
     {
@@ -380,6 +416,7 @@ OCStackResult InitPstatResource()
     {
         gPstat = GetPstatDefault();
     }
+
     // Instantiate 'oic.sec.pstat'
     ret = CreatePstatResource();
 
@@ -402,3 +439,28 @@ OCStackResult DeInitPstatResource()
     return OCDeleteResource(gPstatHandle);
 }
 
+
+/**
+ * Function to restore pstat resurce to initial status.
+ * This function will use in case of error while ownership transfer
+ */
+void RestorePstatToInitState()
+{
+    if(gPstat)
+    {
+        OIC_LOG(INFO, TAG, "PSTAT resource will revert back to initial status.");
+
+        gPstat->cm = NORMAL;
+        gPstat->tm = NORMAL;
+        gPstat->om = SINGLE_SERVICE_CLIENT_DRIVEN;
+        if(gPstat->sm && 0 < gPstat->smLen)
+        {
+            gPstat->sm[0] = SINGLE_SERVICE_CLIENT_DRIVEN;
+        }
+
+        if(!UpdatePersistentStorage(gPstat))
+        {
+            OIC_LOG(ERROR, TAG, "Failed to revert DOXM in persistent storage");
+        }
+    }
+}