X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=resource%2Fcsdk%2Fsecurity%2Fsrc%2Faclresource.c;h=d2b9f4b1d5be4cb84d792bc0e147bff34e1e8ef3;hb=442026128ead8780fa45d0db8a6f17be7c9220e0;hp=55058c714ea241fc3369e2ead8dd7d131d186586;hpb=01be9765a95ede47003777ee576fe9a4de4229e5;p=platform%2Fupstream%2Fiotivity.git diff --git a/resource/csdk/security/src/aclresource.c b/resource/csdk/security/src/aclresource.c index 55058c7..d2b9f4b 100644 --- a/resource/csdk/security/src/aclresource.c +++ b/resource/csdk/security/src/aclresource.c @@ -18,33 +18,45 @@ // //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -#include +#ifdef WITH_ARDUINO #include +#else +#include +#endif +#include + #include "ocstack.h" -#include "logger.h" +#include "ocserverrequest.h" #include "oic_malloc.h" #include "oic_string.h" -#include "cJSON.h" -#include "base64.h" -#include "resourcemanager.h" -#include "aclresource.h" -#include "psinterface.h" +#include "ocrandom.h" +#include "ocpayload.h" #include "utlist.h" +#include "payload_logging.h" #include "srmresourcestrings.h" +#include "aclresource.h" #include "doxmresource.h" +#include "resourcemanager.h" #include "srmutility.h" -#include "ocserverrequest.h" -#include -#ifdef WITH_ARDUINO -#include -#else -#include -#endif +#include "psinterface.h" + +#include "security_internals.h" #define TAG "SRM-ACL" +#define NUMBER_OF_SEC_PROV_RSCS 4 +#define NUMBER_OF_DEFAULT_SEC_RSCS 2 + +static const uint8_t ACL_MAP_SIZE = 2; +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; + + +// CborSize is the default cbor payload size being used. +static const uint16_t CBOR_SIZE = 2048; -OicSecAcl_t *gAcl = NULL; -static OCResourceHandle gAclHandle = NULL; +static OicSecAcl_t *gAcl = NULL; +static OCResourceHandle gAclHandle = NULL; /** * This function frees OicSecAcl_t object's fields and object itself. @@ -52,9 +64,9 @@ static OCResourceHandle gAclHandle = NULL; static void FreeACE(OicSecAcl_t *ace) { size_t i; - if(NULL == ace) + if (NULL == ace) { - OC_LOG (INFO, TAG, "Invalid Parameter"); + OIC_LOG(ERROR, TAG, "Invalid Parameter"); return; } @@ -65,17 +77,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); } - OICFree(ace->periods); - OICFree(ace->recurrences); - // Clean Owners - OICFree(ace->owners); + //Clean Recurrence + if (ace->recurrences) + { + for (i = 0; i < ace->prdRecrLen; i++) + { + OICFree(ace->recurrences[i]); + } + OICFree(ace->recurrences); + } // Clean ACL node itself OICFree(ace); @@ -95,354 +115,628 @@ void DeleteACLList(OicSecAcl_t* acl) } } -/* - * This internal method converts ACL data into JSON format. - * - * Note: Caller needs to invoke 'free' when finished done using - * return string. - */ -char * BinToAclJSON(const OicSecAcl_t * acl) +static size_t OicSecAclSize(const OicSecAcl_t *secAcl) { - cJSON *jsonRoot = NULL; - char *jsonStr = NULL; + if (!secAcl) + { + return 0; + } + OicSecAcl_t *acl = (OicSecAcl_t *)secAcl; + size_t size = 0; + while (acl) + { + size++; + acl = acl->next; + } + return size; +} - if (acl) +OCStackResult AclToCBORPayload(const OicSecAcl_t *secAcl, uint8_t **payload, size_t *size) +{ + if (NULL == secAcl || NULL == payload || NULL != *payload || NULL == size) { - jsonRoot = cJSON_CreateObject(); - VERIFY_NON_NULL(TAG, jsonRoot, ERROR); + return OC_STACK_INVALID_PARAM; + } + + OCStackResult ret = OC_STACK_ERROR; + CborError cborEncoderResult = CborNoError; + OicSecAcl_t *acl = (OicSecAcl_t *)secAcl; + CborEncoder encoder; + CborEncoder aclMap; + CborEncoder aclListMap; + CborEncoder acesArray; + uint8_t *outPayload = NULL; + size_t cborLen = *size; + *size = 0; + *payload = NULL; + + if (cborLen == 0) + { + cborLen = CBOR_SIZE; + } + + outPayload = (uint8_t *)OICCalloc(1, cborLen); + VERIFY_NON_NULL(TAG, outPayload, ERROR); + cbor_encoder_init(&encoder, outPayload, cborLen, 0); + + // Create ACL Map (aclist, rownerid) + cborEncoderResult = cbor_encoder_create_map(&encoder, &aclMap, ACL_MAP_SIZE); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Creating ACL Map."); + + cborEncoderResult = cbor_encode_text_string(&aclMap, OIC_JSON_ACLIST_NAME, + strlen(OIC_JSON_ACLIST_NAME)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding aclist Name Tag."); + + // Create ACLIST Map (aces) + cborEncoderResult = cbor_encoder_create_map(&aclMap, &aclListMap, ACL_ACLIST_MAP_SIZE); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Creating ACLIST Map."); - cJSON *jsonAclArray = NULL; - cJSON_AddItemToObject (jsonRoot, OIC_JSON_ACL_NAME, jsonAclArray = cJSON_CreateArray()); - VERIFY_NON_NULL(TAG, jsonAclArray, ERROR); + cborEncoderResult = cbor_encode_text_string(&aclListMap, OIC_JSON_ACES_NAME, + strlen(OIC_JSON_ACES_NAME)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ACES Name Tag."); - while(acl) + // Create ACES Array + cborEncoderResult = cbor_encoder_create_array(&aclListMap, &acesArray, OicSecAclSize(secAcl)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Creating ACES Array."); + + while (acl) + { + CborEncoder oicSecAclMap; + // ACL Map size - Number of mandatory items + uint8_t aclMapSize = ACL_ACES_MAP_SIZE; + size_t inLen = 0; + + // Create ACL Map + if (acl->periods) + { + ++aclMapSize; + } + if (acl->recurrences) { - char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {}; - uint32_t outLen = 0; - size_t inLen = 0; - B64Result b64Ret = B64_OK; + ++aclMapSize; + } - cJSON *jsonAcl = cJSON_CreateObject(); + cborEncoderResult = cbor_encoder_create_map(&acesArray, &oicSecAclMap, aclMapSize); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Creating ACES Map"); + + // Subject -- Mandatory + cborEncoderResult = cbor_encode_text_string(&oicSecAclMap, OIC_JSON_SUBJECTID_NAME, + strlen(OIC_JSON_SUBJECTID_NAME)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Subject Name Tag."); + inLen = (memcmp(&(acl->subject), &WILDCARD_SUBJECT_ID, sizeof(OicUuid_t)) == 0) ? + WILDCARD_SUBJECT_ID_LEN : sizeof(OicUuid_t); + if(inLen == WILDCARD_SUBJECT_ID_LEN) + { + cborEncoderResult = cbor_encode_text_string(&oicSecAclMap, WILDCARD_RESOURCE_URI, + strlen(WILDCARD_RESOURCE_URI)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Subject Id wildcard Value."); + } + else + { + char *subject = NULL; + ret = ConvertUuidToStr(&acl->subject, &subject); + VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR); + cborEncoderResult = cbor_encode_text_string(&oicSecAclMap, subject, strlen(subject)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Subject Id Value."); + OICFree(subject); + } + + // Resources + { + CborEncoder resources; + cborEncoderResult = cbor_encode_text_string(&oicSecAclMap, OIC_JSON_RESOURCES_NAME, + strlen(OIC_JSON_RESOURCES_NAME)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Resource Name Tag."); + + cborEncoderResult = cbor_encoder_create_array(&oicSecAclMap, &resources, acl->resourcesLen); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Resource Name Array."); - // Subject -- Mandatory - outLen = 0; - if (memcmp(&(acl->subject), &WILDCARD_SUBJECT_ID, sizeof(OicUuid_t)) == 0) - { - inLen = WILDCARD_SUBJECT_ID_LEN; - } - else - { - inLen = sizeof(OicUuid_t); - } - b64Ret = b64Encode(acl->subject.id, inLen, base64Buff, - sizeof(base64Buff), &outLen); - VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR); - cJSON_AddStringToObject(jsonAcl, OIC_JSON_SUBJECT_NAME, base64Buff ); - - // Resources -- Mandatory - cJSON *jsonRsrcArray = NULL; - cJSON_AddItemToObject (jsonAcl, OIC_JSON_RESOURCES_NAME, jsonRsrcArray = cJSON_CreateArray()); - VERIFY_NON_NULL(TAG, jsonRsrcArray, ERROR); for (size_t i = 0; i < acl->resourcesLen; i++) { - cJSON_AddItemToArray (jsonRsrcArray, cJSON_CreateString(acl->resources[i])); + + CborEncoder rMap; + cborEncoderResult = cbor_encoder_create_map(&resources, &rMap, ACL_RESOURCE_MAP_SIZE); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Resource Map."); + + cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_HREF_NAME, + strlen(OIC_JSON_HREF_NAME)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding HREF Name Tag."); + cborEncoderResult = cbor_encode_text_string(&rMap, acl->resources[i], + strlen(acl->resources[i])); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding HREF Value in Map."); + + 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."); + + // TODO : Need to assign real value of REL + cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_EMPTY_STRING, + strlen(OIC_JSON_EMPTY_STRING)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding REL Value."); + + cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_RT_NAME, + strlen(OIC_JSON_RT_NAME)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Name Tag."); + + // TODO : Need to assign real value of RT + cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_EMPTY_STRING, + strlen(OIC_JSON_EMPTY_STRING)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Value."); + + cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_IF_NAME, + strlen(OIC_JSON_IF_NAME)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Name Tag."); + + // TODO : Need to assign real value of IF + cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_EMPTY_STRING, + strlen(OIC_JSON_EMPTY_STRING)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Value."); + + + cborEncoderResult = cbor_encoder_close_container(&resources, &rMap); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Resource Map."); + } + cborEncoderResult = cbor_encoder_close_container(&oicSecAclMap, &resources); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Resource Name Array."); + } + - // Permissions -- Mandatory - cJSON_AddNumberToObject (jsonAcl, OIC_JSON_PERMISSION_NAME, acl->permission); + // Permissions -- Mandatory + cborEncoderResult = cbor_encode_text_string(&oicSecAclMap, OIC_JSON_PERMISSION_NAME, + strlen(OIC_JSON_PERMISSION_NAME)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Permission Name Tag."); + cborEncoderResult = cbor_encode_int(&oicSecAclMap, acl->permission); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Permission Name Value."); + + // Period -- Not Mandatory + if (acl->periods) + { - //Period & Recurrence -- Not Mandatory - if(0 != acl->prdRecrLen) + CborEncoder period; + cborEncoderResult = cbor_encode_text_string(&oicSecAclMap, OIC_JSON_PERIOD_NAME, + strlen(OIC_JSON_PERIOD_NAME)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Period Tag."); + cborEncoderResult = cbor_encoder_create_array(&oicSecAclMap, &period, acl->prdRecrLen); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Period Array."); + for (size_t i = 0; i < acl->prdRecrLen; i++) { - cJSON *jsonPeriodArray = NULL; - cJSON_AddItemToObject (jsonAcl, OIC_JSON_PERIODS_NAME, - jsonPeriodArray = cJSON_CreateArray()); - VERIFY_NON_NULL(TAG, jsonPeriodArray, ERROR); - for (size_t i = 0; i < acl->prdRecrLen; i++) - { - cJSON_AddItemToArray (jsonPeriodArray, - cJSON_CreateString(acl->periods[i])); - } + cborEncoderResult = cbor_encode_text_string(&period, acl->periods[i], + strlen(acl->periods[i])); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Period Value in Array."); } + cborEncoderResult = cbor_encoder_close_container(&oicSecAclMap, &period); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Period Array."); + } - //Recurrence -- Not Mandatory - if(0 != acl->prdRecrLen && acl->recurrences) + // Recurrence -- Not Mandatory + if (acl->recurrences) + { + CborEncoder recurrences; + cborEncoderResult = cbor_encode_text_string(&oicSecAclMap, OIC_JSON_RECURRENCES_NAME, + strlen(OIC_JSON_RECURRENCES_NAME)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Recurrence Tag."); + cborEncoderResult = cbor_encoder_create_array(&oicSecAclMap, &recurrences, acl->prdRecrLen); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Recurrence Array."); + + for (size_t i = 0; i < acl->prdRecrLen; i++) { - cJSON *jsonRecurArray = NULL; - cJSON_AddItemToObject (jsonAcl, OIC_JSON_RECURRENCES_NAME, - jsonRecurArray = cJSON_CreateArray()); - VERIFY_NON_NULL(TAG, jsonRecurArray, ERROR); - for (size_t i = 0; i < acl->prdRecrLen; i++) - { - cJSON_AddItemToArray (jsonRecurArray, - cJSON_CreateString(acl->recurrences[i])); - } + cborEncoderResult = cbor_encode_text_string(&recurrences, acl->recurrences[i], + strlen(acl->recurrences[i])); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Recurrence Array Value."); } + cborEncoderResult = cbor_encoder_close_container(&oicSecAclMap, &recurrences); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Recurrence Array"); - // Owners -- Mandatory - cJSON *jsonOwnrArray = NULL; - cJSON_AddItemToObject (jsonAcl, OIC_JSON_OWNERS_NAME, jsonOwnrArray = cJSON_CreateArray()); - VERIFY_NON_NULL(TAG, jsonOwnrArray, ERROR); - for (size_t i = 0; i < acl->ownersLen; i++) - { - outLen = 0; + } - b64Ret = b64Encode(acl->owners[i].id, sizeof(((OicUuid_t*)0)->id), base64Buff, - sizeof(base64Buff), &outLen); - VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR); - cJSON_AddItemToArray (jsonOwnrArray, cJSON_CreateString(base64Buff)); - } + cborEncoderResult = cbor_encoder_close_container(&acesArray, &oicSecAclMap); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing ACES Map."); + acl = acl->next; + } - // Attach current acl node to Acl Array - cJSON_AddItemToArray(jsonAclArray, jsonAcl); - acl = acl->next; - } + // Close ACES Array + cborEncoderResult = cbor_encoder_close_container(&aclListMap, &acesArray); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing ACES Array."); + + // Close ACLIST Map + cborEncoderResult = cbor_encoder_close_container(&aclMap, &aclListMap); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing ACLIST Map."); - jsonStr = cJSON_PrintUnformatted(jsonRoot); + // Rownerid + { + char *rowner = NULL; + cborEncoderResult = cbor_encode_text_string(&aclMap, OIC_JSON_ROWNERID_NAME, + strlen(OIC_JSON_ROWNERID_NAME)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding rownerid Name."); + ret = ConvertUuidToStr(&secAcl->rownerID, &rowner); + VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR); + cborEncoderResult = cbor_encode_text_string(&aclMap, rowner, strlen(rowner)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding rownerid Value."); + OICFree(rowner); } + // Close ACL Map + cborEncoderResult = cbor_encoder_close_container(&encoder, &aclMap); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing ACL Map."); + + if (CborNoError == cborEncoderResult) + { + OIC_LOG(DEBUG, TAG, "AclToCBORPayload Successed"); + *size = encoder.ptr - outPayload; + *payload = outPayload; + ret = OC_STACK_OK; + } exit: - if (jsonRoot) + if (CborErrorOutOfMemory == cborEncoderResult) + { + OIC_LOG(DEBUG, TAG, "AclToCBORPayload:CborErrorOutOfMemory : retry with more memory"); + + // reallocate and try again! + OICFree(outPayload); + // Since the allocated initial memory failed, double the memory. + cborLen += encoder.ptr - encoder.end; + cborEncoderResult = CborNoError; + ret = AclToCBORPayload(secAcl, payload, &cborLen); + *size = cborLen; + } + else if (cborEncoderResult != CborNoError) { - cJSON_Delete(jsonRoot); + OIC_LOG(ERROR, TAG, "Failed to AclToCBORPayload"); + OICFree(outPayload); + outPayload = NULL; + *size = 0; + *payload = NULL; + ret = OC_STACK_ERROR; } - return jsonStr; + + return ret; } -/* - * This internal method converts JSON ACL into binary ACL. - */ -OicSecAcl_t * JSONToAclBin(const char * jsonStr) +// 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) { + if (NULL == cborPayload || 0 == size) + { + return NULL; + } OCStackResult ret = OC_STACK_ERROR; - OicSecAcl_t * headAcl = NULL; - OicSecAcl_t * prevAcl = NULL; - cJSON *jsonRoot = NULL; - cJSON *jsonAclArray = NULL; - - VERIFY_NON_NULL(TAG, jsonStr, ERROR); + CborValue aclCbor = { .parser = NULL }; + CborParser parser = { .end = NULL }; + CborError cborFindResult = CborNoError; + cbor_parser_init(cborPayload, size, 0, &parser, &aclCbor); - jsonRoot = cJSON_Parse(jsonStr); - VERIFY_NON_NULL(TAG, jsonRoot, ERROR); + OicSecAcl_t *headAcl = (OicSecAcl_t *) OICCalloc(1, sizeof(OicSecAcl_t)); - jsonAclArray = cJSON_GetObjectItem(jsonRoot, OIC_JSON_ACL_NAME); - VERIFY_NON_NULL(TAG, jsonAclArray, 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."); - if (cJSON_Array == jsonAclArray->type) + while (cbor_value_is_valid(&aclMap)) { - int numAcl = cJSON_GetArraySize(jsonAclArray); - int idx = 0; - - VERIFY_SUCCESS(TAG, numAcl > 0, INFO); - do + char* tagName = NULL; + size_t len = 0; + CborType type = cbor_value_get_type(&aclMap); + if (type == CborTextStringType) { - cJSON *jsonAcl = cJSON_GetArrayItem(jsonAclArray, idx); - VERIFY_NON_NULL(TAG, jsonAcl, ERROR); - - OicSecAcl_t *acl = (OicSecAcl_t*)OICCalloc(1, sizeof(OicSecAcl_t)); - VERIFY_NON_NULL(TAG, acl, ERROR); - - headAcl = (headAcl) ? headAcl : acl; - if (prevAcl) + 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) { - prevAcl->next = acl; - } + // Enter ACLIST Map + CborValue aclistMap = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 }; + cborFindResult = cbor_value_enter_container(&aclMap, &aclistMap); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering ACLIST Map."); - size_t jsonObjLen = 0; - cJSON *jsonObj = NULL; - - unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {}; - uint32_t outLen = 0; - B64Result b64Ret = B64_OK; - - // Subject -- Mandatory - jsonObj = cJSON_GetObjectItem(jsonAcl, OIC_JSON_SUBJECT_NAME); - VERIFY_NON_NULL(TAG, jsonObj, ERROR); - VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR); - outLen = 0; - b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring), base64Buff, - sizeof(base64Buff), &outLen); - VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(acl->subject.id)), ERROR); - memcpy(acl->subject.id, base64Buff, outLen); - - // Resources -- Mandatory - jsonObj = cJSON_GetObjectItem(jsonAcl, OIC_JSON_RESOURCES_NAME); - VERIFY_NON_NULL(TAG, jsonObj, ERROR); - VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR); - - acl->resourcesLen = cJSON_GetArraySize(jsonObj); - VERIFY_SUCCESS(TAG, acl->resourcesLen > 0, ERROR); - acl->resources = (char**)OICCalloc(acl->resourcesLen, sizeof(char*)); - VERIFY_NON_NULL(TAG, (acl->resources), ERROR); - - size_t idxx = 0; - do - { - cJSON *jsonRsrc = cJSON_GetArrayItem(jsonObj, idxx); - VERIFY_NON_NULL(TAG, jsonRsrc, ERROR); - - jsonObjLen = strlen(jsonRsrc->valuestring) + 1; - acl->resources[idxx] = (char*)OICMalloc(jsonObjLen); - VERIFY_NON_NULL(TAG, (acl->resources[idxx]), ERROR); - OICStrcpy(acl->resources[idxx], jsonObjLen, jsonRsrc->valuestring); - } while ( ++idxx < acl->resourcesLen); - - // Permissions -- Mandatory - jsonObj = cJSON_GetObjectItem(jsonAcl, - OIC_JSON_PERMISSION_NAME); - VERIFY_NON_NULL(TAG, jsonObj, ERROR); - VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR); - acl->permission = jsonObj->valueint; - - //Period -- Not Mandatory - cJSON *jsonPeriodObj = cJSON_GetObjectItem(jsonAcl, - OIC_JSON_PERIODS_NAME); - if(jsonPeriodObj) - { - VERIFY_SUCCESS(TAG, cJSON_Array == jsonPeriodObj->type, - ERROR); - acl->prdRecrLen = cJSON_GetArraySize(jsonPeriodObj); - if(acl->prdRecrLen > 0) - { - acl->periods = (char**)OICCalloc(acl->prdRecrLen, - sizeof(char*)); - VERIFY_NON_NULL(TAG, acl->periods, ERROR); - cJSON *jsonPeriod = NULL; - for(size_t i = 0; i < acl->prdRecrLen; i++) + while (cbor_value_is_valid(&aclistMap)) + { + char* acName = NULL; + size_t acLen = 0; + CborType acType = cbor_value_get_type(&aclistMap); + if (acType == CborTextStringType) { - jsonPeriod = cJSON_GetArrayItem(jsonPeriodObj, i); - VERIFY_NON_NULL(TAG, jsonPeriod, ERROR); - - jsonObjLen = strlen(jsonPeriod->valuestring) + 1; - acl->periods[i] = (char*)OICMalloc(jsonObjLen); - VERIFY_NON_NULL(TAG, acl->periods[i], ERROR); - OICStrcpy(acl->periods[i], jsonObjLen, - jsonPeriod->valuestring); + cborFindResult = cbor_value_dup_text_string(&aclistMap, &acName, &acLen, NULL); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Name in ACLIST Map."); + cborFindResult = cbor_value_advance(&aclistMap); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Value in ACLIST Map."); } - } - } + if(acName) + { + if (strcmp(acName, OIC_JSON_ACES_NAME) == 0) + { - //Recurrence -- Not mandatory - cJSON *jsonRecurObj = cJSON_GetObjectItem(jsonAcl, - OIC_JSON_RECURRENCES_NAME); - if(jsonRecurObj) - { - VERIFY_SUCCESS(TAG, cJSON_Array == jsonRecurObj->type, - ERROR); - if(acl->prdRecrLen > 0) - { - acl->recurrences = (char**)OICCalloc(acl->prdRecrLen, - sizeof(char*)); - VERIFY_NON_NULL(TAG, acl->recurrences, ERROR); + // Enter ACES Array + CborValue aclArray = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 }; + cborFindResult = cbor_value_enter_container(&aclistMap, &aclArray); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering ACL Array."); + + int acesCount = 0; + while (cbor_value_is_valid(&aclArray)) + { + acesCount++; + + CborValue aclMap = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 }; + cborFindResult = cbor_value_enter_container(&aclArray, &aclMap); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering ACL Map."); + OicSecAcl_t *acl = NULL; + + if(acesCount == 1) + { + acl = headAcl; + } + else + { + acl = (OicSecAcl_t *) OICCalloc(1, sizeof(OicSecAcl_t)); + OicSecAcl_t *temp = headAcl; + while (temp->next) + { + temp = temp->next; + } + temp->next = acl; + } + VERIFY_NON_NULL(TAG, acl, ERROR); + + while (cbor_value_is_valid(&aclMap)) + { + char* name = NULL; + size_t len = 0; + CborType type = cbor_value_get_type(&aclMap); + if (type == CborTextStringType) + { + cborFindResult = cbor_value_dup_text_string(&aclMap, &name, &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 (name) + { + // Subject -- Mandatory + if (strcmp(name, OIC_JSON_SUBJECTID_NAME) == 0) + { + char *subject = NULL; + cborFindResult = cbor_value_dup_text_string(&aclMap, &subject, &len, NULL); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding subject Value."); + if(strcmp(subject, WILDCARD_RESOURCE_URI) == 0) + { + acl->subject.id[0] = '*'; + } + else + { + ret = ConvertStrToUuid(subject, &acl->subject); + 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_get_array_length(&aclMap, &acl->resourcesLen); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a Resource Array Len Value."); + cborFindResult = cbor_value_enter_container(&aclMap, &resources); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering a Resource Array."); + + acl->resources = (char **) OICMalloc(acl->resourcesLen * sizeof(char*)); + VERIFY_NON_NULL(TAG, acl->resources, ERROR); + int i = 0; + 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"); + + + 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)) + { + // TODO : Need to check data structure of OicSecAcl_t based on RAML spec. + cborFindResult = cbor_value_dup_text_string(&rMap, &acl->resources[i++], &len, NULL); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Href Value."); + } + // "rel" + if (0 == strcmp(OIC_JSON_REL_NAME, rMapName)) + { + // TODO : Need to check data structure of OicSecAcl_t based on RAML spec. + char *relData = NULL; + cborFindResult = cbor_value_dup_text_string(&rMap, &relData, &len, NULL); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding REL Value."); + OICFree(relData); + } + // "rt" + if (0 == strcmp(OIC_JSON_RT_NAME, rMapName)) + { + // TODO : Need to check data structure of OicSecAcl_t and assign based on RAML spec. + char *rtData = NULL; + cborFindResult = cbor_value_dup_text_string(&rMap, &rtData, &len, NULL); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding RT Value."); + OICFree(rtData); + } + + // "if" + if (0 == strcmp(OIC_JSON_IF_NAME, rMapName)) + { + // TODO : Need to check data structure of OicSecAcl_t and assign based on RAML spec. + char *ifData = NULL; + cborFindResult = cbor_value_dup_text_string(&rMap, &ifData, &len, NULL); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding IF Value."); + OICFree(ifData); + } + + 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) + { + cborFindResult = cbor_value_get_uint64(&aclMap, (uint64_t *) &acl->permission); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a PERM Value."); + } + + // Period -- Not mandatory + if (strcmp(name, OIC_JSON_PERIOD_NAME) == 0) + { + CborValue period = { .parser = NULL }; + cborFindResult = cbor_value_get_array_length(&aclMap, &acl->prdRecrLen); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a Period Array Len."); + cborFindResult = cbor_value_enter_container(&aclMap, &period); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a Period Array Map."); + acl->periods = (char**)OICCalloc(acl->prdRecrLen, sizeof(char*)); + VERIFY_NON_NULL(TAG, acl->periods, ERROR); + int i = 0; + while (cbor_value_is_text_string(&period)) + { + cborFindResult = cbor_value_dup_text_string(&period, &acl->periods[i++], + &len, NULL); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a Period Array Value."); + cborFindResult = cbor_value_advance(&period); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing a Period Array."); + } + } + + // Recurrence -- Not mandatory + if (strcmp(name, OIC_JSON_RECURRENCES_NAME) == 0) + { + CborValue recurrences = { .parser = NULL }; + cborFindResult = cbor_value_enter_container(&aclMap, &recurrences); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Adding Recurrence Array."); + acl->recurrences = (char**)OICCalloc(acl->prdRecrLen, sizeof(char*)); + VERIFY_NON_NULL(TAG, acl->recurrences, ERROR); + int i = 0; + while (cbor_value_is_text_string(&recurrences)) + { + cborFindResult = cbor_value_dup_text_string(&recurrences, + &acl->recurrences[i++], &len, NULL); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Adding Recurrence Array Value."); + cborFindResult = cbor_value_advance(&recurrences); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Closing Recurrence Array."); + } + } + + OICFree(name); + } + + if (type != CborMapType && cbor_value_is_valid(&aclMap)) + { + cborFindResult = cbor_value_advance(&aclMap); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing the Array."); + } + } + + acl->next = NULL; + + if (cbor_value_is_valid(&aclArray)) + { + cborFindResult = cbor_value_advance(&aclArray); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing ACL Array."); + } + } + } + OICFree(acName); + } - cJSON *jsonRecur = NULL; - for(size_t i = 0; i < acl->prdRecrLen; i++) + if (cbor_value_is_valid(&aclistMap)) { - jsonRecur = cJSON_GetArrayItem(jsonRecurObj, i); - 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); + cborFindResult = cbor_value_advance(&aclistMap); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing ACLIST Map."); } } } - // Owners -- Mandatory - jsonObj = cJSON_GetObjectItem(jsonAcl, OIC_JSON_OWNERS_NAME); - VERIFY_NON_NULL(TAG, jsonObj, ERROR); - VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR); - - acl->ownersLen = cJSON_GetArraySize(jsonObj); - VERIFY_SUCCESS(TAG, acl->ownersLen > 0, ERROR); - acl->owners = (OicUuid_t*)OICCalloc(acl->ownersLen, sizeof(OicUuid_t)); - VERIFY_NON_NULL(TAG, (acl->owners), ERROR); - - idxx = 0; - do + // TODO : Need to modify headAcl->owners[0].id to headAcl->rowner based on RAML spec. + if (strcmp(tagName, OIC_JSON_ROWNERID_NAME) == 0) { - cJSON *jsonOwnr = cJSON_GetArrayItem(jsonObj, idxx); - VERIFY_NON_NULL(TAG, jsonOwnr, ERROR); - VERIFY_SUCCESS(TAG, cJSON_String == jsonOwnr->type, ERROR); - - outLen = 0; - b64Ret = b64Decode(jsonOwnr->valuestring, strlen(jsonOwnr->valuestring), base64Buff, - sizeof(base64Buff), &outLen); - - VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(acl->owners[idxx].id)), - ERROR); - memcpy(acl->owners[idxx].id, base64Buff, outLen); - } while ( ++idxx < acl->ownersLen); - - prevAcl = acl; - } while( ++idx < numAcl); + char *stRowner = NULL; + cborFindResult = cbor_value_dup_text_string(&aclMap, &stRowner, &len, NULL); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Rownerid Value."); + ret = ConvertStrToUuid(stRowner, &headAcl->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."); + } } - ret = OC_STACK_OK; - exit: - cJSON_Delete(jsonRoot); - if (OC_STACK_OK != ret) + if (cborFindResult != CborNoError) { + OIC_LOG(ERROR, TAG, "Failed to CBORPayloadToAcl"); DeleteACLList(headAcl); headAcl = NULL; } return headAcl; } -static bool UpdatePersistentStorage(const OicSecAcl_t *acl) -{ - // Convert ACL data into JSON for update to persistent storage - char *jsonStr = BinToAclJSON(acl); - if (jsonStr) - { - cJSON *jsonAcl = cJSON_Parse(jsonStr); - OICFree(jsonStr); - - if ((jsonAcl) && (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_ACL_NAME, jsonAcl))) - { - return true; - } - cJSON_Delete(jsonAcl); - } - return false; -} - -/* +/** * This method removes ACE for the subject and resource from the ACL * - * @param subject - subject of the ACE - * @param resource - resource of the ACE + * @param subject of the ACE + * @param resource of the ACE * * @return - * OC_STACK_RESOURCE_DELETED on success - * OC_STACK_NO_RESOURC on failure to find the appropriate ACE - * OC_STACK_INVALID_PARAM on invalid parameter + * ::OC_STACK_RESOURCE_DELETED on success + * ::OC_STACK_NO_RESOURCE on failure to find the appropriate ACE + * ::OC_STACK_INVALID_PARAM on invalid parameter */ -static OCStackResult RemoveACE(const OicUuid_t * subject, - const char * resource) +static OCStackResult RemoveACE(const OicUuid_t * subject, const char * resource) { - OC_LOG(INFO, TAG, "IN RemoveACE"); + OIC_LOG(DEBUG, TAG, "IN RemoveACE"); OicSecAcl_t *acl = NULL; OicSecAcl_t *tempAcl = NULL; bool deleteFlag = false; OCStackResult ret = OC_STACK_NO_RESOURCE; - if(memcmp(subject->id, &WILDCARD_SUBJECT_ID, sizeof(subject->id)) == 0) + if (memcmp(subject->id, &WILDCARD_SUBJECT_ID, sizeof(subject->id)) == 0) { - OC_LOG_V (INFO, TAG, "%s received invalid parameter", __func__ ); + OIC_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 || resource[0] == '\0') + if (NULL == resource || resource[0] == '\0') { LL_FOREACH_SAFE(gAcl, acl, tempAcl) { - if(memcmp(acl->subject.id, subject->id, sizeof(subject->id)) == 0) + if (memcmp(acl->subject.id, subject->id, sizeof(subject->id)) == 0) { LL_DELETE(gAcl, acl); FreeACE(acl); @@ -458,9 +752,9 @@ static OCStackResult RemoveACE(const OicUuid_t * subject, //the resource array LL_FOREACH_SAFE(gAcl, acl, tempAcl) { - if(memcmp(acl->subject.id, subject->id, sizeof(subject->id)) == 0) + if (memcmp(acl->subject.id, subject->id, sizeof(subject->id)) == 0) { - if(1 == acl->resourcesLen && strcmp(acl->resources[0], resource) == 0) + if (1 == acl->resourcesLen && strcmp(acl->resources[0], resource) == 0) { LL_DELETE(gAcl, acl); FreeACE(acl); @@ -469,24 +763,24 @@ static OCStackResult RemoveACE(const OicUuid_t * subject, } else { - int resPos = -1; + size_t resPos = -1; size_t i; - for(i = 0; i < acl->resourcesLen; i++) + for (i = 0; i < acl->resourcesLen; i++) { - if(strcmp(acl->resources[i], resource) == 0) + if (strcmp(acl->resources[i], resource) == 0) { resPos = i; break; } } - if((0 <= resPos)) + if (0 <= (int) resPos) { OICFree(acl->resources[resPos]); acl->resources[resPos] = NULL; acl->resourcesLen -= 1; - for(i = resPos; i < acl->resourcesLen; i++) + for (i = resPos; i < acl->resourcesLen; i++) { - acl->resources[i] = acl->resources[i+1]; + acl->resources[i] = acl->resources[i + 1]; } deleteFlag = true; break; @@ -496,17 +790,31 @@ static OCStackResult RemoveACE(const OicUuid_t * subject, } } - if(deleteFlag) + if (deleteFlag) { - if(UpdatePersistentStorage(gAcl)) + // In case of unit test do not update persistant storage. + if (memcmp(subject->id, &WILDCARD_SUBJECT_B64_ID, sizeof(subject->id)) == 0) { ret = OC_STACK_RESOURCE_DELETED; } + else + { + uint8_t *payload = NULL; + size_t size = 0; + if (OC_STACK_OK == AclToCBORPayload(gAcl, &payload, &size)) + { + if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_ACL_NAME, payload, size)) + { + ret = OC_STACK_RESOURCE_DELETED; + } + OICFree(payload); + } + } } return ret; } -/* +/** * This method parses the query string received for REST requests and * retrieves the 'subject' field. * @@ -517,33 +825,25 @@ static OCStackResult RemoveACE(const OicUuid_t * subject, */ static bool GetSubjectFromQueryString(const char *query, OicUuid_t *subject) { - OicParseQueryIter_t parseIter = {.attrPos=NULL}; + OicParseQueryIter_t parseIter = { .attrPos = NULL }; - ParseQueryIterInit((unsigned char *)query, &parseIter); + ParseQueryIterInit((unsigned char *) query, &parseIter); - - while(GetNextQuery(&parseIter)) + while (GetNextQuery (&parseIter)) { - if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_SUBJECT_NAME, parseIter.attrLen) == 0) + if (strncasecmp((char *) parseIter.attrPos, OIC_JSON_SUBJECTID_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); - + memcpy(subject->id, parseIter.valPos, parseIter.valLen); return true; } } exit: - return false; + return false; } -/* +/** * This method parses the query string received for REST requests and * retrieves the 'resource' field. * @@ -555,16 +855,17 @@ exit: */ static bool GetResourceFromQueryString(const char *query, char *resource, size_t resourceSize) { - OicParseQueryIter_t parseIter = {.attrPos=NULL}; + OicParseQueryIter_t parseIter = { .attrPos = NULL }; - ParseQueryIterInit((unsigned char *)query, &parseIter); + ParseQueryIterInit((unsigned char *) query, &parseIter); - while(GetNextQuery(&parseIter)) + while (GetNextQuery (&parseIter)) { - if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_RESOURCES_NAME, parseIter.attrLen) == 0) + 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); + OICStrcpy(resource, resourceSize, (char *) parseIter.valPos); return true; } @@ -574,28 +875,26 @@ exit: return false; } - - -static OCEntityHandlerResult HandleACLGetRequest (const OCEntityHandlerRequest * ehRequest) +static OCEntityHandlerResult HandleACLGetRequest(const OCEntityHandlerRequest *ehRequest) { - OCEntityHandlerResult ehRet = OC_EH_ERROR; - char* jsonStr = NULL; + OIC_LOG(INFO, TAG, "HandleACLGetRequest processing the request"); + uint8_t* payload = NULL; + size_t size = 0; + OCEntityHandlerResult ehRet; // Process the REST querystring parameters - if(ehRequest->query) + if (ehRequest->query) { - OC_LOG (INFO, TAG, "HandleACLGetRequest processing query"); + OIC_LOG(DEBUG, TAG, "HandleACLGetRequest processing query"); - OicUuid_t subject = {.id={0}}; - char resource[MAX_URI_LENGTH] = {0}; + 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); + VERIFY_SUCCESS(TAG, true == GetSubjectFromQueryString(ehRequest->query, &subject), ERROR); GetResourceFromQueryString(ehRequest->query, resource, sizeof(resource)); @@ -604,7 +903,7 @@ static OCEntityHandlerResult HandleACLGetRequest (const OCEntityHandlerRequest * * Below code needs to be updated for scenarios when Subject have * multiple ACE's in ACL resource. */ - while((currentAce = GetACLResourceData(&subject, &savePtr))) + while ((currentAce = GetACLResourceData(&subject, &savePtr))) { /* * If REST querystring contains a specific resource, we need @@ -612,106 +911,138 @@ static OCEntityHandlerResult HandleACLGetRequest (const OCEntityHandlerRequest * */ if (resource[0] != '\0') { - for(size_t n = 0; n < currentAce->resourcesLen; n++) + 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]))) + 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); + // Convert ACL data into CBOR format for transmission + if (OC_STACK_OK != AclToCBORPayload(currentAce, &payload, &size)) + { + ehRet = OC_EH_ERROR; + } goto exit; } } } else { - // Convert ACL data into JSON for transmission - jsonStr = BinToAclJSON(currentAce); + // Convert ACL data into CBOR format for transmission + if (OC_STACK_OK != AclToCBORPayload(currentAce, &payload, &size)) + { + ehRet = OC_EH_ERROR; + } goto exit; } } } else { - // Convert ACL data into JSON for transmission - jsonStr = BinToAclJSON(gAcl); + // Convert ACL data into CBOR format for transmission. + if (OC_STACK_OK != AclToCBORPayload(gAcl, &payload, &size)) + { + ehRet = OC_EH_ERROR; + } } - exit: - ehRet = (jsonStr ? OC_EH_OK : OC_EH_ERROR); + // A device should always have a default acl. Therefore, payload should never be NULL. + ehRet = (payload ? OC_EH_OK : OC_EH_ERROR); // Send response payload to request originator - SendSRMResponse(ehRequest, ehRet, jsonStr); - - OICFree(jsonStr); + if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, payload, size)) + { + ehRet = OC_EH_ERROR; + OIC_LOG(ERROR, TAG, "SendSRMResponse failed for HandleACLGetRequest"); + } + OICFree(payload); - OC_LOG_V (INFO, TAG, "%s RetVal %d", __func__ , ehRet); + OIC_LOG_V(DEBUG, TAG, "%s RetVal %d", __func__, ehRet); return ehRet; } -static OCEntityHandlerResult HandleACLPostRequest (const OCEntityHandlerRequest * ehRequest) +static OCEntityHandlerResult HandleACLPostRequest(const OCEntityHandlerRequest *ehRequest) { + OIC_LOG(INFO, TAG, "HandleACLPostRequest processing the request"); OCEntityHandlerResult ehRet = OC_EH_ERROR; - // Convert JSON ACL data into binary. This will also validate the ACL data received. - OicSecAcl_t* newAcl = JSONToAclBin(((OCSecurityPayload*)ehRequest->payload)->securityData); - - if (newAcl) + // 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) { - // Append the new ACL to existing ACL - LL_APPEND(gAcl, newAcl); - - if(UpdatePersistentStorage(gAcl)) + OicSecAcl_t *newAcl = CBORPayloadToAcl(payload, size); + if (newAcl) { - ehRet = OC_EH_RESOURCE_CREATED; + // Append the new ACL to existing ACL + LL_APPEND(gAcl, newAcl); + size_t size = 0; + // In case of unit test do not update persistant storage. + if (memcmp(newAcl->subject.id, &WILDCARD_SUBJECT_ID, sizeof(newAcl->subject.id)) == 0 + || memcmp(newAcl->subject.id, &WILDCARD_SUBJECT_B64_ID, sizeof(newAcl->subject.id)) == 0) + { + ehRet = OC_EH_RESOURCE_CREATED; + } + else + { + 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_RESOURCE_CREATED; + } + OICFree(cborPayload); + } + } } } // Send payload to request originator - SendSRMResponse(ehRequest, ehRet, NULL); + if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL, 0)) + { + ehRet = OC_EH_ERROR; + OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandleACLPostRequest"); + } - OC_LOG_V (INFO, TAG, "%s RetVal %d", __func__ , ehRet); + OIC_LOG_V(DEBUG, TAG, "%s RetVal %d", __func__, ehRet); return ehRet; } static OCEntityHandlerResult HandleACLDeleteRequest(const OCEntityHandlerRequest *ehRequest) { - OC_LOG (INFO, TAG, "Processing ACLDeleteRequest"); + OIC_LOG(DEBUG, TAG, "Processing ACLDeleteRequest"); OCEntityHandlerResult ehRet = OC_EH_ERROR; - OicUuid_t subject = {.id={0}}; - char resource[MAX_URI_LENGTH] = {0}; + OicUuid_t subject = { .id= { 0 } }; + char resource[MAX_URI_LENGTH] = { 0 }; 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); + VERIFY_SUCCESS(TAG, true == GetSubjectFromQueryString(ehRequest->query, &subject), ERROR); 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; } exit: // Send payload to request originator - SendSRMResponse(ehRequest, ehRet, NULL); + if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL, 0)) + { + ehRet = OC_EH_ERROR; + OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandleACLDeleteRequest"); + } return ehRet; } -/* - * This internal method is the entity handler for ACL resources and - * will handle REST request (GET/PUT/POST/DEL) for them. - */ -OCEntityHandlerResult ACLEntityHandler (OCEntityHandlerFlag flag, - OCEntityHandlerRequest * ehRequest, - void* callbackParameter) +OCEntityHandlerResult ACLEntityHandler(OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehRequest, + void* callbackParameter) { - OC_LOG(INFO, TAG, "Received request ACLEntityHandler"); + OIC_LOG(DEBUG, TAG, "Received request ACLEntityHandler"); (void)callbackParameter; OCEntityHandlerResult ehRet = OC_EH_ERROR; @@ -723,7 +1054,7 @@ OCEntityHandlerResult ACLEntityHandler (OCEntityHandlerFlag flag, if (flag & OC_REQUEST_FLAG) { // TODO : Handle PUT method - OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG"); + OIC_LOG(DEBUG, TAG, "Flag includes OC_REQUEST_FLAG"); switch (ehRequest->method) { case OC_REST_GET: @@ -740,17 +1071,17 @@ OCEntityHandlerResult ACLEntityHandler (OCEntityHandlerFlag flag, default: ehRet = OC_EH_ERROR; - SendSRMResponse(ehRequest, ehRet, NULL); + SendSRMResponse(ehRequest, ehRet, NULL, 0); } } return ehRet; } -/* +/** * This internal method is used to create '/oic/sec/acl' resource. */ -OCStackResult CreateACLResource() +static OCStackResult CreateACLResource() { OCStackResult ret; @@ -764,23 +1095,24 @@ OCStackResult CreateACLResource() if (OC_STACK_OK != ret) { - OC_LOG (FATAL, TAG, "Unable to instantiate ACL resource"); + OIC_LOG(FATAL, TAG, "Unable to instantiate ACL resource"); DeInitACLResource(); } return ret; } -/* - * This internal method is to retrieve the default ACL. - * If SVR database in persistent storage got corrupted or - * is not available for some reason, a default ACL is created - * which allows user to initiate ACL provisioning again. - */ -OCStackResult GetDefaultACL(OicSecAcl_t** defaultAcl) +// This function sets the default ACL and is defined for the unit test only. +OCStackResult SetDefaultACL(OicSecAcl_t *acl) +{ + gAcl = acl; + return OC_STACK_OK; +} + +OCStackResult GetDefaultACL(OicSecAcl_t** defaultAcl) { OCStackResult ret = OC_STACK_ERROR; - OicUuid_t ownerId = {.id = {0}}; + OicUuid_t ownerId = { .id = { 0 } }; /* * TODO In future, when new virtual resources will be added in OIC @@ -807,22 +1139,22 @@ OCStackResult GetDefaultACL(OicSecAcl_t** defaultAcl) return OC_STACK_INVALID_PARAM; } - OicSecAcl_t *acl = (OicSecAcl_t *)OICCalloc(1, sizeof(OicSecAcl_t)); + OicSecAcl_t *acl = (OicSecAcl_t *) OICCalloc(1, sizeof(OicSecAcl_t)); VERIFY_NON_NULL(TAG, acl, ERROR); // Subject -- Mandatory memcpy(&(acl->subject), &WILDCARD_SUBJECT_ID, sizeof(acl->subject)); // Resources -- Mandatory - acl->resourcesLen = sizeof(rsrcs)/sizeof(rsrcs[0]); + acl->resourcesLen = sizeof(rsrcs) / sizeof(rsrcs[0]); - acl->resources = (char**)OICCalloc(acl->resourcesLen, sizeof(char*)); + acl->resources = (char**) OICCalloc(acl->resourcesLen, sizeof(char*)); VERIFY_NON_NULL(TAG, (acl->resources), ERROR); - for (size_t i = 0; i < acl->resourcesLen; i++) + for (size_t i = 0; i < acl->resourcesLen; i++) { size_t len = strlen(rsrcs[i]) + 1; - acl->resources[i] = (char*)OICMalloc(len * sizeof(char)); + acl->resources[i] = (char*) OICMalloc(len * sizeof(char)); VERIFY_NON_NULL(TAG, (acl->resources[i]), ERROR); OICStrcpy(acl->resources[i], len, rsrcs[i]); } @@ -833,13 +1165,18 @@ OCStackResult GetDefaultACL(OicSecAcl_t** defaultAcl) acl->recurrences = NULL; // Device ID is the owner of this default ACL - ret = GetDoxmDeviceID( &ownerId); - VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, FATAL); + if (GetDoxmResourceData() != NULL) + { + ret = GetDoxmDeviceID(&ownerId); + VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, FATAL); + } + else + { + OCRandomUuidResult rdm = OCGenerateUuid(ownerId.id); + VERIFY_SUCCESS(TAG, RAND_UUID_OK == rdm, FATAL); + } - acl->ownersLen = 1; - acl->owners = (OicUuid_t*)OICMalloc(sizeof(OicUuid_t)); - VERIFY_NON_NULL(TAG, (acl->owners), ERROR); - memcpy(acl->owners, &ownerId, sizeof(OicUuid_t)); + memcpy(&acl->rownerID, &ownerId, sizeof(OicUuid_t)); acl->next = NULL; @@ -857,30 +1194,29 @@ exit: return ret; } -/** - * Initialize ACL resource by loading data from persistent storage. - * - * @retval OC_STACK_OK for Success, otherwise some error value - */ OCStackResult InitACLResource() { OCStackResult ret = OC_STACK_ERROR; - // Read ACL resource from PS - char* jsonSVRDatabase = GetSVRDatabase(); - - if (jsonSVRDatabase) + uint8_t *data = NULL; + size_t size = 0; + ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_ACL_NAME, &data, &size); + // If database read failed + if (ret != OC_STACK_OK) + { + OIC_LOG(DEBUG, TAG, "ReadSVDataFromPS failed"); + } + if (data) { - // Convert JSON ACL into binary format - gAcl = JSONToAclBin(jsonSVRDatabase); - OICFree(jsonSVRDatabase); + // Read ACL resource from PS + gAcl = CBORPayloadToAcl(data, size); } /* * If SVR database in persistent storage got corrupted or * is not available for some reason, a default ACL is created * which allows user to initiate ACL provisioning again. */ - if (!jsonSVRDatabase || !gAcl) + if (!gAcl) { GetDefaultACL(&gAcl); // TODO Needs to update persistent storage @@ -898,37 +1234,25 @@ exit: return ret; } -/** - * Perform cleanup for ACL resources. - * - * @retval none - */ -void DeInitACLResource() +OCStackResult DeInitACLResource() { - OCDeleteResource(gAclHandle); + OCStackResult ret = OCDeleteResource(gAclHandle); gAclHandle = NULL; - DeleteACLList(gAcl); - gAcl = NULL; + if (gAcl) + { + DeleteACLList(gAcl); + gAcl = NULL; + } + return ret; } -/** - * This method is used by PolicyEngine to retrieve ACL for a Subject. - * - * @param subjectId ID of the subject for which ACL is required. - * @param savePtr is used internally by @ref GetACLResourceData to maintain index between - * successive calls for same subjectId. - * - * @retval reference to @ref OicSecAcl_t if ACL is found, else NULL - * - * @note On the first call to @ref GetACLResourceData, savePtr should point to NULL - */ const OicSecAcl_t* GetACLResourceData(const OicUuid_t* subjectId, OicSecAcl_t **savePtr) { OicSecAcl_t *acl = NULL; OicSecAcl_t *begin = NULL; - if ( NULL == subjectId) + if (NULL == subjectId) { return NULL; } @@ -972,33 +1296,217 @@ const OicSecAcl_t* GetACLResourceData(const OicUuid_t* subjectId, OicSecAcl_t ** return NULL; } - -OCStackResult InstallNewACL(const char* newJsonStr) +OCStackResult InstallNewACL(const uint8_t *cborPayload, const size_t size) { OCStackResult ret = OC_STACK_ERROR; - // Convert JSON ACL data into binary. This will also validate the ACL data received. - OicSecAcl_t* newAcl = JSONToAclBin(newJsonStr); + // Convert CBOR format to ACL data. This will also validate the ACL data received. + OicSecAcl_t* newAcl = CBORPayloadToAcl(cborPayload, size); 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) + // Update persistent storage only if it is not WILDCARD_SUBJECT_ID + if (memcmp(newAcl->subject.id, &WILDCARD_SUBJECT_ID, sizeof(newAcl->subject.id)) == 0 + || memcmp(newAcl->subject.id, &WILDCARD_SUBJECT_B64_ID, sizeof(newAcl->subject.id)) == 0) { - cJSON *jsonAcl = cJSON_Parse(jsonStr); - OICFree(jsonStr); + ret = OC_STACK_OK; + } + else + { + 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); + } + } + } - if (jsonAcl) + return ret; +} + +/** + * This function generates default ACL for security resource in case of owned status. + * + * @return Default ACL for security resource. + */ +static OicSecAcl_t* GetSecDefaultACL() +{ + const char *sec_rsrcs[] = { + OIC_RSRC_DOXM_URI, + OIC_RSRC_PSTAT_URI + }; + OicUuid_t ownerId = {.id = {0}}; + OCStackResult res = OC_STACK_ERROR; + OicSecAcl_t* newDefaultAcl = (OicSecAcl_t*)OICCalloc(1, sizeof(OicSecAcl_t)); + VERIFY_NON_NULL(TAG, newDefaultAcl, ERROR); + + // Subject -- Mandatory + memcpy(&(newDefaultAcl->subject), &WILDCARD_SUBJECT_ID, WILDCARD_SUBJECT_ID_LEN); + + // Resources -- Mandatory + newDefaultAcl->resourcesLen = NUMBER_OF_DEFAULT_SEC_RSCS; + newDefaultAcl->resources = (char**)OICCalloc(NUMBER_OF_DEFAULT_SEC_RSCS, sizeof(char*)); + VERIFY_NON_NULL(TAG, (newDefaultAcl->resources), ERROR); + + for (size_t i = 0; i < NUMBER_OF_DEFAULT_SEC_RSCS; i++) + { + size_t len = strlen(sec_rsrcs[i]) + 1; + newDefaultAcl->resources[i] = (char*)OICMalloc(len * sizeof(char)); + VERIFY_NON_NULL(TAG, (newDefaultAcl->resources[i]), ERROR); + OICStrcpy(newDefaultAcl->resources[i], len, sec_rsrcs[i]); + } + + // Permissions -- Mandatory + newDefaultAcl->permission = PERMISSION_READ; + + //Period -- Not Mandatory + newDefaultAcl->prdRecrLen = 0; + newDefaultAcl->periods = NULL; + + //Recurrence -- Not Mandatory + newDefaultAcl->recurrences = NULL; + + // Device ID is the owner of this default ACL + res = GetDoxmDeviceID(&ownerId); + VERIFY_SUCCESS(TAG, OC_STACK_OK == res, FATAL); + + // Owners -- Mandatory + memcpy(&newDefaultAcl->rownerID, &ownerId, sizeof(OicUuid_t)); + + return newDefaultAcl; +exit: + DeleteACLList(newDefaultAcl); + return NULL; + +} + +OCStackResult UpdateDefaultSecProvACL() +{ + OCStackResult ret = OC_STACK_OK; + OicSecAcl_t *acl = NULL; + OicSecAcl_t *tmp = NULL; + + if(gAcl) + { + int matchedRsrc = 0; + bool isRemoved = false; + + LL_FOREACH_SAFE(gAcl, acl, tmp) + { + //Find default security resource ACL + if(memcmp(&acl->subject, &WILDCARD_SUBJECT_ID, sizeof(OicUuid_t)) == 0 && + ((PERMISSION_READ | PERMISSION_WRITE) == acl->permission)) + { + matchedRsrc = 0; + + for(size_t i = 0; i < acl->resourcesLen; i++) + { + if(strncmp(acl->resources[i], OIC_RSRC_DOXM_URI, + strlen(OIC_RSRC_DOXM_URI) + 1) == 0 || + strncmp(acl->resources[i], OIC_RSRC_CRED_URI, + strlen(OIC_RSRC_CRED_URI) + 1) == 0 || + strncmp(acl->resources[i], OIC_RSRC_ACL_URI, + strlen(OIC_RSRC_ACL_URI) + 1) == 0 || + strncmp(acl->resources[i], 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, acl); + FreeACE(acl); + isRemoved = true; + } + } + } + + if(isRemoved) + { + /* + * Generate new security resource ACL as follows : + * subject : "*" + * resources : '/oic/sec/doxm', '/oic/sec/pstat' + * permission : READ + */ + OicSecAcl_t *newDefaultAcl = GetSecDefaultACL(); + if (newDefaultAcl) { - ret = UpdateSVRDatabase(OIC_JSON_ACL_NAME, jsonAcl); + LL_APPEND(gAcl, newDefaultAcl); + + 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); + } } - cJSON_Delete(jsonAcl); } } 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; +}