replace : iotivity -> iotivity-sec
[platform/upstream/iotivity.git] / resource / csdk / security / src / aclresource.c
index e3aef30..f557a09 100644 (file)
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
+#include "iotivity_config.h"
 #ifdef HAVE_STRING_H
 #include <string.h>
-#elif HAVE_STRINGS_H
+#elif defined(HAVE_STRINGS_H)
 #include <strings.h>
 #endif
 #include <stdlib.h>
 #include "resourcemanager.h"
 #include "srmutility.h"
 #include "psinterface.h"
+#include "ocpayloadcbor.h"
 
 #include "security_internals.h"
 
-#define TAG  "SRM-ACL"
-#define NUMBER_OF_SEC_PROV_RSCS 4
+#define TAG  "OIC_SRM_ACL"
+#define NUMBER_OF_SEC_PROV_RSCS 3
 #define NUMBER_OF_DEFAULT_SEC_RSCS 2
 #define STRING_UUID_SIZE (UUID_LENGTH * 2 + 5)
 
-static const uint8_t ACL_MAP_SIZE = 2;
+static const uint8_t ACL_MAP_SIZE = 4;
 static const uint8_t ACL_ACLIST_MAP_SIZE = 1;
 static const uint8_t ACL_ACES_MAP_SIZE = 3;
-static const uint8_t ACL_RESOURCE_MAP_SIZE = 4;
+static const uint8_t ACL_RESOURCE_MAP_SIZE = 3;
 
 
 // CborSize is the default cbor payload size being used.
-static const uint16_t CBOR_SIZE = 2048;
+static const uint16_t CBOR_SIZE = 2048*8;
 
 static OicSecAcl_t *gAcl = NULL;
 static OCResourceHandle gAclHandle = NULL;
 
-/**
- * This function frees OicSecRsrc_t object's fields and object itself.
- */
-static void FreeRsrc(OicSecRsrc_t *rsrc)
+void FreeRsrc(OicSecRsrc_t *rsrc)
 {
     //Clean each member of resource
     OICFree(rsrc->href);
@@ -133,6 +132,10 @@ static void FreeACE(OicSecAce_t *ace)
         validity = NULL;
     }
 
+#ifdef MULTIPLE_OWNER
+    OICFree(ace->eownerID);
+#endif
+
     //Clean ACE
     OICFree(ace);
     ace = NULL;
@@ -253,6 +256,18 @@ OicSecAce_t* DuplicateACE(const OicSecAce_t* ace)
             }
         }
 
+#ifdef MULTIPLE_OWNER
+        if (ace->eownerID)
+        {
+            if (NULL == newAce->eownerID)
+            {
+                newAce->eownerID = (OicUuid_t*)OICCalloc(1, sizeof(OicUuid_t));
+                VERIFY_NON_NULL(TAG, (newAce->eownerID), ERROR);
+            }
+            memcpy(newAce->eownerID->id, ace->eownerID->id, sizeof(ace->eownerID->id));
+        }
+#endif
+
         newAce->next = NULL;
     }
 
@@ -347,7 +362,15 @@ OCStackResult AclToCBORPayload(const OicSecAcl_t *secAcl, uint8_t **payload, siz
             {
                 aclMapSize++;
             }
+            validityElts = validityElts->next;
+        }
+
+#ifdef MULTIPLE_OWNER
+        if(ace->eownerID)
+        {
+            aclMapSize++;
         }
+#endif //MULTIPLE_OWNER
 
         cborEncoderResult = cbor_encoder_create_map(&acesArray, &oicSecAclMap, aclMapSize);
         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Creating ACES Map");
@@ -396,7 +419,13 @@ OCStackResult AclToCBORPayload(const OicSecAcl_t *secAcl, uint8_t **payload, siz
             {
 
                 CborEncoder rMap;
-                cborEncoderResult = cbor_encoder_create_map(&resources, &rMap, ACL_RESOURCE_MAP_SIZE);
+                size_t rsrcMapSize = ACL_RESOURCE_MAP_SIZE;
+                if(rsrc->rel)
+                {
+                    rsrcMapSize++;
+                }
+
+                cborEncoderResult = cbor_encoder_create_map(&resources, &rMap, rsrcMapSize);
                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Resource Map.");
 
                 //href -- Mandatory
@@ -448,14 +477,6 @@ OCStackResult AclToCBORPayload(const OicSecAcl_t *secAcl, uint8_t **payload, siz
                     cborEncoderResult = cbor_encode_text_string(&rMap, rsrc->rel, strlen(rsrc->rel));
                     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding REL Value.");
                 }
-                else
-                {
-                    cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_REL_NAME,
-                            strlen(OIC_JSON_REL_NAME));
-                    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding REL Name Tag.");
-                    cborEncoderResult = cbor_encode_text_string(&rMap, "", 0);
-                    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding REL Value.");
-                }
 
                 cborEncoderResult = cbor_encoder_close_container(&resources, &rMap);
                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Resource Map.");
@@ -541,6 +562,22 @@ OCStackResult AclToCBORPayload(const OicSecAcl_t *secAcl, uint8_t **payload, siz
             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Validities Array.");
         }
 
+#ifdef MULTIPLE_OWNER
+        // Eownerid -- Not Mandatory
+        if(ace->eownerID)
+        {
+            char *eowner = NULL;
+            cborEncoderResult = cbor_encode_text_string(&oicSecAclMap, OIC_JSON_EOWNERID_NAME,
+                strlen(OIC_JSON_EOWNERID_NAME));
+            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding eownerId Name Tag.");
+            ret = ConvertUuidToStr(ace->eownerID, &eowner);
+            VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
+            cborEncoderResult = cbor_encode_text_string(&oicSecAclMap, eowner, strlen(eowner));
+            OICFree(eowner);
+            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding eownerId Value.");
+        }
+#endif //MULTIPLE_OWNER
+
         cborEncoderResult = cbor_encoder_close_container(&acesArray, &oicSecAclMap);
         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing ACES Map.");
     }
@@ -566,6 +603,38 @@ OCStackResult AclToCBORPayload(const OicSecAcl_t *secAcl, uint8_t **payload, siz
         OICFree(rowner);
     }
 
+    //RT -- Mandatory
+    CborEncoder rtArray;
+    cborEncoderResult = cbor_encode_text_string(&aclMap, OIC_JSON_RT_NAME,
+            strlen(OIC_JSON_RT_NAME));
+    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Name Tag.");
+    cborEncoderResult = cbor_encoder_create_array(&aclMap, &rtArray, 1);
+    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Value.");
+    for (size_t i = 0; i < 1; i++)
+    {
+        cborEncoderResult = cbor_encode_text_string(&rtArray, OIC_RSRC_TYPE_SEC_ACL,
+                strlen(OIC_RSRC_TYPE_SEC_ACL));
+        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding RT Value.");
+    }
+    cborEncoderResult = cbor_encoder_close_container(&aclMap, &rtArray);
+    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing RT.");
+
+    //IF-- Mandatory
+    CborEncoder ifArray;
+    cborEncoderResult = cbor_encode_text_string(&aclMap, OIC_JSON_IF_NAME,
+             strlen(OIC_JSON_IF_NAME));
+    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Name Tag.");
+    cborEncoderResult = cbor_encoder_create_array(&aclMap, &ifArray, 1);
+    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Value.");
+    for (size_t i = 0; i < 1; i++)
+    {
+        cborEncoderResult = cbor_encode_text_string(&ifArray, OC_RSRVD_INTERFACE_DEFAULT,
+                strlen(OC_RSRVD_INTERFACE_DEFAULT));
+        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding IF Value.");
+    }
+    cborEncoderResult = cbor_encoder_close_container(&aclMap, &ifArray);
+    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing IF.");
+
     // Close ACL Map
     cborEncoderResult = cbor_encoder_close_container(&encoder, &aclMap);
     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing ACL Map.");
@@ -573,7 +642,7 @@ OCStackResult AclToCBORPayload(const OicSecAcl_t *secAcl, uint8_t **payload, siz
     if (CborNoError == cborEncoderResult)
     {
         OIC_LOG(DEBUG, TAG, "AclToCBORPayload Successed");
-        *size = encoder.ptr - outPayload;
+        *size = cbor_encoder_get_buffer_size(&encoder, outPayload);
         *payload = outPayload;
         ret = OC_STACK_OK;
     }
@@ -585,7 +654,7 @@ exit:
         // reallocate and try again!
         OICFree(outPayload);
         // Since the allocated initial memory failed, double the memory.
-        cborLen += encoder.ptr - encoder.end;
+        cborLen += cbor_encoder_get_buffer_size(&encoder, encoder.end);
         cborEncoderResult = CborNoError;
         ret = AclToCBORPayload(secAcl, payload, &cborLen);
         *size = cborLen;
@@ -605,6 +674,311 @@ exit:
 
 // This function converts CBOR format to ACL data.
 // Caller needs to invoke 'free' when done using
+// It parses { "aclist" : [ { ... } ] } instead of { "aclist" : { "aces" : [ ] } }
+OicSecAcl_t* CBORPayloadToAcl2(const uint8_t *cborPayload, const size_t size)
+{
+    if (NULL == cborPayload || 0 == size)
+    {
+        return NULL;
+    }
+    OCStackResult ret = OC_STACK_ERROR;
+    CborValue aclCbor = { .parser = NULL };
+    CborParser parser = { .end = NULL };
+    CborError cborFindResult = CborNoError;
+    cbor_parser_init(cborPayload, size, 0, &parser, &aclCbor);
+
+    OicSecAcl_t *acl = (OicSecAcl_t *) OICCalloc(1, sizeof(OicSecAcl_t));
+    VERIFY_NON_NULL(TAG, acl, ERROR);
+
+    // Enter ACL Map
+    CborValue aclMap = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
+    cborFindResult = cbor_value_enter_container(&aclCbor, &aclMap);
+    VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering ACL Map.");
+
+    while (cbor_value_is_valid(&aclMap))
+    {
+        char* tagName = NULL;
+        size_t len = 0;
+        CborType type = cbor_value_get_type(&aclMap);
+        if (type == CborTextStringType)
+        {
+            cborFindResult = cbor_value_dup_text_string(&aclMap, &tagName, &len, NULL);
+            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Name in ACL Map.");
+            cborFindResult = cbor_value_advance(&aclMap);
+            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Value in ACL Map.");
+        }
+        if(tagName)
+        {
+            if (strcmp(tagName, OIC_JSON_ACLIST_NAME)  == 0)
+            {
+                // Enter ACES Array
+                CborValue acesArray = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
+                cborFindResult = cbor_value_enter_container(&aclMap, &acesArray);
+                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering ACES Array.");
+
+                int acesCount = 0;
+                while (cbor_value_is_valid(&acesArray))
+                {
+                    acesCount++;
+                    CborValue aceMap = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
+                    cborFindResult = cbor_value_enter_container(&acesArray, &aceMap);
+                    VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering ACE Map.");
+
+                    OicSecAce_t *ace = NULL;
+                    ace = (OicSecAce_t *) OICCalloc(1, sizeof(OicSecAce_t));
+                    VERIFY_NON_NULL(TAG, ace, ERROR);
+                    LL_APPEND(acl->aces, ace);
+
+                    while (cbor_value_is_valid(&aceMap))
+                    {
+                        char* name = NULL;
+                        size_t len = 0;
+                        CborType type = cbor_value_get_type(&aceMap);
+                        if (type == CborTextStringType)
+                        {
+                            cborFindResult = cbor_value_dup_text_string(&aceMap, &name, &len, NULL);
+                            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Name in ACE Map.");
+                            cborFindResult = cbor_value_advance(&aceMap);
+                            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Value in ACE Map.");
+                        }
+                        if (name)
+                        {
+                            // Subject -- Mandatory
+                            if (strcmp(name, OIC_JSON_SUBJECTID_NAME)  == 0)
+                            {
+                                char *subject = NULL;
+                                cborFindResult = cbor_value_dup_text_string(&aceMap, &subject, &len, NULL);
+                                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding subject Value.");
+                                if(strcmp(subject, WILDCARD_RESOURCE_URI) == 0)
+                                {
+                                    ace->subjectuuid.id[0] = '*';
+                                }
+                                else
+                                {
+                                    OIC_LOG_V(DEBUG, TAG, "Converting subjectuuid = %s to uuid...", subject);
+                                    ret = ConvertStrToUuid(subject, &ace->subjectuuid);
+                                    VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
+                                }
+                                OICFree(subject);
+                            }
+
+                            // Resources -- Mandatory
+                            if (strcmp(name, OIC_JSON_RESOURCES_NAME) == 0)
+                            {
+                                CborValue resources = { .parser = NULL };
+                                cborFindResult = cbor_value_enter_container(&aceMap, &resources);
+                                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering a Resource Array.");
+
+                                while (cbor_value_is_valid(&resources))
+                                {
+                                    // rMap
+                                    CborValue rMap = { .parser = NULL  };
+                                    cborFindResult = cbor_value_enter_container(&resources, &rMap);
+                                    VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering Resource Map");
+
+                                    OicSecRsrc_t* rsrc = (OicSecRsrc_t*)OICCalloc(1, sizeof(OicSecRsrc_t));
+                                    VERIFY_NON_NULL(TAG, rsrc, ERROR);
+                                    LL_APPEND(ace->resources, rsrc);
+
+                                    while(cbor_value_is_valid(&rMap))
+                                    {
+                                        char *rMapName = NULL;
+                                        size_t rMapNameLen = 0;
+                                        cborFindResult = cbor_value_dup_text_string(&rMap, &rMapName, &rMapNameLen, NULL);
+                                        VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding RMap Data Name Tag.");
+                                        cborFindResult = cbor_value_advance(&rMap);
+                                        VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding RMap Data Value.");
+
+                                        // "href"
+                                        if (0 == strcmp(OIC_JSON_HREF_NAME, rMapName))
+                                        {
+                                            cborFindResult = cbor_value_dup_text_string(&rMap, &rsrc->href, &len, NULL);
+                                            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Href Value.");
+                                        }
+
+                                        // "rt"
+                                        if (0 == strcmp(OIC_JSON_RT_NAME, rMapName) && cbor_value_is_array(&rMap))
+                                        {
+                                            cbor_value_get_array_length(&rMap, &rsrc->typeLen);
+                                            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding RT array length.");
+                                            VERIFY_SUCCESS(TAG, (0 != rsrc->typeLen), ERROR);
+
+                                            rsrc->types = (char**)OICCalloc(rsrc->typeLen, sizeof(char*));
+                                            VERIFY_NON_NULL(TAG, rsrc->types, ERROR);
+
+                                            CborValue resourceTypes;
+                                            cborFindResult = cbor_value_enter_container(&rMap, &resourceTypes);
+                                            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering RT Array.");
+
+                                            for(size_t i = 0; cbor_value_is_valid(&resourceTypes) && cbor_value_is_text_string(&resourceTypes); i++)
+                                            {
+                                                size_t readLen = 0;
+                                                cborFindResult = cbor_value_dup_text_string(&resourceTypes, &(rsrc->types[i]), &readLen, NULL);
+                                                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding resource type.");
+                                                cborFindResult = cbor_value_advance(&resourceTypes);
+                                                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing resource type.");
+                                            }
+                                        }
+
+                                        // "if"
+                                        if (0 == strcmp(OIC_JSON_IF_NAME, rMapName) && cbor_value_is_array(&rMap))
+                                        {
+                                            cbor_value_get_array_length(&rMap, &rsrc->interfaceLen);
+                                            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding IF array length.");
+                                            VERIFY_SUCCESS(TAG, (0 != rsrc->interfaceLen), ERROR);
+
+                                            rsrc->interfaces = (char**)OICCalloc(rsrc->interfaceLen, sizeof(char*));
+                                            VERIFY_NON_NULL(TAG, rsrc->interfaces, ERROR);
+
+                                            CborValue interfaces;
+                                            cborFindResult = cbor_value_enter_container(&rMap, &interfaces);
+                                            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering IF Array.");
+
+                                            for(size_t i = 0; cbor_value_is_valid(&interfaces) && cbor_value_is_text_string(&interfaces); i++)
+                                            {
+                                                size_t readLen = 0;
+                                                cborFindResult = cbor_value_dup_text_string(&interfaces, &(rsrc->interfaces[i]), &readLen, NULL);
+                                                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding IF type.");
+                                                cborFindResult = cbor_value_advance(&interfaces);
+                                                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing IF type.");
+                                            }
+                                        }
+
+                                        // "rel"
+                                        if (0 == strcmp(OIC_JSON_REL_NAME, rMapName))
+                                        {
+                                            cborFindResult = cbor_value_dup_text_string(&rMap, &rsrc->rel, &len, NULL);
+                                            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding REL Value.");
+                                        }
+
+                                        if (cbor_value_is_valid(&rMap))
+                                        {
+                                            cborFindResult = cbor_value_advance(&rMap);
+                                            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Rlist Map.");
+                                        }
+                                        OICFree(rMapName);
+                                    }
+
+                                    if (cbor_value_is_valid(&resources))
+                                    {
+                                        cborFindResult = cbor_value_advance(&resources);
+                                        VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Resource Array.");
+                                    }
+                                }
+                            }
+
+                            // Permissions -- Mandatory
+                            if (strcmp(name, OIC_JSON_PERMISSION_NAME) == 0)
+                            {
+                                uint64_t tmp64;
+                                cborFindResult = cbor_value_get_uint64(&aceMap, &tmp64);
+                                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a PERM Value.");
+                                ace->permission = (uint16_t)tmp64;
+                            }
+
+                            // TODO: Need to verfication for validity
+                            // Validity -- Not mandatory
+                            if(strcmp(name, OIC_JSON_VALIDITY_NAME) == 0)
+                            {
+                                CborValue validitiesMap = {.parser = NULL};
+                                size_t validitySize = 0;
+
+                                cborFindResult = cbor_value_get_array_length(&aceMap, &validitySize);
+                                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a Validity Array Length.");
+
+                                cborFindResult = cbor_value_enter_container(&aceMap, &validitiesMap);
+                                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a validity Array Map.");
+
+                                while(cbor_value_is_valid(&validitiesMap))
+                                {
+                                    OicSecValidity_t* validity = (OicSecValidity_t*)OICCalloc(1, sizeof(OicSecValidity_t));
+                                    VERIFY_NON_NULL(TAG, validity, ERROR);
+                                    LL_APPEND(ace->validities, validity);
+
+                                    CborValue validityMap  = {.parser = NULL};
+                                    //period (string)
+                                    cborFindResult = cbor_value_enter_container(&validitiesMap, &validityMap);
+                                    VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a validity Map.");
+
+                                    size_t len = 0;
+                                    cborFindResult =cbor_value_dup_text_string(&validityMap, &validity->period, &len, NULL);
+                                    VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a Period value.");
+
+                                    //recurrence (string array)
+                                    CborValue recurrenceMap  = {.parser = NULL};
+                                    cborFindResult = cbor_value_enter_container(&validityMap, &recurrenceMap);
+                                    VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a recurrence array.");
+
+                                    cborFindResult = cbor_value_get_array_length(&recurrenceMap, &validity->recurrenceLen);
+                                    VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Adding Recurrence Array.");
+
+                                    validity->recurrences = (char**)OICCalloc(validity->recurrenceLen, sizeof(char*));
+                                    VERIFY_NON_NULL(TAG, validity->recurrences, ERROR);
+
+                                    for(size_t i = 0; cbor_value_is_text_string(&recurrenceMap) && i < validity->recurrenceLen; i++)
+                                    {
+                                        cborFindResult = cbor_value_dup_text_string(&recurrenceMap, &validity->recurrences[i], &len, NULL);
+                                        VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a recurrence Value.");
+
+                                        cborFindResult = cbor_value_advance(&recurrenceMap);
+                                        VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing a recurrences Array.");
+                                    }
+
+                                    cborFindResult = cbor_value_advance(&validitiesMap);
+                                    VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing a validities Array.");
+                                }
+                            }
+                            OICFree(name);
+                        }
+
+                        if (type != CborMapType && cbor_value_is_valid(&aceMap))
+                        {
+                            cborFindResult = cbor_value_advance(&aceMap);
+                            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing the Array.");
+                        }
+                    }
+
+                    if (cbor_value_is_valid(&acesArray))
+                    {
+                        cborFindResult = cbor_value_advance(&acesArray);
+                        VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing ACL Array.");
+                    }
+                }
+            }
+
+            //rownerID -- Mandatory
+            if (strcmp(tagName, OIC_JSON_ROWNERID_NAME)  == 0)
+            {
+                char *stRowner = NULL;
+                cborFindResult = cbor_value_dup_text_string(&aclMap, &stRowner, &len, NULL);
+                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Rownerid Value.");
+                OIC_LOG_V(DEBUG, TAG, "Converting rownerid = %s to uuid...", stRowner);
+                ret = ConvertStrToUuid(stRowner, &acl->rownerID);
+                VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
+                OICFree(stRowner);
+            }
+            OICFree(tagName);
+        }
+        if (cbor_value_is_valid(&aclMap))
+        {
+            cborFindResult = cbor_value_advance(&aclMap);
+            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing ACL Map.");
+        }
+    }
+
+exit:
+    if (cborFindResult != CborNoError)
+    {
+        OIC_LOG(ERROR, TAG, "Failed to CBORPayloadToAcl");
+        DeleteACLList(acl);
+        acl = NULL;
+    }
+
+    return acl;
+}
+
+// This function converts CBOR format to ACL data.
+// Caller needs to invoke 'free' when done using
 // note: This function is used in unit test hence not declared static,
 OicSecAcl_t* CBORPayloadToAcl(const uint8_t *cborPayload, const size_t size)
 {
@@ -613,15 +987,17 @@ OicSecAcl_t* CBORPayloadToAcl(const uint8_t *cborPayload, const size_t size)
         return NULL;
     }
     OCStackResult ret = OC_STACK_ERROR;
+    CborValue aclMap = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
     CborValue aclCbor = { .parser = NULL };
     CborParser parser = { .end = NULL };
     CborError cborFindResult = CborNoError;
+
     cbor_parser_init(cborPayload, size, 0, &parser, &aclCbor);
 
     OicSecAcl_t *acl = (OicSecAcl_t *) OICCalloc(1, sizeof(OicSecAcl_t));
+    VERIFY_NON_NULL(TAG, acl, ERROR);
 
     // Enter ACL Map
-    CborValue aclMap = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
     cborFindResult = cbor_value_enter_container(&aclCbor, &aclMap);
     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering ACL Map.");
 
@@ -646,7 +1022,6 @@ OicSecAcl_t* CBORPayloadToAcl(const uint8_t *cborPayload, const size_t size)
                 cborFindResult = cbor_value_enter_container(&aclMap, &aclistMap);
                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering ACLIST Map.");
 
-
                 while (cbor_value_is_valid(&aclistMap))
                 {
                     char* acName = NULL;
@@ -682,8 +1057,6 @@ OicSecAcl_t* CBORPayloadToAcl(const uint8_t *cborPayload, const size_t size)
                                 VERIFY_NON_NULL(TAG, ace, ERROR);
                                 LL_APPEND(acl->aces, ace);
 
-                                VERIFY_NON_NULL(TAG, acl, ERROR);
-
                                 while (cbor_value_is_valid(&aceMap))
                                 {
                                     char* name = NULL;
@@ -880,6 +1253,24 @@ OicSecAcl_t* CBORPayloadToAcl(const uint8_t *cborPayload, const size_t size)
                                                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing a validities Array.");
                                             }
                                         }
+
+#ifdef MULTIPLE_OWNER
+                                        // eowner uuid -- Not Mandatory
+                                        if (strcmp(name, OIC_JSON_EOWNERID_NAME)  == 0)
+                                        {
+                                            char *eowner = NULL;
+                                            cborFindResult = cbor_value_dup_text_string(&aceMap, &eowner, &len, NULL);
+                                            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding eownerId Value.");
+                                            if(NULL == ace->eownerID)
+                                            {
+                                                ace->eownerID = (OicUuid_t*)OICCalloc(1, sizeof(OicUuid_t));
+                                                VERIFY_NON_NULL(TAG, ace->eownerID, ERROR);
+                                            }
+                                            ret = ConvertStrToUuid(eowner, ace->eownerID);
+                                            OICFree(eowner);
+                                            VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
+                                        }
+#endif //MULTIPLE_OWNER
                                         OICFree(name);
                                     }
 
@@ -918,6 +1309,10 @@ OicSecAcl_t* CBORPayloadToAcl(const uint8_t *cborPayload, const size_t size)
                 VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
                 OICFree(stRowner);
             }
+            else if (NULL != gAcl)
+            {
+                memcpy(&(acl->rownerID), &(gAcl->rownerID), sizeof(OicUuid_t));
+            }
             OICFree(tagName);
         }
         if (cbor_value_is_valid(&aclMap))
@@ -938,6 +1333,48 @@ exit:
     return acl;
 }
 
+#ifdef MULTIPLE_OWNER
+bool IsValidAclAccessForSubOwner(const OicUuid_t* uuid, const uint8_t *cborPayload, const size_t size)
+{
+    bool retValue = false;
+    OicSecAcl_t* acl = NULL;
+
+    VERIFY_NON_NULL(TAG, uuid, ERROR);
+    VERIFY_NON_NULL(TAG, cborPayload, ERROR);
+    VERIFY_SUCCESS(TAG, 0 != size, ERROR);
+
+    acl = CBORPayloadToAcl(cborPayload, size);
+    VERIFY_NON_NULL(TAG, acl, ERROR);
+
+    OicSecAce_t* ace = NULL;
+    OicSecAce_t* tempAce = NULL;
+    LL_FOREACH_SAFE(acl->aces, ace, tempAce)
+    {
+        OicSecRsrc_t* rsrc = NULL;
+        OicSecRsrc_t* tempRsrc = NULL;
+
+        VERIFY_NON_NULL(TAG, ace->eownerID, ERROR);
+        VERIFY_SUCCESS(TAG, memcmp(ace->eownerID->id, uuid->id, sizeof(uuid->id)) == 0, ERROR);
+
+        LL_FOREACH_SAFE(ace->resources, rsrc, tempRsrc)
+        {
+            VERIFY_SUCCESS(TAG, strcmp(rsrc->href, OIC_RSRC_TYPE_SEC_DOXM) != 0, ERROR);
+            VERIFY_SUCCESS(TAG, strcmp(rsrc->href, OIC_RSRC_TYPE_SEC_CRED) != 0, ERROR);
+            VERIFY_SUCCESS(TAG, strcmp(rsrc->href, OIC_RSRC_TYPE_SEC_ACL) != 0, ERROR);
+            VERIFY_SUCCESS(TAG, strcmp(rsrc->href, OIC_RSRC_TYPE_SEC_PSTAT) != 0, ERROR);
+            VERIFY_SUCCESS(TAG, strcmp(rsrc->href, OIC_RSRC_TYPE_SEC_CRL) != 0, ERROR);
+        }
+    }
+
+    retValue = true;
+
+exit:
+    DeleteACLList(acl);
+
+    return retValue;
+}
+#endif //MULTIPLE_OWNER
+
 /**
  * This method removes ACE for the subject and resource from the ACL
  *
@@ -953,6 +1390,12 @@ OCStackResult RemoveACE(const OicUuid_t * subject, const char * resource)
 {
     OIC_LOG(DEBUG, TAG, "IN RemoveACE");
 
+    if (!gAcl)
+    {
+        OIC_LOG_V(ERROR, TAG, "%s: gAcl is NULL", __func__);
+        return OC_STACK_INVALID_PARAM;
+    }
+
     OicSecAce_t *ace = NULL;
     OicSecAce_t *tempAce = NULL;
     bool deleteFlag = false;
@@ -1098,32 +1541,343 @@ exit:
    return false;
 }
 
-static OCEntityHandlerResult HandleACLGetRequest(const OCEntityHandlerRequest *ehRequest)
+static size_t GetNumberOfResource(OicSecRsrc_t* resources)
 {
-    OIC_LOG(INFO, TAG, "HandleACLGetRequest processing the request");
-    uint8_t* payload = NULL;
-    size_t size = 0;
-    OCEntityHandlerResult ehRet;
+    size_t ret = 0;
+    if(resources)
+    {
+        OicSecRsrc_t* rsrc = NULL;
+        LL_FOREACH(resources, rsrc)
+        {
+            ret++;
+        }
+    }
+    return ret;
+}
 
-    OicUuid_t subject = {.id= { 0 } };
+static size_t GetNumberOfValidity(OicSecValidity_t* val)
+{
+    size_t ret = 0;
 
-    // In case, 'subject' field is included in REST request.
-    if (ehRequest->query && GetSubjectFromQueryString(ehRequest->query, &subject))
+    if(val)
     {
-        OIC_LOG(DEBUG,TAG,"'subject' field is inculded in REST request.");
-        OIC_LOG(DEBUG, TAG, "HandleACLGetRequest processing query");
+        OicSecValidity_t* temp = NULL;
+        LL_FOREACH(val, temp)
+        {
+            ret++;
+        }
+    }
+    return ret;
+}
 
-        char resource[MAX_URI_LENGTH] = { 0 };
 
-        OicSecAce_t *savePtr = NULL;
-        const OicSecAce_t *currentAce = NULL;
-        OicSecAcl_t targetAcl;
+static bool IsSameStringArray(char** strArr1, size_t strArr1Len,
+                              char** strArr2, size_t strArr2Len)
+{
 
-        memcpy(&targetAcl.rownerID, &gAcl->rownerID, sizeof(OicUuid_t));
-        targetAcl.aces = NULL;
+    if(NULL == strArr1 && NULL == strArr2)
+    {
+        return true;
+    }
 
-        // 'Subject' field is MUST for processing a querystring in REST request.
-        GetResourceFromQueryString(ehRequest->query, resource, sizeof(resource));
+    if(strArr1 && strArr2 && NULL == *strArr1 && NULL == *strArr2)
+    {
+        return true;
+    }
+
+    if(strArr1 && strArr2)
+    {
+        if(*strArr1 && *strArr2 && strArr1Len == strArr2Len)
+        {
+            size_t matchedStr = 0;
+            for(size_t i = 0; i < strArr1Len; i++)
+            {
+                for(size_t j = 0; j < strArr2Len; j++)
+                {
+                    if(strcmp(strArr1[i], strArr2[j]) == 0)
+                    {
+                        matchedStr++;
+                    }
+                }
+            }
+            if(matchedStr == strArr1Len)
+            {
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+static bool IsSameResources(OicSecRsrc_t* resources1, OicSecRsrc_t* resources2)
+{
+    size_t numOfRsrc1 = 0;
+    size_t numOfRsrc2 = 0;
+    size_t numOfMatchedRsrc = 0;
+    OicSecRsrc_t* rsrc1 = NULL;
+    OicSecRsrc_t* rsrc2 = NULL;
+
+    if(NULL == resources1 && NULL == resources2)
+    {
+        return true;
+    }
+
+    if(resources1 && resources2)
+    {
+        numOfRsrc1 = GetNumberOfResource(resources1);
+        numOfRsrc2 = GetNumberOfResource(resources2);
+
+        if(0 == numOfRsrc1 && 0 == numOfRsrc2)
+        {
+            return true;
+        }
+
+        LL_FOREACH(resources1, rsrc1)
+        {
+            rsrc2 = NULL;
+            LL_FOREACH(resources2, rsrc2)
+            {
+                if(rsrc1 && rsrc2)
+                {
+                    if(strcmp(rsrc1->href, rsrc2->href) == 0 &&
+                        IsSameStringArray(rsrc1->interfaces, rsrc1->interfaceLen,
+                                          rsrc2->interfaces, rsrc2->interfaceLen) &&
+                        IsSameStringArray(rsrc1->types, rsrc1->typeLen,
+                                          rsrc2->types, rsrc2->typeLen))
+                    {
+                        // TODO: Update codes to compare 'rel' property
+                        numOfMatchedRsrc++;
+                    }
+                }
+            }
+        }
+
+        if(numOfMatchedRsrc == numOfRsrc1)
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+static bool IsSameValidities(OicSecValidity_t* validities1, OicSecValidity_t* validities2)
+{
+    size_t numOfVal1 = 0;
+    size_t numOfVal2 = 0;
+    size_t numOfMatchedVal = 0;
+    OicSecValidity_t* val1 = NULL;
+    OicSecValidity_t* val2 = NULL;
+
+    if(NULL == validities1 && NULL == validities2)
+    {
+        return true;
+    }
+
+    if(validities1 && validities2)
+    {
+        numOfVal1 = GetNumberOfValidity(validities1);
+        numOfVal2 = GetNumberOfValidity(validities2);
+        if(0 == numOfVal1 && 0 == numOfVal2)
+        {
+            return true;
+        }
+
+        if(numOfVal1 == numOfVal2)
+        {
+            LL_FOREACH(validities1, val1)
+            {
+                LL_FOREACH(validities2, val2)
+                {
+                    if(strcmp(val1->period, val2->period) == 0 &&
+                        IsSameStringArray(val1->recurrences, val1->recurrenceLen,
+                                          val2->recurrences, val2->recurrenceLen))
+                    {
+                        numOfMatchedVal++;
+                    }
+                }
+            }
+            if(numOfVal1 == numOfMatchedVal)
+            {
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+#ifdef MULTIPLE_OWNER
+static bool IsSameEowner(OicUuid_t* eowner1, OicUuid_t* eowner2)
+{
+    if (NULL != eowner1 && NULL != eowner2)
+    {
+        if (memcmp(eowner1->id, eowner2->id, sizeof(eowner1->id)) == 0)
+        {
+            return true;
+        }
+    }
+    else if (NULL == eowner1 && NULL == eowner2)
+    {
+        OIC_LOG(DEBUG, TAG, "Both eowner1 and eowner2 are NULL");
+        return true;
+    }
+
+    return false;
+}
+#endif
+
+static bool IsSameACE(OicSecAce_t* ace1, OicSecAce_t* ace2)
+{
+    if(ace1 && ace2)
+    {
+        if(memcmp(ace1->subjectuuid.id, ace2->subjectuuid.id, sizeof(ace1->subjectuuid.id)) != 0)
+        {
+            return false;
+        }
+
+        if(false == IsSameResources(ace1->resources, ace2->resources))
+        {
+            return false;
+        }
+
+        if(ace1->permission != ace2->permission)
+        {
+            return false;
+        }
+
+        if(false == IsSameValidities(ace1->validities, ace2->validities))
+        {
+            return false;
+        }
+
+#ifdef MULTIPLE_OWNER
+        if(false == IsSameEowner(ace1->eownerID, ace2->eownerID))
+        {
+            return false;
+        }
+#endif
+
+        return true;
+    }
+
+    return false;
+}
+
+/**
+ * Internal function to remove all ACL data on ACL resource and persistent storage
+ *
+ * @retval
+ *     OC_STACK_RESOURCE_DELETED  - no errors
+ *     Otherwise                  - error
+ */
+static OCStackResult RemoveAllAce(void)
+{
+    OCStackResult ret = OC_STACK_ERROR;
+    uint8_t* aclBackup = NULL;
+    size_t backupSize = 0;
+    uint8_t* payload = NULL;
+    size_t size = 0;
+    OicSecAce_t* aceItem = NULL;
+    OicSecAce_t* tempAce = NULL;
+
+    OIC_LOG(INFO, TAG, "IN RemoveAllAce");
+
+    //Backup the current ACL
+    ret = AclToCBORPayload(gAcl, &aclBackup, &backupSize);
+    if(OC_STACK_OK == ret)
+    {
+        // Remove all ACE from ACL
+        LL_FOREACH_SAFE(gAcl->aces, aceItem, tempAce)
+        {
+            LL_DELETE(gAcl->aces, aceItem);
+            FreeACE(aceItem);
+        }
+
+        //Generate empty ACL payload
+        ret = AclToCBORPayload(gAcl, &payload, &size);
+        if (OC_STACK_OK == ret )
+        {
+            //Update the PS.
+            ret = UpdateSecureResourceInPS(OIC_JSON_ACL_NAME, payload, size);
+            if (OC_STACK_OK != ret)
+            {
+                OIC_LOG_V(ERROR, TAG, "Error in UpdateSecureResourceInPS : %d", ret);
+            }
+        }
+
+        if(OC_STACK_OK != ret)
+        {
+            OIC_LOG_V(ERROR, TAG, "Error while DELETE ACE : %d", ret);
+
+            //If some erorr is occured, revert back.
+            OicSecAcl_t* originAcl = CBORPayloadToAcl(aclBackup, backupSize);
+            if( originAcl )
+            {
+                ret = UpdateSecureResourceInPS(OIC_JSON_ACL_NAME, aclBackup, backupSize);
+                if (OC_STACK_OK == ret)
+                {
+                    DeleteACLList(gAcl);
+                    gAcl = originAcl;
+                }
+                else
+                {
+                    OIC_LOG_V(ERROR, TAG, "Error in UpdateSecureResourceInPS : %d", ret);
+                }
+            }
+            else
+            {
+                OIC_LOG(FATAL, TAG, "Error in CBORPayloadToAcl");
+                ret = OC_STACK_ERROR;
+            }
+        }
+    }
+
+    OICFree(aclBackup);
+    OICFree(payload);
+
+    OIC_LOG(INFO, TAG, "OUT RemoveAllAce");
+
+    return (OC_STACK_OK == ret ? OC_STACK_RESOURCE_DELETED : ret);
+}
+
+static OCEntityHandlerResult HandleACLGetRequest(const OCEntityHandlerRequest *ehRequest)
+{
+    OIC_LOG(INFO, TAG, "HandleACLGetRequest processing the request");
+
+    uint8_t* payload = NULL;
+    size_t size = 0;
+    OCEntityHandlerResult ehRet;
+
+    OicUuid_t subject = {.id= { 0 } };
+
+    // In case, 'subject' field is included in REST request.
+    if (ehRequest->query && GetSubjectFromQueryString(ehRequest->query, &subject))
+    {
+        OIC_LOG(DEBUG,TAG,"'subject' field is inculded in REST request.");
+        OIC_LOG(DEBUG, TAG, "HandleACLGetRequest processing query");
+
+        char resource[MAX_URI_LENGTH] = { 0 };
+
+        OicSecAce_t *savePtr = NULL;
+        const OicSecAce_t *currentAce = NULL;
+        OicSecAcl_t targetAcl;
+
+        if (NULL != gAcl)
+        {
+            memcpy(&targetAcl.rownerID, &gAcl->rownerID, sizeof(OicUuid_t));
+        }
+        else
+        {
+            OIC_LOG_V(ERROR, TAG, "%s: gAcl is NULL", __func__);
+            goto exit;
+        }
+
+        targetAcl.aces = NULL;
+
+        // 'Subject' field is MUST for processing a querystring in REST request.
+        GetResourceFromQueryString(ehRequest->query, resource, sizeof(resource));
 
         /*
          * TODO : Currently, this code only provides one ACE for a Subject.
@@ -1179,13 +1933,13 @@ static OCEntityHandlerResult HandleACLGetRequest(const OCEntityHandlerRequest *e
 exit:
     // A device should always have a default acl. Therefore, payload should never be NULL.
     ehRet = (payload ? OC_EH_OK : OC_EH_ERROR);
+    OIC_LOG(DEBUG, TAG, "ACL payload with GET response");
+    OIC_LOG_BUFFER(DEBUG, TAG, payload, size);
+
+    //Send payload to request originator
+    ehRet = ((SendSRMResponse(ehRequest, ehRet, payload, size)) == OC_STACK_OK) ?
+                   OC_EH_OK : OC_EH_ERROR;
 
-    // Send response payload to request originator
-    if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, payload, size))
-    {
-        ehRet = OC_EH_ERROR;
-        OIC_LOG(ERROR, TAG, "SendSRMResponse failed for HandleACLGetRequest");
-    }
     OICFree(payload);
 
     OIC_LOG_V(DEBUG, TAG, "%s RetVal %d", __func__, ehRet);
@@ -1195,46 +1949,86 @@ exit:
 static OCEntityHandlerResult HandleACLPostRequest(const OCEntityHandlerRequest *ehRequest)
 {
     OIC_LOG(INFO, TAG, "HandleACLPostRequest processing the request");
-    OCEntityHandlerResult ehRet = OC_EH_ERROR;
+    OCEntityHandlerResult ehRet = OC_EH_OK;
 
     // Convert CBOR into ACL data and update to SVR buffers. This will also validate the ACL data received.
     uint8_t *payload = ((OCSecurityPayload *) ehRequest->payload)->securityData;
     size_t size = ((OCSecurityPayload *) ehRequest->payload)->payloadSize;
     if (payload)
     {
-        OicSecAcl_t *newAcl = CBORPayloadToAcl(payload, size);
-        if (newAcl)
+        OicSecAcl_t *newAcl = NULL;
+        OIC_LOG(DEBUG, TAG, "ACL payload from POST request << ");
+        OIC_LOG_BUFFER(DEBUG, TAG, payload, size);
+
+        newAcl = CBORPayloadToAcl(payload, size);
+        if (NULL != newAcl && NULL != gAcl)
         {
-            // Append the new ACL to existing ACL
+            bool isNewAce = true;
+            OicSecAce_t* existAce = NULL;
             OicSecAce_t* newAce = NULL;
-            OicSecAce_t* tempAce = NULL;
-            LL_FOREACH_SAFE(newAcl->aces, newAce, tempAce)
+            OicSecAce_t* tempAce1 = NULL;
+            OicSecAce_t* tempAce2 = NULL;
+
+            LL_FOREACH_SAFE(newAcl->aces, newAce, tempAce1)
             {
-                LL_APPEND(gAcl->aces, newAce);
+                isNewAce = true;
+                LL_FOREACH_SAFE(gAcl->aces, existAce, tempAce2)
+                {
+                    if(IsSameACE(newAce, existAce))
+                    {
+                        isNewAce = false;
+                    }
+                }
+                if(isNewAce)
+                {
+                    OIC_LOG(DEBUG, TAG, "NEW ACE dectected.");
+
+                    OicSecAce_t* insertAce = DuplicateACE(newAce);
+                    if(insertAce)
+                    {
+                        OIC_LOG(DEBUG, TAG, "Appending new ACE..");
+                        LL_PREPEND(gAcl->aces, insertAce);
+                    }
+                    else
+                    {
+                        OIC_LOG(ERROR, TAG, "Failed to duplicate ACE.");
+                        ehRet = OC_EH_ERROR;
+                    }
+                }
             }
-            newAcl->aces = NULL;
+            memcpy(&(gAcl->rownerID), &(newAcl->rownerID), sizeof(OicUuid_t));
 
-            size_t size = 0;
-            uint8_t *cborPayload = NULL;
-            if (OC_STACK_OK == AclToCBORPayload(gAcl, &cborPayload, &size))
+            DeleteACLList(newAcl);
+
+            if(OC_EH_OK == ehRet)
             {
-                if (UpdateSecureResourceInPS(OIC_JSON_ACL_NAME, cborPayload, size) == OC_STACK_OK)
+                size_t size = 0;
+                uint8_t *cborPayload = NULL;
+
+                if (OC_STACK_OK == AclToCBORPayload(gAcl, &cborPayload, &size))
+                {
+                    if (UpdateSecureResourceInPS(OIC_JSON_ACL_NAME, cborPayload, size) == OC_STACK_OK)
+                    {
+                        ehRet = OC_EH_CHANGED;
+                    }
+                    OICFree(cborPayload);
+                }
+
+                if(OC_EH_CHANGED != ehRet)
                 {
-                    ehRet = OC_EH_RESOURCE_CREATED;
+                    ehRet = OC_EH_ERROR;
                 }
-                OICFree(cborPayload);
             }
         }
-
-        DeleteACLList(newAcl);
+        else
+        {
+            OIC_LOG_V(ERROR, TAG, "%s: %s", __func__, (NULL == newAcl) ? "no new ACL" : "gAcl is NULL");
+        }
     }
 
-    // Send payload to request originator
-    if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL, 0))
-    {
-        ehRet = OC_EH_ERROR;
-        OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandleACLPostRequest");
-    }
+    //Send response to request originator
+    ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
+                   OC_EH_OK : OC_EH_ERROR;
 
     OIC_LOG_V(DEBUG, TAG, "%s RetVal %d", __func__, ehRet);
     return ehRet;
@@ -1249,23 +2043,31 @@ static OCEntityHandlerResult HandleACLDeleteRequest(const OCEntityHandlerRequest
 
     VERIFY_NON_NULL(TAG, ehRequest->query, ERROR);
 
-    // '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));
+    // If 'Subject' field exist, processing a querystring in REST request.
+    if(GetSubjectFromQueryString(ehRequest->query, &subject))
+    {
+        GetResourceFromQueryString(ehRequest->query, resource, sizeof(resource));
 
-    if (OC_STACK_RESOURCE_DELETED == RemoveACE(&subject, resource))
+        if (OC_STACK_RESOURCE_DELETED == RemoveACE(&subject, resource))
+        {
+            ehRet = OC_EH_RESOURCE_DELETED;
+        }
+    }
+    // If 'subject field not exist, remove all ACL data from ACL resource
+    else
     {
-        ehRet = OC_EH_RESOURCE_DELETED;
+        OIC_LOG(WARNING, TAG, "Can not find the 'subject' in querystring, All ACL list will be removed.");
+
+        if(OC_STACK_RESOURCE_DELETED == RemoveAllAce())
+        {
+            ehRet = OC_EH_RESOURCE_DELETED;
+        }
     }
 
 exit:
-    // Send payload to request originator
-    if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL, 0))
-    {
-        ehRet = OC_EH_ERROR;
-        OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandleACLDeleteRequest");
-    }
+    //Send response to request originator
+    ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
+                   OC_EH_OK : OC_EH_ERROR;
 
     return ehRet;
 }
@@ -1301,8 +2103,8 @@ OCEntityHandlerResult ACLEntityHandler(OCEntityHandlerFlag flag, OCEntityHandler
                 break;
 
             default:
-                ehRet = OC_EH_ERROR;
-                SendSRMResponse(ehRequest, ehRet, NULL, 0);
+                ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
+                               OC_EH_OK : OC_EH_ERROR;
         }
     }
 
@@ -1322,7 +2124,7 @@ static OCStackResult CreateACLResource()
                            OIC_RSRC_ACL_URI,
                            ACLEntityHandler,
                            NULL,
-                           OC_OBSERVABLE | OC_SECURE | OC_EXPLICIT_DISCOVERABLE);
+                           OC_SECURE);
 
     if (OC_STACK_OK != ret)
     {
@@ -1531,6 +2333,7 @@ OCStackResult InitACLResource()
     {
         // Read ACL resource from PS
         gAcl = CBORPayloadToAcl(data, size);
+        OICFree(data);
     }
     /*
      * If SVR database in persistent storage got corrupted or
@@ -1577,7 +2380,7 @@ const OicSecAce_t* GetACLResourceData(const OicUuid_t* subjectId, OicSecAce_t **
     OicSecAce_t *ace = NULL;
     OicSecAce_t *begin = NULL;
 
-    if (NULL == subjectId)
+    if (NULL == subjectId || NULL == savePtr || NULL == gAcl)
     {
         return NULL;
     }
@@ -1621,34 +2424,223 @@ const OicSecAce_t* GetACLResourceData(const OicUuid_t* subjectId, OicSecAce_t **
     return NULL;
 }
 
-OCStackResult InstallNewACL(const uint8_t *cborPayload, const size_t size)
+void printACL(const OicSecAcl_t* acl)
+{
+    OIC_LOG(INFO, TAG, "Print ACL:");
+
+    if (NULL == acl)
+    {
+        OIC_LOG(INFO, TAG, "Received NULL acl");
+        return;
+    }
+
+    char *rowner = NULL;
+    if (OC_STACK_OK == ConvertUuidToStr(&acl->rownerID, &rowner))
+    {
+        OIC_LOG_V(INFO, TAG, "rowner id = %s", rowner);
+    }
+    else
+    {
+        OIC_LOG(ERROR, TAG, "Can't convert rowner uuid to string");
+    }
+    OICFree(rowner);
+
+    const OicSecAce_t *ace = acl->aces;
+    int ace_count = 0;
+    while (ace)
+    {
+        ace_count++;
+        OIC_LOG_V(INFO, TAG, "Print ace[%d]:", ace_count);
+
+        OIC_LOG_V(INFO, TAG, "ace permission = %d", ace->permission);
+
+        char *subjectuuid = NULL;
+        if (OC_STACK_OK == ConvertUuidToStr(&ace->subjectuuid, &subjectuuid))
+        {
+            OIC_LOG_V(INFO, TAG, "ace subject uuid = %s", subjectuuid);
+        }
+        else
+        {
+            OIC_LOG(ERROR, TAG, "Can't convert subjectuuid to string");
+        }
+        OICFree(subjectuuid);
+
+        OicSecRsrc_t *res = ace->resources;
+        int res_count = 0;
+        while (res)
+        {
+            res_count++;
+            OIC_LOG_V(INFO, TAG, "Print resources[%d]:", res_count);
+
+            OIC_LOG_V(INFO, TAG, "href = %s", res->href);
+
+            for (size_t i = 0; i < res->typeLen; i++)
+            {
+                OIC_LOG_V(INFO, TAG, "if[%zu] = %s", i, res->types[i]);
+            }
+            for (size_t i = 0; i < res->interfaceLen; i++)
+            {
+                OIC_LOG_V(INFO, TAG, "if[%zu] = %s", i, res->interfaces[i]);
+            }
+
+            res= res->next;
+        }
+
+        OicSecValidity_t *vals = ace->validities;
+        int vals_count = 0;
+        while (vals)
+        {
+            vals_count++;
+            OIC_LOG_V(INFO, TAG, "Print validities[%d]:", vals_count);
+
+            OIC_LOG_V(INFO, TAG, "period = %s", vals->period);
+            for (size_t i = 0; i < vals->recurrenceLen; i++)
+            {
+                OIC_LOG_V(INFO, TAG, "recurrences[%zu] = %s", i, vals->recurrences[i]);
+            }
+        }
+
+        ace = ace->next;
+    }
+}
+
+OCStackResult AppendACL2(const OicSecAcl_t* acl)
 {
     OCStackResult ret = OC_STACK_ERROR;
 
+    OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
+
+    if (!acl)
+    {
+        OIC_LOG_V(ERROR, TAG, "%s: acl is NULL", __func__);
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    if (!gAcl)
+    {
+        OIC_LOG_V(ERROR, TAG, "%s: gAcl is NULL", __func__);
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    // Append the new ACE to existing ACE list
+    // Can't use LL_APPEND because it sets ace->next to NULL
+    OicSecAce_t* ace = gAcl->aces;
+    if (ace)
+    {
+        while (ace->next)
+        {
+            ace = ace->next;
+        }
+        ace->next = acl->aces;
+    }
+    else
+    {
+        gAcl->aces = acl->aces;
+    }
+
+    printACL(gAcl);
+
+    size_t size = 0;
+    uint8_t *payload = NULL;
+    ret = AclToCBORPayload(gAcl, &payload, &size);
+    if (OC_STACK_OK == ret)
+    {
+        ret = UpdateSecureResourceInPS(OIC_JSON_ACL_NAME, payload, size);
+        OICFree(payload);
+    }
+
+    OIC_LOG_V(DEBUG, TAG, "OUT: %s", __func__);
+
+    return ret;
+}
+
+OCStackResult AppendACL(const uint8_t *cborPayload, const size_t size)
+{
     // Convert CBOR format to ACL data. This will also validate the ACL data received.
     OicSecAcl_t* newAcl = CBORPayloadToAcl(cborPayload, size);
 
-    if (newAcl)
+    return AppendACL2(newAcl);
+}
+
+OCStackResult InstallACL(const OicSecAcl_t* acl)
+{
+    OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
+
+    OCStackResult ret = OC_STACK_ERROR;
+
+    if (!acl)
+    {
+        OIC_LOG_V(ERROR, TAG, "%s: acl is NULL", __func__);
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    if (!gAcl)
+    {
+        OIC_LOG_V(ERROR, TAG, "%s: gAcl is NULL", __func__);
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    bool isNewAce = true;
+    OicSecAce_t* existAce = NULL;
+    OicSecAce_t* newAce = NULL;
+    OicSecAce_t* tempAce1 = NULL;
+    OicSecAce_t* tempAce2 = NULL;
+    OicSecAcl_t* newInstallAcl = NULL;
+
+    LL_FOREACH_SAFE(acl->aces, newAce, tempAce1)
     {
-        // Append the new ACL to existing ACL
-        OicSecAce_t* newAce = NULL;
-        LL_FOREACH(newAcl->aces, newAce)
+        isNewAce = true;
+        LL_FOREACH_SAFE(gAcl->aces, existAce, tempAce2)
         {
-            LL_APPEND(gAcl->aces, newAce);
+            if(IsSameACE(newAce, existAce))
+            {
+                OIC_LOG(DEBUG, TAG, "Duplicated ACE dectected.");
+                ret = OC_STACK_DUPLICATE_REQUEST;
+                isNewAce = false;
+            }
         }
-
-        size_t size = 0;
-        uint8_t *payload = NULL;
-        if (OC_STACK_OK == AclToCBORPayload(gAcl, &payload, &size))
+        if(isNewAce)
         {
-            if (UpdateSecureResourceInPS(OIC_JSON_ACL_NAME, payload, size) == OC_STACK_OK)
+            // Append new ACE to existing ACL
+            OIC_LOG(DEBUG, TAG, "NEW ACE dectected.");
+
+            OicSecAce_t* insertAce = DuplicateACE(newAce);
+            if(insertAce)
+            {
+                OIC_LOG(DEBUG, TAG, "Appending new ACE..");
+
+                if (!newInstallAcl)
+                {
+                    newInstallAcl = (OicSecAcl_t *) OICCalloc(1, sizeof(OicSecAcl_t));
+                    if (NULL == newInstallAcl)
+                    {
+                        OIC_LOG(ERROR, TAG, "Failed to acllocate ACL");
+                        return OC_STACK_NO_MEMORY;
+                    }
+                }
+                LL_PREPEND(newInstallAcl->aces, insertAce);
+            }
+            else
             {
-                ret = OC_STACK_OK;
+                OIC_LOG(ERROR, TAG, "Failed to duplicate ACE");
+                DeleteACLList(newInstallAcl);
+                return OC_STACK_ERROR;
             }
-            OICFree(payload);
         }
     }
 
+    if (newInstallAcl)
+    {
+        ret = AppendACL2(newInstallAcl);
+        if (OC_STACK_OK != ret)
+        {
+            OIC_LOG(ERROR, TAG, "Failed to append ACL");
+        }
+        OICFree(newInstallAcl);
+    }
+
+    OIC_LOG_V(DEBUG, TAG, "OUT: %s", __func__);
+    
     return ret;
 }
 
@@ -1769,8 +2761,6 @@ OCStackResult UpdateDefaultSecProvACE()
                                strlen(OIC_RSRC_DOXM_URI) + 1) == 0 ||
                        strncmp(rsrc->href, OIC_RSRC_CRED_URI,
                                strlen(OIC_RSRC_CRED_URI) + 1) == 0 ||
-                       strncmp(rsrc->href, OIC_RSRC_ACL_URI,
-                               strlen(OIC_RSRC_ACL_URI) + 1) == 0 ||
                        strncmp(rsrc->href, OIC_RSRC_PSTAT_URI,
                                strlen(OIC_RSRC_PSTAT_URI) + 1) == 0)
                     {