Merge branch 'master' into security-summit
[platform/upstream/iotivity.git] / resource / csdk / security / src / aclresource.c
index 3a18703..5515fc6 100644 (file)
@@ -437,7 +437,7 @@ static OCStackResult RemoveACE(const OicUuid_t * subject,
     }
 
     //If resource is NULL then delete all the ACE for the subject.
-    if(NULL == resource)
+    if(NULL == resource || resource[0] == '\0')
     {
         LL_FOREACH_SAFE(gAcl, acl, tempAcl)
         {
@@ -505,16 +505,139 @@ static OCStackResult RemoveACE(const OicUuid_t * subject,
     return ret;
 }
 
+/*
+ * This method parses the query string received for REST requests and
+ * retrieves the 'subject' 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_SUBJECT_NAME, parseIter.attrLen) == 0)
+        {
+            VERIFY_SUCCESS(TAG, 0 != parseIter.valLen, ERROR);
+            unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
+            uint32_t outLen = 0;
+            B64Result b64Ret = B64_OK;
+            b64Ret = b64Decode((char *)parseIter.valPos, parseIter.valLen, base64Buff,
+                    sizeof(base64Buff), &outLen);
+            VERIFY_SUCCESS(TAG, (B64_OK == b64Ret && outLen <= sizeof(subject->id)), ERROR);
+            memcpy(subject->id, base64Buff, outLen);
+
+            return true;
+        }
+    }
+
+exit:
+   return false;
+}
+
+/*
+ * This method parses the query string received for REST requests and
+ * retrieves the 'resource' field.
+ *
+ * @param query querystring passed in REST request
+ * @param resource resource parsed from query string
+ * @param resourceSize size of the memory pointed to resource
+ *
+ * @return true if query parsed successfully and found 'resource', else false.
+ */
+static bool GetResourceFromQueryString(const char *query, char *resource, size_t resourceSize)
+{
+    OicParseQueryIter_t parseIter = {.attrPos=NULL};
+
+    ParseQueryIterInit((unsigned char *)query, &parseIter);
+
+    while(GetNextQuery(&parseIter))
+    {
+        if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_RESOURCES_NAME, parseIter.attrLen) == 0)
+        {
+            VERIFY_SUCCESS(TAG, 0 != parseIter.valLen, ERROR);
+            OICStrcpy(resource, resourceSize, (char *)parseIter.valPos);
+
+            return true;
+        }
+    }
+
+exit:
+   return false;
+}
+
+
+
 static OCEntityHandlerResult HandleACLGetRequest (const OCEntityHandlerRequest * ehRequest)
 {
-    // Convert ACL data into JSON for transmission
-    char* jsonStr = BinToAclJSON(gAcl);
+    OCEntityHandlerResult ehRet = OC_EH_ERROR;
+    char* jsonStr = NULL;
 
-    /*
-     * A device should 'always' have a default ACL. Therefore,
-     * jsonStr should never be NULL.
-     */
-    OCEntityHandlerResult ehRet = (jsonStr ? OC_EH_OK : OC_EH_ERROR);
+    // Process the REST querystring parameters
+    if(ehRequest->query)
+    {
+        OC_LOG (INFO, TAG, "HandleACLGetRequest processing query");
+
+        OicUuid_t subject = {.id={0}};
+        char resource[MAX_URI_LENGTH] = {0};
+
+        OicSecAcl_t *savePtr = NULL;
+        const OicSecAcl_t *currentAce = NULL;
+
+        // 'Subject' field is MUST for processing a querystring in REST request.
+        VERIFY_SUCCESS(TAG,
+                       true == GetSubjectFromQueryString(ehRequest->query, &subject),
+                       ERROR);
+
+        GetResourceFromQueryString(ehRequest->query, resource, sizeof(resource));
+
+        /*
+         * TODO : Currently, this code only provides one ACE for a Subject.
+         * Below code needs to be updated for scenarios when Subject have
+         * multiple ACE's in ACL resource.
+         */
+        while((currentAce = GetACLResourceData(&subject, &savePtr)))
+        {
+            /*
+             * If REST querystring contains a specific resource, we need
+             * to search for that resource in ACE.
+             */
+            if (resource[0] != '\0')
+            {
+                for(size_t n = 0; n < currentAce->resourcesLen; n++)
+                {
+                    if((currentAce->resources[n]) &&
+                            (0 == strcmp(resource, currentAce->resources[n]) ||
+                             0 == strcmp(WILDCARD_RESOURCE_URI, currentAce->resources[n])))
+                    {
+                        // Convert ACL data into JSON for transmission
+                        jsonStr = BinToAclJSON(currentAce);
+                        goto exit;
+                    }
+                }
+            }
+            else
+            {
+                // Convert ACL data into JSON for transmission
+                jsonStr = BinToAclJSON(currentAce);
+                goto exit;
+            }
+        }
+    }
+    else
+    {
+        // Convert ACL data into JSON for transmission
+        jsonStr = BinToAclJSON(gAcl);
+    }
+
+exit:
+    ehRet = (jsonStr ? OC_EH_OK : OC_EH_ERROR);
 
     // Send response payload to request originator
     SendSRMResponse(ehRequest, ehRet, jsonStr);
@@ -554,50 +677,27 @@ static OCEntityHandlerResult HandleACLDeleteRequest(const OCEntityHandlerRequest
 {
     OC_LOG (INFO, TAG, "Processing ACLDeleteRequest");
     OCEntityHandlerResult ehRet = OC_EH_ERROR;
-
-    if(NULL == ehRequest->query)
-    {
-        return ehRet;
-    }
-    OicParseQueryIter_t parseIter = {.attrPos=NULL};
     OicUuid_t subject = {.id={0}};
-    char * resource = NULL;
+    char resource[MAX_URI_LENGTH] = {0};
 
-    //Parsing REST query to get subject & resource
-    ParseQueryIterInit((unsigned char *)ehRequest->query, &parseIter);
+    VERIFY_NON_NULL(TAG, ehRequest->query, ERROR);
 
-    while(GetNextQuery(&parseIter))
-    {
-        if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_SUBJECT_NAME, parseIter.attrLen) == 0)
-        {
-            unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
-            uint32_t outLen = 0;
-            B64Result b64Ret = B64_OK;
+    // 'Subject' field is MUST for processing a querystring in REST request.
+    VERIFY_SUCCESS(TAG,
+            true == GetSubjectFromQueryString(ehRequest->query, &subject),
+            ERROR);
 
-           b64Ret = b64Decode((char *)parseIter.valPos, parseIter.valLen, base64Buff,
-                               sizeof(base64Buff), &outLen);
-
-           VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(subject.id)), ERROR);
-           memcpy(subject.id, base64Buff, outLen);
-        }
-        if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_RESOURCES_NAME, parseIter.attrLen) == 0)
-        {
-            resource = (char *)OICMalloc(parseIter.valLen);
-            VERIFY_NON_NULL(TAG, resource, ERROR);
-            OICStrcpy(resource, sizeof(resource), (char *)parseIter.valPos);
-        }
-    }
+    GetResourceFromQueryString(ehRequest->query, resource, sizeof(resource));
 
     if(OC_STACK_RESOURCE_DELETED == RemoveACE(&subject, resource))
     {
         ehRet = OC_EH_RESOURCE_DELETED;
     }
-    OICFree(resource);
 
+exit:
     // Send payload to request originator
     SendSRMResponse(ehRequest, ehRet, NULL);
 
-exit:
     return ehRet;
 }
 
@@ -620,7 +720,7 @@ OCEntityHandlerResult ACLEntityHandler (OCEntityHandlerFlag flag,
 
     if (flag & OC_REQUEST_FLAG)
     {
-        // TODO :  Handle PUT and DEL methods
+        // TODO :  Handle PUT method
         OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
         switch (ehRequest->method)
         {