#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)
// 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;
validity = NULL;
}
+#ifdef MULTIPLE_OWNER
+ OICFree(ace->eownerID);
+#endif
+
//Clean ACE
OICFree(ace);
ace = NULL;
newRsrc->rel = (char*)OICMalloc(sizeof(char) * allocateSize);
VERIFY_NON_NULL(TAG, newRsrc->rel, ERROR);
OICStrcpy(newRsrc->rel, allocateSize, rsrc->rel);
+ newRsrc->rel[allocateSize - 1] = '\0';
}
if(rsrc->types && 0 < rsrc->typeLen)
}
}
+#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;
}
{
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");
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.");
}
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;
}
// 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;
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 };
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;
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.");
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;
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;
{
cbor_value_get_array_length(&rMap, &rsrc->typeLen);
VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding RT array length.");
+
+ CborValue resourceTypes;
+
+ if (rsrc->typeLen == 0)
+ {
+ cborFindResult = cbor_value_enter_container(&rMap, &resourceTypes);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering RT Array.");
+
+ while (!cbor_value_at_end(&resourceTypes))
+ {
+ rsrc->typeLen++;
+ cborFindResult = cbor_value_advance(&resourceTypes);
+ if (cborFindResult != CborNoError)
+ {
+ break;
+ }
+ }
+ 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.");
{
cbor_value_get_array_length(&rMap, &rsrc->interfaceLen);
VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding IF array length.");
+
+ CborValue interfaces;
+
+ if (rsrc->interfaceLen == 0)
+ {
+ cborFindResult = cbor_value_enter_container(&rMap, &interfaces);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering IF Array.");
+
+ while (!cbor_value_at_end(&interfaces))
+ {
+ rsrc->interfaceLen++;
+ cborFindResult = cbor_value_advance(&interfaces);
+ if (cborFindResult != CborNoError)
+ {
+ break;
+ }
+ }
+ 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.");
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);
}
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))
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
*
{
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;
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)
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;
const OicSecAce_t *currentAce = NULL;
OicSecAcl_t targetAcl;
- memcpy(&targetAcl.rownerID, &gAcl->rownerID, sizeof(OicUuid_t));
+ 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.
OIC_LOG_BUFFER(DEBUG, TAG, payload, size);
newAcl = CBORPayloadToAcl(payload, size);
- if (newAcl)
+ if (NULL != newAcl && NULL != gAcl)
{
bool isNewAce = true;
OicSecAce_t* existAce = NULL;
}
}
}
+ memcpy(&(gAcl->rownerID), &(newAcl->rownerID), sizeof(OicUuid_t));
DeleteACLList(newAcl);
{
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)
}
}
}
+ else
+ {
+ OIC_LOG_V(ERROR, TAG, "%s: %s", __func__, (NULL == newAcl) ? "no new ACL" : "gAcl is NULL");
+ }
}
//Send response to request originator
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:
{
// Read ACL resource from PS
gAcl = CBORPayloadToAcl(data, size);
+ OICFree(data);
}
/*
* If SVR database in persistent storage got corrupted or
OicSecAce_t *ace = NULL;
OicSecAce_t *begin = NULL;
- if (NULL == subjectId)
+ if (NULL == subjectId || NULL == savePtr || NULL == gAcl)
{
return NULL;
}
}
}
-OCStackResult InstallNewACL2(const OicSecAcl_t* acl)
+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;
}
OICFree(payload);
}
+ OIC_LOG_V(DEBUG, TAG, "OUT: %s", __func__);
+
return ret;
}
-OCStackResult InstallNewACL(const uint8_t *cborPayload, const size_t size)
+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 InstallNewACL2(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)
+ {
+ 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;
}
/**
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)
{