CONPRO-1467: Improve Reset
[platform/upstream/iotivity.git] / resource / csdk / security / src / doxmresource.c
index 320425f..d8b4506 100644 (file)
@@ -49,6 +49,8 @@
 #include "pinoxmcommon.h"
 #include "oxmverifycommon.h"
 #include "octhread.h"
+#include "oic_time.h"
+#include "oic_string.h"
 
 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
 #include "pkix_interface.h"
@@ -95,7 +97,11 @@ static OicSecDoxm_t        *gDoxm = NULL;
 static oc_mutex            g_mutexDoxm = NULL;
 static bool                g_isDoxmNull = false;
 static OCResourceHandle    gDoxmHandle = NULL;
+static oc_mutex            g_mutexWait;
+static oc_thread           g_waitConfirmThreadId;
+oc_cond                    g_condWait;
 static InformOxmSelectedCallback_t g_InformOxmSelectedCallback = NULL;
+static bool                g_isConfirmResult;
 
 static OicSecOxm_t gOicSecDoxmJustWorks = OIC_JUST_WORKS;
 static OicSecDoxm_t gDefaultDoxm =
@@ -1096,6 +1102,137 @@ void UnsetInformOxmSelCB()
     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
 }
 
+#if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
+static OCEntityHandlerResult HandleDoxmPostRequest(OCEntityHandlerRequest * ehRequest);
+
+static void DestroyEntityHandlerRequest(OCEntityHandlerRequest * ehRequest)
+{
+    if (ehRequest == NULL) {
+        OIC_LOG(WARNING, TAG, "ehRequest is NULL");
+        return;
+    }
+
+    OICFree(ehRequest->query);
+
+    if (ehRequest->payload) {
+        OICFree(((OCSecurityPayload *)ehRequest->payload)->securityData);
+        OICFree(ehRequest->payload);
+    }
+
+    OICFree(ehRequest);
+}
+
+void * WaitConfirm(OCEntityHandlerRequest * ehRequest)
+{
+    bool confirmResult = false, confirmState = false;
+
+    oc_mutex_lock(g_mutexWait);
+    oc_cond_wait(g_condWait, g_mutexWait);
+    oc_cond_free(g_condWait);
+    g_condWait = NULL;
+
+    oc_mutex_unlock(g_mutexWait);
+    oc_mutex_free(g_mutexWait);
+    g_mutexWait = NULL;
+
+    g_isConfirmResult = true;
+    GetAsyncVerifyUserResult(&confirmResult, &confirmState);
+    if (confirmResult == true)
+    {
+        gConfirmState = CONFIRM_STATE_ACCEPTED;
+        HandleDoxmPostRequest(ehRequest);
+        g_isConfirmResult = false;
+    }
+    else
+    {
+        gConfirmState = CONFIRM_STATE_DENIED;
+        HandleDoxmPostRequest(ehRequest);
+        g_isConfirmResult = false;
+    }
+
+    DestroyEntityHandlerRequest(ehRequest);
+
+    return NULL;
+}
+
+static OCEntityHandlerRequest *CopyRequest(OCEntityHandlerRequest *entityHandlerRequest)
+{
+    OIC_LOG(INFO, TAG, "Copying received request for slow response");
+
+    if (!entityHandlerRequest)
+    {
+        OIC_LOG_V(ERROR, TAG, "%s: entityHandlerRequest is NULL", __func__);
+        return NULL;
+    }
+
+    OCEntityHandlerRequest *copyOfRequest =
+            (OCEntityHandlerRequest *)OICCalloc(1, sizeof(OCEntityHandlerRequest));
+    if(!copyOfRequest)
+    {
+        OIC_LOG(ERROR, TAG, "Copy failed due to allocation failure");
+        return NULL;
+    }
+
+    memcpy(copyOfRequest, entityHandlerRequest, sizeof(OCEntityHandlerRequest));
+
+    if (entityHandlerRequest->query)
+    {
+        copyOfRequest->query = OICStrdup(entityHandlerRequest->query);
+        if(!copyOfRequest->query)
+        {
+            OIC_LOG(ERROR, TAG, "Copy failed due to allocation failure");
+            OICFree(copyOfRequest);
+            return NULL;
+        }
+    }
+
+    if (entityHandlerRequest->payload)
+    {
+        copyOfRequest->payload =
+                (OCSecurityPayload *)OICCalloc(1, sizeof(OCSecurityPayload));
+        if(!copyOfRequest->payload)
+        {
+            OIC_LOG(ERROR, TAG, "Copy failed due to allocation failure");
+            OICFree(copyOfRequest->query);
+            OICFree(copyOfRequest);
+            return NULL;
+        }
+
+        if (((OCSecurityPayload *)entityHandlerRequest->payload)->payloadSize)
+        {
+            ((OCSecurityPayload *)copyOfRequest->payload)->securityData =
+                    (uint8_t *)OICCalloc(1, ((OCSecurityPayload *)entityHandlerRequest->payload)->payloadSize);
+            if(!((OCSecurityPayload *)copyOfRequest->payload)->securityData)
+            {
+                OIC_LOG(ERROR, TAG, "Copy failed due to allocation failure");
+                OICFree(copyOfRequest->payload);
+                OICFree(copyOfRequest->query);
+                OICFree(copyOfRequest);
+                return NULL;
+            }
+
+            memcpy(((OCSecurityPayload *)copyOfRequest->payload)->securityData,
+                  ((OCSecurityPayload *)entityHandlerRequest->payload)->securityData,
+                  ((OCSecurityPayload *)entityHandlerRequest->payload)->payloadSize);
+
+            ((OCSecurityPayload *)(copyOfRequest->payload))->payloadSize =
+                    ((OCSecurityPayload *)(entityHandlerRequest->payload))->payloadSize;
+        }
+
+        copyOfRequest->payload->type = entityHandlerRequest->payload->type;
+        copyOfRequest->messageID = entityHandlerRequest->messageID;
+    }
+
+    // Ignore vendor specific header options for example
+    copyOfRequest->numRcvdVendorSpecificHeaderOptions = 0;
+    copyOfRequest->rcvdVendorSpecificHeaderOptions = NULL;
+
+    OIC_LOG(INFO, TAG, "Copied client request");
+
+    return copyOfRequest;
+}
+#endif // defined(__WITH_DTLS__) || defined (__WITH_TLS__)
+
 static OCEntityHandlerResult HandleDoxmPostRequest(OCEntityHandlerRequest * ehRequest)
 {
     OIC_LOG (DEBUG, TAG, "Doxm EntityHandle  processing POST request");
@@ -1124,7 +1261,7 @@ static OCEntityHandlerResult HandleDoxmPostRequest(OCEntityHandlerRequest * ehRe
              * In case of other transport adapter, duplicate message check is not required.
              */
             if (OC_ADAPTER_IP == ehRequest->devAddr.adapter &&
-                 previousMsgId == ehRequest->messageID)
+                 previousMsgId == ehRequest->messageID && g_isConfirmResult == false)
             {
                 isDuplicatedMsg = true;
             }
@@ -1165,6 +1302,13 @@ static OCEntityHandlerResult HandleDoxmPostRequest(OCEntityHandlerRequest * ehRe
                     ehRet = OC_EH_NOT_ACCEPTABLE;
                     goto exit;
                 }
+
+                if(0 != memcmp(&gDoxm->owner.id, &newDoxm->owner.id, sizeof(gDoxm->owner.id)))
+                {
+                    OIC_LOG(ERROR, TAG, "Not acceptable request for owned property");
+                    ehRet = OC_EH_NOT_ACCEPTABLE;
+                }
+
                 //Update gDoxm based on newDoxm
                 updateWriteableProperty(newDoxm, gDoxm);
 
@@ -1473,25 +1617,48 @@ static OCEntityHandlerResult HandleDoxmPostRequest(OCEntityHandlerRequest * ehRe
 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
                 else if (OIC_MANUFACTURER_CERTIFICATE ==  newDoxm->oxmSel || OIC_CON_MFG_CERT == newDoxm->oxmSel)
                 {
-                    //Get user confirmation
-                    if (false == newDoxm->owned &&
-                        false == isDuplicatedMsg &&
-                        memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) != 0)
+                    if (CONFIRM_STATE_ACCEPTED != gConfirmState && CONFIRM_STATE_DENIED != gConfirmState)
                     {
-                        gConfirmMsgId = ehRequest->messageID;
-                        gConfirmState = CONFIRM_STATE_WAIT;
-                        if (OC_STACK_OK != VerifyOwnershipTransfer(NULL, USER_CONFIRM))
-                        {
-                            ehRet = OC_EH_NOT_ACCEPTABLE;
-                            gConfirmState = CONFIRM_STATE_DENIED;
-                            goto exit;
-                        }
-                        else
+                        //Get user confirmation
+                        if (false == newDoxm->owned &&
+                            false == isDuplicatedMsg &&
+                            memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) != 0)
                         {
-                            ehRet = OC_EH_OK;
-                            gConfirmState = CONFIRM_STATE_ACCEPTED;
+                            gConfirmMsgId = ehRequest->messageID;
+                            gConfirmState = CONFIRM_STATE_WAIT;
+
+                            if (OC_STACK_OK != VerifyUserConfirm())
+                            {
+                                if (OC_STACK_OK != VerifyOwnershipTransfer(NULL, USER_CONFIRM))
+                                {
+                                    ehRet = OC_EH_NOT_ACCEPTABLE;
+                                    gConfirmState = CONFIRM_STATE_DENIED;
+                                    goto exit;
+                                }
+                            }
+                            else
+                            {
+                                OCEntityHandlerRequest * ehRequestCopy = CopyRequest(ehRequest);
+                                VERIFY_NON_NULL(TAG, ehRequestCopy, ERROR);
+
+                                g_condWait = oc_cond_new();
+                                g_mutexWait = oc_mutex_new();
+                                if (oc_thread_new (&g_waitConfirmThreadId, WaitConfirm, ehRequestCopy))
+                                {
+                                    oc_thread_detach(g_waitConfirmThreadId);
+                                }
+
+                                previousMsgId = ehRequest->messageID;
+
+                                return OC_EH_SLOW;
+                            }
                         }
                     }
+                    else if (CONFIRM_STATE_DENIED == gConfirmState)
+                    {
+                        ehRet = OC_EH_NOT_ACCEPTABLE;
+                        goto exit;
+                    }
 
                     //Save the owner's UUID to derive owner credential
                     memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
@@ -1611,8 +1778,7 @@ exit:
                     InvokeOtmEventHandler(ehRequest->devAddr.addr, ehRequest->devAddr.port,
                                           NULL, OIC_OTM_ERROR);
 #endif
-                    RestoreDoxmToInitState();
-                    RestorePstatToInitState();
+                    ResetSecureResourceInPS();
                     OIC_LOG(WARNING, TAG, "DOXM will be reverted.");
                 }
             }