X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=resource%2Fcsdk%2Fsecurity%2Fsrc%2Fpstatresource.c;h=e32c86c5ccf30ba1d4103ce413ca278d26881568;hb=refs%2Ftags%2Faccepted%2Ftizen%2Funified%2F20171010.063815;hp=2fb01c066e0ba61e5a40d16a19b154b9cb854a75;hpb=19d62d6a8a53f556e3a91ef9b4f63c3e5f89c1b9;p=platform%2Fupstream%2Fiotivity.git diff --git a/resource/csdk/security/src/pstatresource.c b/resource/csdk/security/src/pstatresource.c index 2fb01c0..e32c86c 100644 --- a/resource/csdk/security/src/pstatresource.c +++ b/resource/csdk/security/src/pstatresource.c @@ -24,6 +24,7 @@ #include "ocstack.h" #include "oic_malloc.h" #include "ocpayload.h" +#include "ocpayloadcbor.h" #include "payload_logging.h" #include "resourcemanager.h" #include "pstatresource.h" @@ -32,23 +33,26 @@ #include "srmresourcestrings.h" #include "srmutility.h" -#define TAG "SRM-PSTAT" +#define TAG "OIC_SRM_PSTAT" /** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory. * The value of payload size is increased until reaching below max cbor size. */ -static const uint8_t CBOR_SIZE = 255; +static const uint16_t CBOR_SIZE = 512; // Max cbor size payload. static const uint16_t CBOR_MAX_SIZE = 4400; // PSTAT Map size - Number of mandatory items -static const uint8_t PSTAT_MAP_SIZE = 7; +static const uint8_t PSTAT_MAP_SIZE = 6; + +// Number of writeable property +static const uint8_t WRITEABLE_PROPERTY_SIZE = 3; static OicSecDpom_t gSm = SINGLE_SERVICE_CLIENT_DRIVEN; static OicSecPstat_t gDefaultPstat = { - false, // bool isOwned - (OicSecDpm_t)(TAKE_OWNER | BOOTSTRAP_SERVICE | SECURITY_MANAGEMENT_SERVICES | + false, // bool isop + (OicSecDpm_t)(BOOTSTRAP_SERVICE | SECURITY_MANAGEMENT_SERVICES | PROVISION_CREDENTIALS | PROVISION_ACLS), // OicSecDpm_t cm (OicSecDpm_t)(TAKE_OWNER | BOOTSTRAP_SERVICE | SECURITY_MANAGEMENT_SERVICES | PROVISION_CREDENTIALS | PROVISION_ACLS), // OicSecDpm_t tm @@ -57,12 +61,21 @@ static OicSecPstat_t gDefaultPstat = 1, // the number of elts in Sms &gSm, // OicSecDpom_t *sm 0, // uint16_t commitHash + {.id = {0}}, // OicUuid_t rownerID }; static OicSecPstat_t *gPstat = NULL; static OCResourceHandle gPstatHandle = NULL; +/** + * This method is internal method. + * the param roParsed is optionally used to know whether cborPayload has + * at least read only property value or not. + */ +static OCStackResult CBORPayloadToPstatBin(const uint8_t *cborPayload, const size_t size, + OicSecPstat_t **secPstat, bool *roParsed); + void DeletePstatBinData(OicSecPstat_t* pstat) { if (pstat) @@ -75,7 +88,8 @@ void DeletePstatBinData(OicSecPstat_t* pstat) } } -OCStackResult PstatToCBORPayload(const OicSecPstat_t *pstat, uint8_t **payload, size_t *size) +OCStackResult PstatToCBORPayload(const OicSecPstat_t *pstat, uint8_t **payload, size_t *size, + bool writableOnly) { if (NULL == pstat || NULL == payload || NULL != *payload || NULL == size) { @@ -92,9 +106,10 @@ OCStackResult PstatToCBORPayload(const OicSecPstat_t *pstat, uint8_t **payload, *size = 0; OCStackResult ret = OC_STACK_ERROR; - - CborEncoder encoder = { {.ptr = NULL }, .end = 0 }; - CborEncoder pstatMap = { {.ptr = NULL }, .end = 0 }; + size_t pstatMapSize = PSTAT_MAP_SIZE; + CborEncoder encoder; + CborEncoder pstatMap; + char* strUuid = NULL; int64_t cborEncoderResult = CborNoError; @@ -102,68 +117,105 @@ OCStackResult PstatToCBORPayload(const OicSecPstat_t *pstat, uint8_t **payload, VERIFY_NON_NULL(TAG, outPayload, ERROR); cbor_encoder_init(&encoder, outPayload, cborLen, 0); - cborEncoderResult |= cbor_encoder_create_map(&encoder, &pstatMap, PSTAT_MAP_SIZE); + if (false == writableOnly) + { + pstatMapSize += WRITEABLE_PROPERTY_SIZE; + } + + cborEncoderResult = cbor_encoder_create_map(&encoder, &pstatMap, pstatMapSize); VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Pstat Map."); - cborEncoderResult |= cbor_encode_text_string(&pstatMap, OIC_JSON_ISOP_NAME, + cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_ISOP_NAME, strlen(OIC_JSON_ISOP_NAME)); VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ISOP Name Tag."); - cborEncoderResult |= cbor_encode_boolean(&pstatMap, pstat->isOp); + cborEncoderResult = cbor_encode_boolean(&pstatMap, pstat->isOp); VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ISOP Name Value."); - cborEncoderResult |= cbor_encode_text_string(&pstatMap, OIC_JSON_DEVICE_ID_NAME, - strlen(OIC_JSON_DEVICE_ID_NAME)); - VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Id Tag."); - cborEncoderResult |= cbor_encode_byte_string(&pstatMap, (uint8_t *)pstat->deviceID.id, - sizeof(pstat->deviceID.id)); - VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Id Value."); - - cborEncoderResult |= cbor_encode_text_string(&pstatMap, OIC_JSON_COMMIT_HASH_NAME, - strlen(OIC_JSON_COMMIT_HASH_NAME)); - VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Commit Hash Tag."); - cborEncoderResult |= cbor_encode_int(&pstatMap, pstat->commitHash); - VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Commit Hash Value."); - - cborEncoderResult |= cbor_encode_text_string(&pstatMap, OIC_JSON_CM_NAME, + cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_CM_NAME, strlen(OIC_JSON_CM_NAME)); VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding CM Name Tag."); - cborEncoderResult |= cbor_encode_int(&pstatMap, pstat->cm); + cborEncoderResult = cbor_encode_int(&pstatMap, pstat->cm); VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding CM Name Value."); - cborEncoderResult |= cbor_encode_text_string(&pstatMap, OIC_JSON_TM_NAME, + cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_TM_NAME, strlen(OIC_JSON_TM_NAME)); VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding TM Name Tag."); - cborEncoderResult |= cbor_encode_int(&pstatMap, pstat->tm); + cborEncoderResult = cbor_encode_int(&pstatMap, pstat->tm); VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding TM Name Value."); - cborEncoderResult |= cbor_encode_text_string(&pstatMap, OIC_JSON_OM_NAME, + cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_OM_NAME, strlen(OIC_JSON_OM_NAME)); VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding OM Name Tag."); - cborEncoderResult |= cbor_encode_int(&pstatMap, pstat->om); + cborEncoderResult = cbor_encode_int(&pstatMap, pstat->om); VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding OM Name Value."); - cborEncoderResult |= cbor_encode_text_string(&pstatMap, OIC_JSON_SM_NAME, - strlen(OIC_JSON_SM_NAME)); - VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SM Name Tag."); + if (false == writableOnly) { - CborEncoder sm; - cborEncoderResult |= cbor_encoder_create_array(&pstatMap, &sm, pstat->smLen); - VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SM Array."); + cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_SM_NAME, + strlen(OIC_JSON_SM_NAME)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SM Name Tag."); + cborEncoderResult = cbor_encode_int(&pstatMap, pstat->sm[0]); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SM Name Value."); + + cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_DEVICE_ID_NAME, + strlen(OIC_JSON_DEVICE_ID_NAME)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Id Tag."); + ret = ConvertUuidToStr(&pstat->deviceID, &strUuid); + VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR); + cborEncoderResult = cbor_encode_text_string(&pstatMap, strUuid, strlen(strUuid)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Id Value."); + OICFree(strUuid); + strUuid = NULL; + + cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_ROWNERID_NAME, + strlen(OIC_JSON_ROWNERID_NAME)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ROwner Id Tag."); + ret = ConvertUuidToStr(&pstat->rownerID, &strUuid); + VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR); + cborEncoderResult = cbor_encode_text_string(&pstatMap, strUuid, strlen(strUuid)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ROwner Id Value."); + OICFree(strUuid); + strUuid = NULL; + } - for (size_t i = 0; i < pstat->smLen; i++) - { - cborEncoderResult |= cbor_encode_int(&sm, pstat->sm[i]); - VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SM Value in Array."); - } - cborEncoderResult |= cbor_encoder_close_container(&pstatMap, &sm); - VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing SM Array."); + //RT -- Mandatory + CborEncoder rtArray; + cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_RT_NAME, + strlen(OIC_JSON_RT_NAME)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Name Tag."); + cborEncoderResult = cbor_encoder_create_array(&pstatMap, &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_PSTAT, + strlen(OIC_RSRC_TYPE_SEC_PSTAT)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding RT Value."); + } + cborEncoderResult = cbor_encoder_close_container(&pstatMap, &rtArray); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing RT."); + + //IF-- Mandatory + CborEncoder ifArray; + cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_IF_NAME, + strlen(OIC_JSON_IF_NAME)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Name Tag."); + cborEncoderResult = cbor_encoder_create_array(&pstatMap, &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(&encoder, &pstatMap); + cborEncoderResult = cbor_encoder_close_container(&pstatMap, &ifArray); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing IF."); + + cborEncoderResult = cbor_encoder_close_container(&encoder, &pstatMap); VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Closing PSTAT Map."); if (CborNoError == cborEncoderResult) { - *size = encoder.ptr - outPayload; + *size = cbor_encoder_get_buffer_size(&encoder, outPayload); *payload = outPayload; ret = OC_STACK_OK; } @@ -172,10 +224,11 @@ exit: { // reallocate and try again! OICFree(outPayload); + outPayload = NULL; // 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 = PstatToCBORPayload(pstat, payload, &cborLen); + ret = PstatToCBORPayload(pstat, payload, &cborLen, writableOnly); if (OC_STACK_OK == ret) { *size = cborLen; @@ -197,7 +250,13 @@ exit: OCStackResult CBORPayloadToPstat(const uint8_t *cborPayload, const size_t size, OicSecPstat_t **secPstat) { - if (NULL == cborPayload || NULL == secPstat || NULL != *secPstat) + return CBORPayloadToPstatBin(cborPayload, size, secPstat, NULL); +} + +static OCStackResult CBORPayloadToPstatBin(const uint8_t *cborPayload, const size_t size, + OicSecPstat_t **secPstat, bool *roParsed) +{ + if (NULL == cborPayload || NULL == secPstat || NULL != *secPstat || 0 == size) { return OC_STACK_INVALID_PARAM; } @@ -208,14 +267,11 @@ OCStackResult CBORPayloadToPstat(const uint8_t *cborPayload, const size_t size, CborValue pstatCbor; CborParser parser; CborError cborFindResult = CborNoError; - int cborLen = size; + char *strUuid = NULL; size_t len = 0; - if (0 == size) - { - cborLen = CBOR_SIZE; - } - cbor_parser_init(cborPayload, cborLen, 0, &parser, &pstatCbor); - CborValue pstatMap; + + cbor_parser_init(cborPayload, size, 0, &parser, &pstatCbor); + CborValue pstatMap = { .parser = NULL }; OicSecPstat_t *pstat = NULL; cborFindResult = cbor_value_enter_container(&pstatCbor, &pstatMap); @@ -230,60 +286,117 @@ OCStackResult CBORPayloadToPstat(const uint8_t *cborPayload, const size_t size, cborFindResult = cbor_value_get_boolean(&pstatMap, &pstat->isOp); VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding isOp Value."); } + else + { + pstat->isOp = gPstat->isOp; + cborFindResult = CborNoError; + } cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_DEVICE_ID_NAME, &pstatMap); - if (CborNoError == cborFindResult && cbor_value_is_byte_string(&pstatMap)) + if (CborNoError == cborFindResult && cbor_value_is_text_string(&pstatMap)) { - uint8_t *subjectId = NULL; - cborFindResult = cbor_value_dup_byte_string(&pstatMap, &subjectId, &len, NULL); - VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding subjectId Value."); - memcpy(pstat->deviceID.id, subjectId, len); - OICFree(subjectId); - } + cborFindResult = cbor_value_dup_text_string(&pstatMap, &strUuid , &len, NULL); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Device Id Value."); + ret = ConvertStrToUuid(strUuid , &pstat->deviceID); + VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR); + OICFree(strUuid ); + strUuid = NULL; - cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_COMMIT_HASH_NAME, &pstatMap); - if (CborNoError == cborFindResult && cbor_value_is_integer(&pstatMap)) + } + else { - cborFindResult = cbor_value_get_int(&pstatMap, (int *) &pstat->commitHash); - VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding commitHash."); + memcpy(&pstat->deviceID, &gPstat->deviceID, sizeof(OicUuid_t)); + cborFindResult = CborNoError; } cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_CM_NAME, &pstatMap); if (CborNoError == cborFindResult && cbor_value_is_integer(&pstatMap)) { - cborFindResult = cbor_value_get_int(&pstatMap, (int *) &pstat->cm); + int cm; + + cborFindResult = cbor_value_get_int(&pstatMap, &cm); VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding CM."); + pstat->cm = (OicSecDpm_t)cm; + } + else + { + pstat->cm = gPstat->cm; + cborFindResult = CborNoError; + } + + cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_TM_NAME, &pstatMap); + if (CborNoError == cborFindResult && cbor_value_is_integer(&pstatMap)) + { + int tm; + + cborFindResult = cbor_value_get_int(&pstatMap, &tm); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding TM."); + pstat->tm = (OicSecDpm_t)tm; + } + else + { + pstat->tm = gPstat->tm; + cborFindResult = CborNoError; } cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_OM_NAME, &pstatMap); if (CborNoError == cborFindResult && cbor_value_is_integer(&pstatMap)) { - cborFindResult = cbor_value_get_int(&pstatMap, (int *) &pstat->om); + int om; + + cborFindResult = cbor_value_get_int(&pstatMap, &om); VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding OM."); + pstat->om = (OicSecDpom_t)om; + } + else + { + pstat->om = gPstat->om; + cborFindResult = CborNoError; } cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_SM_NAME, &pstatMap); - if (CborNoError == cborFindResult && cbor_value_is_array(&pstatMap)) + if (CborNoError == cborFindResult && cbor_value_is_integer(&pstatMap)) { - CborValue sm = { .parser = NULL }; - cborFindResult = cbor_value_get_array_length(&pstatMap, &pstat->smLen); - VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Array Len."); + int sm; - pstat->sm = (OicSecDpom_t *)OICCalloc(pstat->smLen, sizeof(OicSecDpom_t)); + pstat->smLen = 1; + pstat->sm = (OicSecDpom_t*)OICCalloc(pstat->smLen, sizeof(OicSecDpom_t)); VERIFY_NON_NULL(TAG, pstat->sm, ERROR); + cborFindResult = cbor_value_get_int(&pstatMap, &sm); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding SM."); + pstat->sm[0] = (OicSecDpom_t)sm; - cborFindResult = cbor_value_enter_container(&pstatMap, &sm); - VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering SM."); - - int i = 0; - while (cbor_value_is_valid(&sm)) + if (roParsed) { - cborFindResult = cbor_value_get_int(&sm, (int *)&pstat->sm[i++]); - VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding SM."); - cborFindResult = cbor_value_advance(&sm); - VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Closing SM."); + *roParsed = true; } } + else + { + VERIFY_NON_NULL(TAG, gPstat, ERROR); + pstat->smLen = gPstat->smLen; + pstat->sm = (OicSecDpom_t*)OICCalloc(pstat->smLen, sizeof(OicSecDpom_t)); + VERIFY_NON_NULL(TAG, pstat->sm, ERROR); + *pstat->sm = *gPstat->sm; + cborFindResult = CborNoError; + } + + cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_ROWNERID_NAME, &pstatMap); + if (CborNoError == cborFindResult && cbor_value_is_text_string(&pstatMap)) + { + cborFindResult = cbor_value_dup_text_string(&pstatMap, &strUuid , &len, NULL); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding ROwner Id Value."); + ret = ConvertStrToUuid(strUuid , &pstat->rownerID); + VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR); + OICFree(strUuid ); + strUuid = NULL; + } + else + { + VERIFY_NON_NULL(TAG, gPstat, ERROR); + memcpy(pstat->rownerID.id, gPstat->rownerID.id, sizeof(gPstat->rownerID.id)); + cborFindResult = CborNoError; + } *secPstat = pstat; ret = OC_STACK_OK; @@ -294,6 +407,7 @@ exit: OIC_LOG(ERROR, TAG, "CBORPayloadToPstat failed"); DeletePstatBinData(pstat); pstat = NULL; + *secPstat = NULL; ret = OC_STACK_ERROR; } @@ -309,7 +423,7 @@ static bool UpdatePersistentStorage(OicSecPstat_t *pstat) size_t size = 0; uint8_t *cborPayload = NULL; - OCStackResult ret = PstatToCBORPayload(pstat, &cborPayload, &size); + OCStackResult ret = PstatToCBORPayload(pstat, &cborPayload, &size, false); if (OC_STACK_OK == ret) { if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_PSTAT_NAME, cborPayload, size)) @@ -322,24 +436,98 @@ static bool UpdatePersistentStorage(OicSecPstat_t *pstat) return bRet; } +static bool ValidateQuery(const char * query) +{ + OIC_LOG (DEBUG, TAG, "In ValidateQuery"); + if(NULL == gPstat) + { + return false; + } + + bool bInterfaceQry = false; // does querystring contains 'if' query ? + bool bInterfaceMatch = false; // does 'if' query matches with oic.if.baseline ? + + OicParseQueryIter_t parseIter = {.attrPos = NULL}; + + ParseQueryIterInit((unsigned char*)query, &parseIter); + + while (GetNextQuery(&parseIter)) + { + if (strncasecmp((char *)parseIter.attrPos, OC_RSRVD_INTERFACE, parseIter.attrLen) == 0) + { + bInterfaceQry = true; + if ((strncasecmp((char *)parseIter.valPos, OC_RSRVD_INTERFACE_DEFAULT, parseIter.valLen) == 0)) + { + bInterfaceMatch = true; + } + } + } + return (bInterfaceQry ? bInterfaceMatch: true); +} + +#ifdef MULTIPLE_OWNER +bool IsValidPstatAccessForSubOwner(const uint8_t *cborPayload, size_t size) +{ + OicSecPstat_t* pstat = NULL; + bool isValidPstat = true; + + OIC_LOG_BUFFER(DEBUG, TAG, cborPayload, size); + VERIFY_NON_NULL(TAG, cborPayload, ERROR); + VERIFY_SUCCESS(TAG, 0 != size, ERROR); + VERIFY_SUCCESS(TAG, OC_STACK_OK == CBORPayloadToPstat(cborPayload, size, &pstat), ERROR); + VERIFY_NON_NULL(TAG, pstat, ERROR); + + if (RESET & pstat->cm) + { + OIC_LOG(ERROR, TAG, "SubOwner can't reset the server."); + isValidPstat = false; + } + +exit: + DeletePstatBinData(pstat); + return isValidPstat; +} +#endif //MULTIPLE_OWNER /** * The entity handler determines how to process a GET request. */ static OCEntityHandlerResult HandlePstatGetRequest (const OCEntityHandlerRequest * ehRequest) { + OCEntityHandlerResult ehRet = OC_EH_OK; + OIC_LOG(INFO, TAG, "HandlePstatGetRequest processing GET request"); - // Convert ACL data into CBOR for transmission + //Checking if Get request is a query. + if (ehRequest->query) + { + OIC_LOG_V(DEBUG,TAG,"query:%s",ehRequest->query); + OIC_LOG(DEBUG, TAG, "HandlePstatGetRequest processing query"); + if (!ValidateQuery(ehRequest->query)) + { + ehRet = OC_EH_ERROR; + } + } + + /* + * For GET or Valid Query request return doxm resource CBOR payload. + * For non-valid query return NULL json payload. + * A device will 'always' have a default Pstat, so PstatToCBORPayload will + * return valid pstat resource json. + */ size_t size = 0; uint8_t *payload = NULL; - OCStackResult res = PstatToCBORPayload(gPstat, &payload, &size); - - // A device should always have a default pstat. Therefore, payload should never be NULL. - OCEntityHandlerResult ehRet = (res == OC_STACK_OK) ? OC_EH_OK : OC_EH_ERROR; + if (ehRet == OC_EH_OK) + { + if(OC_STACK_OK != PstatToCBORPayload(gPstat, &payload, &size, false)) + { + OIC_LOG(WARNING, TAG, "PstatToCBORPayload failed in HandlePstatGetRequest"); + } + } // Send response payload to request originator - SendSRMCBORResponse(ehRequest, ehRet, payload, size); + ehRet = ((SendSRMResponse(ehRequest, ehRet, payload, size)) == OC_STACK_OK) ? + OC_EH_OK : OC_EH_ERROR; OICFree(payload); return ehRet; } @@ -350,75 +538,177 @@ static OCEntityHandlerResult HandlePstatGetRequest (const OCEntityHandlerRequest * resource or create a new resource. * For pstat, it updates only tm and om. */ -static OCEntityHandlerResult HandlePstatPutRequest(const OCEntityHandlerRequest *ehRequest) +static OCEntityHandlerResult HandlePstatPostRequest(OCEntityHandlerRequest *ehRequest) { OCEntityHandlerResult ehRet = OC_EH_ERROR; - OIC_LOG(INFO, TAG, "HandlePstatPutRequest processing PUT request"); + OIC_LOG(INFO, TAG, "HandlePstatPostRequest processing POST request"); OicSecPstat_t *pstat = NULL; + static uint16_t previousMsgId = 0; + bool isDuplicatedMsg = false; - if (ehRequest->resource) + if (ehRequest->payload && NULL != gPstat) { - uint8_t *payload = ((OCSecurityPayload *) ehRequest->payload)->securityData1; + uint8_t *payload = ((OCSecurityPayload *) ehRequest->payload)->securityData; size_t size = ((OCSecurityPayload *) ehRequest->payload)->payloadSize; VERIFY_NON_NULL(TAG, payload, ERROR); - OCStackResult ret = CBORPayloadToPstat(payload, size, &pstat); - OICFree(payload); + bool roParsed = false; + OCStackResult ret = CBORPayloadToPstatBin(payload, size, &pstat, &roParsed); VERIFY_NON_NULL(TAG, pstat, ERROR); if (OC_STACK_OK == ret) { - if (pstat->tm != NORMAL) + bool validReq = false; + + /* + * message ID is supported for CoAP over UDP only according to RFC 7252 + * So we should check message ID to prevent duplicate request handling in case of OC_ADAPTER_IP. + * In case of other transport adapter, duplicate message check is not required. + */ + if (OC_ADAPTER_IP == ehRequest->devAddr.adapter && + previousMsgId == ehRequest->messageID) + { + isDuplicatedMsg = true; + } + + if (true == roParsed) + { + OIC_LOG(ERROR, TAG, "Not acceptable request because of read-only properties"); + ehRet = OC_EH_NOT_ACCEPTABLE; + goto exit; + } + + //operation mode(om) should be one of supported modes(sm) + for(size_t i = 0; i < gPstat->smLen; i++) + { + if(gPstat->sm[i] == pstat->om) + { + validReq = true; + break; + } + } + + if(!validReq) + { + OIC_LOG_V(ERROR, TAG, "%d is unsupported Operation Mode", (int) pstat->om); + ehRet = OC_EH_BAD_REQ; + goto exit; + } + validReq = false; + + //Currently, IoTivity only supports Single Service Client Directed provisioning + if (pstat->om == SINGLE_SERVICE_CLIENT_DRIVEN) { - gPstat->tm = pstat->tm; - if(0 == pstat->tm && gPstat->commitHash == pstat->commitHash) + if ((pstat->cm & RESET) && false == pstat->isOp) + { + validReq = true; + OIC_LOG(INFO, TAG, "State changed to Ready for Reset"); + } + else if ((pstat->cm & TAKE_OWNER) && false == pstat->isOp) + { + validReq = true; + OIC_LOG (INFO, TAG, "State changed to Ready for Ownership transfer"); + } + else if (false == (pstat->cm & TAKE_OWNER) && false == pstat->isOp) + { + validReq = true; + OIC_LOG(INFO, TAG, "State changed to Ready for Provisioning"); + } + else if (false == (pstat->cm & TAKE_OWNER) && true == pstat->isOp) { - gPstat->isOp = true; - gPstat->cm = NORMAL; - OIC_LOG (INFO, TAG, "CommitHash is valid and isOp is TRUE"); + validReq = true; + OIC_LOG (INFO, TAG, "State changed to Ready for Normal Operation"); } else { - OIC_LOG(DEBUG, TAG, "CommitHash is not valid"); + OIC_LOG(DEBUG, TAG, "Invalid Device provisionig state"); + OIC_LOG_BUFFER(DEBUG, TAG, payload, size); + ehRet = OC_EH_BAD_REQ; + goto exit; } } - if (pstat->om != MULTIPLE_SERVICE_SERVER_DRIVEN && gPstat) + + if (!validReq) { - /* - * Check if the operation mode is in the supported provisioning services - * operation mode list. - */ - for (size_t i=0; i< gPstat->smLen; i++) - { - if(gPstat->sm[i] == pstat->om) - { - gPstat->om = pstat->om; - break; - } - } + OIC_LOG(DEBUG, TAG, "Bad request for PSTAT"); + ehRet = OC_EH_BAD_REQ; + goto exit; } + + gPstat->isOp = pstat->isOp; + gPstat->om = pstat->om; + gPstat->tm = pstat->tm; + gPstat->cm = pstat->cm; + memcpy(&(gPstat->deviceID), &(pstat->deviceID), sizeof(OicUuid_t)); + memcpy(&(gPstat->rownerID), &(pstat->rownerID), sizeof(OicUuid_t)); + // Convert pstat data into CBOR for update to persistent storage if (UpdatePersistentStorage(gPstat)) { ehRet = OC_EH_OK; } + if (true == (pstat->cm & RESET)) + { + if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL, 0)) + { + ehRet = OC_EH_ERROR; + OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandlePstatPostRequest"); + DeletePstatBinData(pstat); + return ehRet; + } + ret = ResetSecureResourceInPS(); + if (OC_STACK_OK == ret) + { + ehRet = OC_EH_OK; + } + DeletePstatBinData(pstat); + return ehRet; + } } } exit: - if(OC_EH_OK != ehRet) - { - /* - * If some error is occured while ownership transfer, - * ownership transfer related resource should be revert back to initial status. - */ - RestoreDoxmToInitState(); - RestorePstatToInitState(); - } - //Send payload to request originator - if(OC_STACK_OK != SendSRMCBORResponse(ehRequest, ehRet, NULL, 0)) - { - OIC_LOG (ERROR, TAG, "SendSRMResponse failed in HandlePstatPostRequest"); - } + if(OC_EH_OK != ehRet) + { + /* + * If some error is occured while ownership transfer, + * ownership transfer related resource should be revert back to initial status. + */ + const OicSecDoxm_t* doxm = GetDoxmResourceData(); + if(doxm) + { + if(!doxm->owned) + { + OIC_LOG(WARNING, TAG, "The operation failed during handle DOXM request"); + + if (!isDuplicatedMsg) + { +#if defined (__WITH_TLS__) || defined(__WITH_DTLS__) + InvokeOtmEventHandler(ehRequest->devAddr.addr, ehRequest->devAddr.port, + NULL, OIC_OTM_ERROR); +#endif + RestoreDoxmToInitState(); + RestorePstatToInitState(); + OIC_LOG(WARNING, TAG, "DOXM will be reverted."); + } + } + } + else + { + OIC_LOG(ERROR, TAG, "Invalid DOXM resource."); + } + } + else + { + if(ehRequest->devAddr.adapter == OC_ADAPTER_IP) + { + previousMsgId = ehRequest->messageID; + } + } + + // Send response payload to request originator + ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ? + OC_EH_OK : OC_EH_ERROR; + DeletePstatBinData(pstat); return ehRet; } @@ -441,12 +731,12 @@ static OCEntityHandlerResult HandlePstatPutRequest(const OCEntityHandlerRequest case OC_REST_GET: ehRet = HandlePstatGetRequest(ehRequest); break; - case OC_REST_PUT: - ehRet = HandlePstatPutRequest(ehRequest); + case OC_REST_POST: + ehRet = HandlePstatPostRequest(ehRequest); break; default: - ehRet = OC_EH_ERROR; - SendSRMCBORResponse(ehRequest, ehRet, NULL, 0); + ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ? + OC_EH_OK : OC_EH_ERROR; break; } } @@ -460,11 +750,12 @@ static OCEntityHandlerResult HandlePstatPutRequest(const OCEntityHandlerRequest { OCStackResult ret = OCCreateResource(&gPstatHandle, OIC_RSRC_TYPE_SEC_PSTAT, - OIC_MI_DEF, + OC_RSRVD_INTERFACE_DEFAULT, OIC_RSRC_PSTAT_URI, PstatEntityHandler, NULL, - OC_RES_PROP_NONE); + OC_SECURE | + OC_DISCOVERABLE); if (OC_STACK_OK != ret) { @@ -491,6 +782,7 @@ OCStackResult InitPstatResource() // Read Pstat resource from PS uint8_t *data = NULL; size_t size = 0; + OicUuid_t emptyUuid = {.id={0}}; ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_PSTAT_NAME, &data, &size); // If database read failed if (OC_STACK_OK != ret) @@ -514,6 +806,16 @@ OCStackResult InitPstatResource() } VERIFY_NON_NULL(TAG, gPstat, FATAL); + //In case of Pstat's device id is empty, fill the device id as doxm's device id. + if(0 == memcmp(&gPstat->deviceID, &emptyUuid, sizeof(OicUuid_t))) + { + OicUuid_t doxmUuid = {.id={0}}; + if(OC_STACK_OK == GetDoxmDeviceID(&doxmUuid)) + { + memcpy(&gPstat->deviceID, &doxmUuid, sizeof(OicUuid_t)); + } + } + // Instantiate 'oic.sec.pstat' ret = CreatePstatResource(); @@ -545,8 +847,8 @@ void RestorePstatToInitState() { OIC_LOG(INFO, TAG, "PSTAT resource will revert back to initial status."); - gPstat->cm = NORMAL; - gPstat->tm = NORMAL; + gPstat->cm = (OicSecDpm_t)(gPstat->cm | TAKE_OWNER); + gPstat->tm = (OicSecDpm_t)(gPstat->tm & (~TAKE_OWNER)); gPstat->om = SINGLE_SERVICE_CLIENT_DRIVEN; if(gPstat->sm && 0 < gPstat->smLen) { @@ -555,7 +857,107 @@ void RestorePstatToInitState() if (!UpdatePersistentStorage(gPstat)) { - OIC_LOG(ERROR, TAG, "Failed to revert DOXM in persistent storage"); + OIC_LOG(ERROR, TAG, "Failed to revert PSTAT in persistent storage"); } } } + +OCStackResult SetPstatRownerId(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 == gPstat) + { + ret = OC_STACK_NO_RESOURCE; + } + + if(newROwner && gPstat) + { + memcpy(prevId.id, gPstat->rownerID.id, sizeof(prevId.id)); + memcpy(gPstat->rownerID.id, newROwner->id, sizeof(newROwner->id)); + + ret = PstatToCBORPayload(gPstat, &cborPayload, &size, false); + VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR); + + ret = UpdateSecureResourceInPS(OIC_JSON_PSTAT_NAME, cborPayload, size); + VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR); + + OICFree(cborPayload); + } + + return ret; + +exit: + OICFree(cborPayload); + memcpy(gPstat->rownerID.id, prevId.id, sizeof(prevId.id)); + return ret; +} + +/** + * This function returns the "isop" status of the device. + * + * @return true iff pstat.isop == 1, else false + */ +bool GetPstatIsop() +{ + return gPstat->isOp; +} + +OCStackResult GetPstatRownerId(OicUuid_t *rowneruuid) +{ + OCStackResult retVal = OC_STACK_ERROR; + if (gPstat) + { + *rowneruuid = gPstat->rownerID; + retVal = OC_STACK_OK; + } + return retVal; +} + +OCStackResult SetPstatSelfOwnership(const OicUuid_t* newROwner) +{ + OCStackResult ret = OC_STACK_ERROR; + uint8_t *cborPayload = NULL; + size_t size = 0; + + if(NULL == gPstat) + { + ret = OC_STACK_NO_RESOURCE; + return ret; + } + + if( newROwner && (false == gPstat->isOp) && (true == (TAKE_OWNER && gPstat->cm)) ) + { + gPstat->cm = (OicSecDpm_t)(gPstat->cm & (~TAKE_OWNER)); + gPstat->isOp = true; + + memcpy(gPstat->deviceID.id, newROwner->id, sizeof(newROwner->id)); + memcpy(gPstat->rownerID.id, newROwner->id, sizeof(newROwner->id)); + + ret = PstatToCBORPayload(gPstat, &cborPayload, &size, false); + VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR); + + ret = UpdateSecureResourceInPS(OIC_JSON_PSTAT_NAME, cborPayload, size); + VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR); + + OICFree(cborPayload); + } + else + { + OIC_LOG(ERROR, TAG, "The state of PSTAT is not Ready For OTM"); + } + + return ret; + +exit: + OICFree(cborPayload); + return ret; +} +