+
+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);
+
+ 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)
+ {
+ isNewAce = true;
+ LL_FOREACH_SAFE(gAcl->aces, existAce, tempAce2)
+ {
+ if(IsSameACE(newAce, existAce))
+ {
+ OIC_LOG(DEBUG, TAG, "Duplicated ACE dectected.");
+ ret = OC_STACK_DUPLICATE_REQUEST;
+ isNewAce = false;
+ }
+ }
+ if(isNewAce)
+ {
+ // 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
+ {
+ OIC_LOG(ERROR, TAG, "Failed to duplicate ACE");
+ DeleteACLList(newInstallAcl);
+ return OC_STACK_ERROR;
+ }
+ }
+ }
+
+ 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;
+}
+
+/**
+ * This function generates default ACE for security resource in case of owned status.
+ *
+ * @return Default ACE for security resource.
+ */
+static OicSecAce_t* GetSecDefaultACE()
+{
+ const int NUM_OF_DOXM_RT = 1;
+ const int NUM_OF_DOXM_IF = 1;
+ const int NUM_OF_PSTAT_RT = 1;
+ const int NUM_OF_PSTAT_IF = 1;
+ const char *doxmRt[] = { OIC_RSRC_TYPE_SEC_DOXM };
+ const char *pstatRt[] = { OIC_RSRC_TYPE_SEC_PSTAT };
+ const char *doxmIf[] = { OC_RSRVD_INTERFACE_DEFAULT };
+ const char *pstatIf[] = { OC_RSRVD_INTERFACE_DEFAULT };
+ OicSecRsrc_t* doxmRsrc = NULL;
+ OicSecRsrc_t* pstatRsrc = NULL;
+
+ //Generate default ACE
+ OicSecAce_t* newAce = (OicSecAce_t*)OICCalloc(1, sizeof(OicSecAce_t));
+ VERIFY_NON_NULL(TAG, newAce, ERROR);
+
+ // Subject -- Mandatory
+ memcpy(newAce->subjectuuid.id, &WILDCARD_SUBJECT_ID, WILDCARD_SUBJECT_ID_LEN);
+
+ //Resources -- Mandatory
+ //Add doxm
+ doxmRsrc = (OicSecRsrc_t*)OICCalloc(1, sizeof(OicSecRsrc_t));
+ VERIFY_NON_NULL(TAG, doxmRsrc, ERROR);
+ LL_APPEND(newAce->resources, doxmRsrc);
+ // pstat-href
+ doxmRsrc->href = OICStrdup(OIC_RSRC_DOXM_URI);
+ VERIFY_NON_NULL(TAG, (doxmRsrc->href), ERROR);
+ // pstat-rt
+ doxmRsrc->typeLen = NUM_OF_DOXM_RT;
+ doxmRsrc->types = (char**)OICCalloc(NUM_OF_DOXM_RT, sizeof(char*));
+ VERIFY_NON_NULL(TAG, (doxmRsrc->types), ERROR);
+ for(int i = 0; i < NUM_OF_DOXM_RT; i++)
+ {
+ doxmRsrc->types[i] = OICStrdup(doxmRt[i]);
+ VERIFY_NON_NULL(TAG, (doxmRsrc->types[i]), ERROR);
+ }
+ // pstat-if
+ doxmRsrc->interfaceLen = NUM_OF_DOXM_IF;
+ doxmRsrc->interfaces = (char**)OICCalloc(NUM_OF_DOXM_IF, sizeof(char*));
+ VERIFY_NON_NULL(TAG, (doxmRsrc->interfaces), ERROR);
+ for(int i = 0; i < NUM_OF_DOXM_IF; i++)
+ {
+ doxmRsrc->interfaces[i] = OICStrdup(doxmIf[i]);
+ VERIFY_NON_NULL(TAG, (doxmRsrc->interfaces[i]), ERROR);
+ }
+
+ //Add pstat
+ pstatRsrc = (OicSecRsrc_t*)OICCalloc(1, sizeof(OicSecRsrc_t));
+ VERIFY_NON_NULL(TAG, pstatRsrc, ERROR);
+ LL_APPEND(newAce->resources, pstatRsrc);
+ //pstat-href
+ pstatRsrc->href = OICStrdup(OIC_RSRC_PSTAT_URI);
+ VERIFY_NON_NULL(TAG, (pstatRsrc->href), ERROR);
+ //pstat-rt
+ pstatRsrc->typeLen = NUM_OF_PSTAT_RT;
+ pstatRsrc->types = (char**)OICCalloc(NUM_OF_PSTAT_RT, sizeof(char*));
+ VERIFY_NON_NULL(TAG, (pstatRsrc->types), ERROR);
+ for(int i = 0; i < NUM_OF_PSTAT_RT; i++)
+ {
+ pstatRsrc->types[i] = OICStrdup(pstatRt[i]);
+ VERIFY_NON_NULL(TAG, (pstatRsrc->types[i]), ERROR);
+ }
+ // pstat-if
+ pstatRsrc->interfaceLen = NUM_OF_PSTAT_IF;
+ pstatRsrc->interfaces = (char**)OICCalloc(NUM_OF_PSTAT_IF, sizeof(char*));
+ VERIFY_NON_NULL(TAG, (pstatRsrc->interfaces), ERROR);
+ for(int i = 0; i < NUM_OF_PSTAT_IF; i++)
+ {
+ pstatRsrc->interfaces[i] = OICStrdup(pstatIf[i]);
+ VERIFY_NON_NULL(TAG, (pstatRsrc->interfaces[i]), ERROR);
+ }
+
+ // Permissions -- Mandatory
+ newAce->permission = PERMISSION_READ;
+
+ //Period -- Not Mandatory
+ newAce->validities = NULL;
+
+ return newAce;
+exit:
+ FreeACE(newAce);
+ return NULL;
+
+}
+
+OCStackResult UpdateDefaultSecProvACE()
+{
+ OCStackResult ret = OC_STACK_OK;
+ OicSecAce_t *ace = NULL;
+ OicSecAce_t *tempAce = NULL;
+
+ if(gAcl)
+ {
+ int matchedRsrc = 0;
+ bool isRemoved = false;
+
+ LL_FOREACH_SAFE(gAcl->aces, ace, tempAce)
+ {
+ //Find default security resource ACL
+ if(memcmp(&ace->subjectuuid, &WILDCARD_SUBJECT_ID, sizeof(OicUuid_t)) == 0 &&
+ ((PERMISSION_READ | PERMISSION_WRITE) == ace->permission))
+ {
+ matchedRsrc = 0;
+
+ OicSecRsrc_t* rsrc = NULL;
+ LL_FOREACH(ace->resources, rsrc)
+ {
+ if(strncmp(rsrc->href, OIC_RSRC_DOXM_URI,
+ 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_PSTAT_URI,
+ strlen(OIC_RSRC_PSTAT_URI) + 1) == 0)
+ {
+ matchedRsrc++;
+ }
+ }
+
+ //If default security resource ACL is detected, delete it.
+ if(NUMBER_OF_SEC_PROV_RSCS == matchedRsrc)
+ {
+ LL_DELETE(gAcl->aces, ace);
+ FreeACE(ace);
+ isRemoved = true;
+ }
+ }
+ }
+
+ if(isRemoved)
+ {
+ /*
+ * Generate new security resource ACE as follows :
+ * subject : "*"
+ * resources : '/oic/sec/doxm', '/oic/sec/pstat'
+ * permission : READ
+ */
+ OicSecAce_t *secDefaultAce = GetSecDefaultACE();
+ if (secDefaultAce)
+ {
+ LL_APPEND(gAcl->aces, secDefaultAce);
+
+ size_t size = 0;
+ uint8_t *payload = NULL;
+ if (OC_STACK_OK == AclToCBORPayload(gAcl, &payload, &size))
+ {
+ if (UpdateSecureResourceInPS(OIC_JSON_ACL_NAME, payload, size) == OC_STACK_OK)
+ {
+ ret = OC_STACK_OK;
+ }
+ OICFree(payload);
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+OCStackResult SetAclRownerId(const OicUuid_t* newROwner)
+{
+ OCStackResult ret = OC_STACK_ERROR;
+ uint8_t *cborPayload = NULL;
+ size_t size = 0;
+ OicUuid_t prevId = {.id={0}};
+
+ if(NULL == newROwner)
+ {
+ ret = OC_STACK_INVALID_PARAM;
+ }
+ if(NULL == gAcl)
+ {
+ ret = OC_STACK_NO_RESOURCE;
+ }
+
+ if(newROwner && gAcl)
+ {
+ memcpy(prevId.id, gAcl->rownerID.id, sizeof(prevId.id));
+ memcpy(gAcl->rownerID.id, newROwner->id, sizeof(newROwner->id));
+
+ ret = AclToCBORPayload(gAcl, &cborPayload, &size);
+ VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
+
+ ret = UpdateSecureResourceInPS(OIC_JSON_ACL_NAME, cborPayload, size);
+ VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
+
+ OICFree(cborPayload);
+ }
+
+ return ret;
+
+exit:
+ OICFree(cborPayload);
+ memcpy(gAcl->rownerID.id, prevId.id, sizeof(prevId.id));
+ return ret;
+}
+
+OCStackResult GetAclRownerId(OicUuid_t *rowneruuid)
+{
+ OCStackResult retVal = OC_STACK_ERROR;
+ if (gAcl)
+ {
+ *rowneruuid = gAcl->rownerID;
+ retVal = OC_STACK_OK;
+ }
+ return retVal;
+}