Merge branch 'plugin-interface' into master
[platform/upstream/iotivity.git] / resource / csdk / security / src / aclresource.c
index 1b858f8..6d20938 100644 (file)
@@ -41,7 +41,7 @@
 #include <strings.h>
 #endif
 
-#define TAG  PCF("SRM-ACL")
+#define TAG  "SRM-ACL"
 
 OicSecAcl_t               *gAcl = NULL;
 static OCResourceHandle    gAclHandle = NULL;
@@ -54,7 +54,7 @@ static void FreeACE(OicSecAcl_t *ace)
     size_t i;
     if(NULL == ace)
     {
-        OC_LOG (INFO, TAG, PCF("Invalid Parameter"));
+        OC_LOG (ERROR, TAG, "Invalid Parameter");
         return;
     }
 
@@ -65,14 +65,25 @@ static void FreeACE(OicSecAcl_t *ace)
     }
     OICFree(ace->resources);
 
-    //Clean Period & Recurrence
-    for(i = 0; i < ace->prdRecrLen; i++)
+    //Clean Period
+    if(ace->periods)
     {
-        OICFree(ace->periods[i]);
-        OICFree(ace->recurrences[i]);
+        for(i = 0; i < ace->prdRecrLen; i++)
+        {
+            OICFree(ace->periods[i]);
+        }
+        OICFree(ace->periods);
+    }
+
+    //Clean Recurrence
+    if(ace->recurrences)
+    {
+        for(i = 0; i < ace->prdRecrLen; i++)
+        {
+            OICFree(ace->recurrences[i]);
+        }
+        OICFree(ace->recurrences);
     }
-    OICFree(ace->periods);
-    OICFree(ace->recurrences);
 
     // Clean Owners
     OICFree(ace->owners);
@@ -331,6 +342,7 @@ OicSecAcl_t * JSONToAclBin(const char * jsonStr)
             {
                 VERIFY_SUCCESS(TAG, cJSON_Array == jsonRecurObj->type,
                                ERROR);
+
                 if(acl->prdRecrLen > 0)
                 {
                     acl->recurrences = (char**)OICCalloc(acl->prdRecrLen,
@@ -341,11 +353,12 @@ OicSecAcl_t * JSONToAclBin(const char * jsonStr)
                     for(size_t i = 0; i < acl->prdRecrLen; i++)
                     {
                         jsonRecur = cJSON_GetArrayItem(jsonRecurObj, i);
+                        VERIFY_NON_NULL(TAG, jsonRecur, ERROR);
                         jsonObjLen = strlen(jsonRecur->valuestring) + 1;
                         acl->recurrences[i] = (char*)OICMalloc(jsonObjLen);
                         VERIFY_NON_NULL(TAG, acl->recurrences[i], ERROR);
                         OICStrcpy(acl->recurrences[i], jsonObjLen,
-                                  jsonRecur->valuestring);
+                              jsonRecur->valuestring);
                     }
                 }
             }
@@ -409,6 +422,7 @@ static bool UpdatePersistentStorage(const OicSecAcl_t *acl)
     }
     return false;
 }
+
 /*
  * This method removes ACE for the subject and resource from the ACL
  *
@@ -423,7 +437,7 @@ static bool UpdatePersistentStorage(const OicSecAcl_t *acl)
 static OCStackResult RemoveACE(const OicUuid_t * subject,
                                const char * resource)
 {
-    OC_LOG(INFO, TAG, PCF("IN RemoveACE"));
+    OC_LOG(DEBUG, TAG, "IN RemoveACE");
 
     OicSecAcl_t *acl = NULL;
     OicSecAcl_t *tempAcl = NULL;
@@ -432,12 +446,12 @@ static OCStackResult RemoveACE(const OicUuid_t * subject,
 
     if(memcmp(subject->id, &WILDCARD_SUBJECT_ID, sizeof(subject->id)) == 0)
     {
-        OC_LOG_V (INFO, TAG, PCF("%s received invalid parameter"), __func__ );
+        OC_LOG_V (ERROR, TAG, "%s received invalid parameter", __func__ );
         return  OC_STACK_INVALID_PARAM;
     }
 
     //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,23 +519,147 @@ 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 (DEBUG, 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);
 
     OICFree(jsonStr);
 
-    OC_LOG_V (INFO, TAG, PCF("%s RetVal %d"), __func__ , ehRet);
+    OC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
     return ehRet;
 }
 
@@ -546,58 +684,35 @@ static OCEntityHandlerResult HandleACLPostRequest (const OCEntityHandlerRequest
     // Send payload to request originator
     SendSRMResponse(ehRequest, ehRet, NULL);
 
-    OC_LOG_V (INFO, TAG, PCF("%s RetVal %d"), __func__ , ehRet);
+    OC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
     return ehRet;
 }
 
 static OCEntityHandlerResult HandleACLDeleteRequest(const OCEntityHandlerRequest *ehRequest)
 {
-    OC_LOG (INFO, TAG, PCF("Processing ACLDeleteRequest"));
+    OC_LOG (DEBUG, 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);
-
-    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;
+    VERIFY_NON_NULL(TAG, ehRequest->query, ERROR);
 
-           b64Ret = b64Decode((char *)parseIter.valPos, parseIter.valLen, base64Buff,
-                               sizeof(base64Buff), &outLen);
+    // 'Subject' field is MUST for processing a querystring in REST request.
+    VERIFY_SUCCESS(TAG,
+            true == GetSubjectFromQueryString(ehRequest->query, &subject),
+            ERROR);
 
-           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;
 }
 
@@ -609,7 +724,7 @@ OCEntityHandlerResult ACLEntityHandler (OCEntityHandlerFlag flag,
                                         OCEntityHandlerRequest * ehRequest,
                                         void* callbackParameter)
 {
-    OC_LOG(INFO, TAG, PCF("Received request ACLEntityHandler"));
+    OC_LOG(DEBUG, TAG, "Received request ACLEntityHandler");
     (void)callbackParameter;
     OCEntityHandlerResult ehRet = OC_EH_ERROR;
 
@@ -620,8 +735,8 @@ OCEntityHandlerResult ACLEntityHandler (OCEntityHandlerFlag flag,
 
     if (flag & OC_REQUEST_FLAG)
     {
-        // TODO :  Handle PUT and DEL methods
-        OC_LOG (INFO, TAG, PCF("Flag includes OC_REQUEST_FLAG"));
+        // TODO :  Handle PUT method
+        OC_LOG (DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
         switch (ehRequest->method)
         {
             case OC_REST_GET:
@@ -662,7 +777,7 @@ OCStackResult CreateACLResource()
 
     if (OC_STACK_OK != ret)
     {
-        OC_LOG (FATAL, TAG, PCF("Unable to instantiate ACL resource"));
+        OC_LOG (FATAL, TAG, "Unable to instantiate ACL resource");
         DeInitACLResource();
     }
     return ret;
@@ -869,3 +984,34 @@ const OicSecAcl_t* GetACLResourceData(const OicUuid_t* subjectId, OicSecAcl_t **
     *savePtr = NULL;
     return NULL;
 }
+
+
+OCStackResult InstallNewACL(const char* newJsonStr)
+{
+    OCStackResult ret = OC_STACK_ERROR;
+
+    // Convert JSON ACL data into binary. This will also validate the ACL data received.
+    OicSecAcl_t* newAcl = JSONToAclBin(newJsonStr);
+
+    if (newAcl)
+    {
+        // Append the new ACL to existing ACL
+        LL_APPEND(gAcl, newAcl);
+
+        // Convert ACL data into JSON for update to persistent storage
+        char *jsonStr = BinToAclJSON(gAcl);
+        if (jsonStr)
+        {
+            cJSON *jsonAcl = cJSON_Parse(jsonStr);
+            OICFree(jsonStr);
+
+            if (jsonAcl)
+            {
+                ret = UpdateSVRDatabase(OIC_JSON_ACL_NAME, jsonAcl);
+            }
+            cJSON_Delete(jsonAcl);
+        }
+    }
+
+    return ret;
+}