[IOT-2465] Fix DELETE request impl for cred
authorAndrii Shtompel <a.shtompel@samsung.com>
Wed, 12 Jul 2017 11:50:10 +0000 (14:50 +0300)
committerRandeep Singh <randeep.s@samsung.com>
Wed, 19 Jul 2017 03:13:11 +0000 (03:13 +0000)
Verified using CTT 1.5.11 test CT1.7.9.3
DELETE delete all credentials return PASSED

Change-Id: Ie52c6af9fb9205a650b766acf0084e0ac2dcdcf1
Signed-off-by: Andrii Shtompel <a.shtompel@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/21403
Reviewed-by: Aleksey Volkov <a.volkov@samsung.com>
Tested-by: jenkins-iotivity <jenkins@iotivity.org>
Reviewed-by: Nathan Heldt-Sheller <nathan.heldt-sheller@intel.com>
Reviewed-by: Oleksii Beketov <ol.beketov@samsung.com>
Reviewed-by: Randeep Singh <randeep.s@samsung.com>
resource/csdk/security/src/credresource.c

index bfe88d5..26a7d94 100644 (file)
@@ -100,6 +100,29 @@ typedef enum CredCompareResult{
     CRED_CMP_ERROR = 2
 }CredCompareResult_t;
 
+typedef struct CredIdList CredIdList_t;
+
+struct CredIdList
+{
+    uint16_t credId;
+    CredIdList_t *next;
+};
+
+static void DeleteCredIdList(CredIdList_t** list)
+{
+    if (list)
+    {
+        CredIdList_t *head = *list;
+
+        while (head)
+        {
+            CredIdList_t *tmp = head->next;
+            OICFree(head);
+            head = tmp;
+        }
+    }
+}
+
 static bool ValueWithinBounds(uint64_t value, uint64_t maxValue)
 {
     if (value > maxValue)
@@ -1838,7 +1861,7 @@ exit:
 
 OCStackResult RemoveCredential(const OicUuid_t *subject)
 {
-    OCStackResult ret = OC_STACK_RESOURCE_DELETED;
+    OCStackResult ret = OC_STACK_ERROR;
     OicSecCred_t *cred = NULL;
     OicSecCred_t *tempCred = NULL;
     bool deleteFlag = false;
@@ -1855,13 +1878,12 @@ OCStackResult RemoveCredential(const OicUuid_t *subject)
 
     if (deleteFlag)
     {
-        if (!UpdatePersistentStorage(gCred))
+        if (UpdatePersistentStorage(gCred))
         {
-            ret = OC_STACK_ERROR;
+            ret = OC_STACK_RESOURCE_DELETED;
         }
     }
     return ret;
-
 }
 
 OCStackResult RemoveCredentialByCredId(uint16_t credId)
@@ -1901,7 +1923,115 @@ OCStackResult RemoveCredentialByCredId(uint16_t credId)
     OIC_LOG(INFO, TAG, "OUT RemoveCredentialByCredId");
 
     return ret;
+}
 
+/**
+ * This method removes cred's corresponding to given list of credid's from the Cred
+ *
+ * @param credid's of the Cred
+ *
+ * @return
+ *     ::OC_STACK_RESOURCE_DELETED on success
+ *     ::OC_STACK_NO_RESOURCE on failure to find the appropriate Cred
+ *     ::OC_STACK_INVALID_PARAM on invalid parameter
+ */
+static OCStackResult RemoveCredentialByCredIds(CredIdList_t *credIdList)
+{
+    OCStackResult ret = OC_STACK_ERROR;
+    OicSecCred_t *cred = NULL;
+    OicSecCred_t *tempCred = NULL;
+    CredIdList_t *credIdElem = NULL;
+    bool deleteFlag = false;
+
+    OIC_LOG(INFO, TAG, "IN RemoveCredentialByCredIds");
+
+    LL_FOREACH(credIdList, credIdElem)
+    {
+        LL_FOREACH_SAFE(gCred, cred, tempCred)
+        {
+            if (cred->credId == credIdElem->credId)
+            {
+                OIC_LOG_V(DEBUG, TAG, "Credential(ID=%d) will be removed.", cred->credId);
+
+                LL_DELETE(gCred, cred);
+                FreeCred(cred);
+                deleteFlag = true;
+                //TODO: add break when cred's will have unique credid (during IOT-2464 fix)
+            }
+        }
+    }
+
+    if (deleteFlag)
+    {
+        if (UpdatePersistentStorage(gCred))
+        {
+            ret = OC_STACK_RESOURCE_DELETED;
+        }
+    }
+    OIC_LOG(INFO, TAG, "OUT RemoveCredentialByCredIds");
+
+    return ret;
+}
+
+/**
+ * This method parses the query string received for REST requests and
+ * retrieves the 'credid' field.
+ *
+ * @param query querystring passed in REST request
+ * @param credid cred id parsed from query string
+ *
+ * @return true if query parsed successfully and found 'credid', else false.
+ */
+static bool GetCredIdsFromQueryString(const char *query, CredIdList_t **credid)
+{
+    bool found = false;
+    OicParseQueryIter_t parseIter = { .attrPos = NULL };
+
+    ParseQueryIterInit((unsigned char *) query, &parseIter);
+
+    while (GetNextQuery (&parseIter))
+    {
+        if (strncasecmp((char *) parseIter.attrPos, OIC_JSON_CREDID_NAME, parseIter.attrLen) == 0)
+        {
+            VERIFY_SUCCESS(TAG, 0 != parseIter.valLen, ERROR);
+
+            //parse credid array value in format "1,2,3"
+            unsigned char *str = parseIter.valPos;
+
+            //remember last symbol (may be '\0' or '&')
+            unsigned char tmp = str[parseIter.valLen];
+            //set last symbol to '\0' to use strtok_r
+            str[parseIter.valLen] = '\0';
+
+            char *saveptr = NULL;
+
+            for (; ; str = NULL)
+            {
+                char *token = strtok_r((char *)str, ",", &saveptr);
+                if (NULL == token)
+                {
+                    break;
+                }
+
+                CredIdList_t *newCredIdElem = (CredIdList_t *) OICCalloc(1, sizeof(CredIdList_t));
+                if (NULL == newCredIdElem)
+                {
+                    OIC_LOG(ERROR, TAG, "Failed to allocate CredIdList_t element");
+                    break;
+                }
+                newCredIdElem->credId = (uint16_t)atoi(token);
+
+                LL_PREPEND(*credid, newCredIdElem);
+                found = true;
+            }
+
+            //restore last symbol
+            parseIter.valPos[parseIter.valLen] = tmp;
+        }
+    }
+
+exit:
+    return found;
 }
 
 /**
@@ -1911,7 +2041,7 @@ OCStackResult RemoveCredentialByCredId(uint16_t credId)
  *     OC_STACK_OK              - no errors
  *     OC_STACK_ERROR           - stack process error
  */
-OCStackResult RemoveAllCredentials(void)
+static OCStackResult RemoveAllCredentials()
 {
     DeleteCredList(gCred);
     gCred = GetCredDefault();
@@ -1923,6 +2053,41 @@ OCStackResult RemoveAllCredentials(void)
     return OC_STACK_OK;
 }
 
+/**
+ * This method parses the query string received for REST requests and
+ * retrieves the 'subjectuuid' field.
+ *
+ * @param query querystring passed in REST request
+ * @param subject subject UUID parsed from query string
+ *
+ * @return true if query parsed successfully and found 'subject', else false.
+ */
+static bool GetSubjectFromQueryString(const char *query, OicUuid_t *subject)
+{
+    OicParseQueryIter_t parseIter = { .attrPos = NULL };
+
+    ParseQueryIterInit((unsigned char *) query, &parseIter);
+
+    while (GetNextQuery (&parseIter))
+    {
+        if (strncasecmp((char *) parseIter.attrPos, OIC_JSON_SUBJECTID_NAME, parseIter.attrLen) == 0)
+        {
+            VERIFY_SUCCESS(TAG, 0 != parseIter.valLen, ERROR);
+            //temporary set '\0' symbol instead of copy string
+            char tmp = parseIter.valPos[parseIter.valLen];
+            parseIter.valPos[parseIter.valLen] = '\0';
+
+            OCStackResult res = ConvertStrToUuid((const char*)parseIter.valPos, subject);
+            parseIter.valPos[parseIter.valLen] = tmp;
+            VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
+            return true;
+        }
+    }
+
+exit:
+    return false;
+}
+
 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
 /**
  * Internal function to fill private data of owner PSK.
@@ -2401,35 +2566,40 @@ static OCEntityHandlerResult HandleDeleteRequest(const OCEntityHandlerRequest *e
     OIC_LOG(DEBUG, TAG, "Processing CredDeleteRequest");
 
     OCEntityHandlerResult ehRet = OC_EH_ERROR;
+    CredIdList_t *credIdList = NULL;
+    OicUuid_t subject = { .id= { 0 } };
 
     if (NULL == ehRequest->query)
     {
         return ehRet;
     }
 
-    OicParseQueryIter_t parseIter = { .attrPos=NULL };
-    OicUuid_t subject = {.id={0}};
-
-    //Parsing REST query to get the subject
-    ParseQueryIterInit((unsigned char *)ehRequest->query, &parseIter);
-    while (GetNextQuery(&parseIter))
+    if (GetCredIdsFromQueryString(ehRequest->query, &credIdList))
     {
-        if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_SUBJECTID_NAME,
-                parseIter.attrLen) == 0)
+        if (OC_STACK_RESOURCE_DELETED == RemoveCredentialByCredIds(credIdList))
         {
-            OCStackResult ret = ConvertStrToUuid((const char*)parseIter.valPos, &subject);
-            VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
+            ehRet = OC_EH_RESOURCE_DELETED;
         }
+        DeleteCredIdList(&credIdList);
     }
-
-    if (OC_STACK_RESOURCE_DELETED == RemoveCredential(&subject))
+    else if (GetSubjectFromQueryString(ehRequest->query, &subject))
     {
-        ehRet = OC_EH_RESOURCE_DELETED;
+        if (OC_STACK_RESOURCE_DELETED == RemoveCredential(&subject))
+        {
+            ehRet = OC_EH_RESOURCE_DELETED;
+        }
     }
+    else
+    {
+        if (OC_STACK_OK == RemoveAllCredentials())
+        {
+            ehRet = OC_EH_RESOURCE_DELETED;
+        }
+    }
+
     //Send response to request originator
     ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
                    OC_EH_OK : OC_EH_ERROR;
-exit:
     return ehRet;
 }
 
@@ -2451,7 +2621,7 @@ OCEntityHandlerResult CredEntityHandler(OCEntityHandlerFlag flag,
         switch (ehRequest->method)
         {
             case OC_REST_GET:
-                ret = HandleGetRequest(ehRequest);;
+                ret = HandleGetRequest(ehRequest);
                 break;
             case OC_REST_PUT:
             case OC_REST_POST: