X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=resource%2Fcsdk%2Fsecurity%2Fsrc%2Fpstatresource.c;h=f66b760bec42cf15622c2b5afa5168932472d706;hb=a4c5663cffebefb1a963859a7026ae961f921d3d;hp=f5c47461bffd5d1b816fd8f18a729f25a00dab9a;hpb=0e7762704ad69d816015184a55177d17c701188b;p=platform%2Fupstream%2Fiotivity.git diff --git a/resource/csdk/security/src/pstatresource.c b/resource/csdk/security/src/pstatresource.c index f5c4746..f66b760 100644 --- a/resource/csdk/security/src/pstatresource.c +++ b/resource/csdk/security/src/pstatresource.c @@ -18,27 +18,37 @@ // //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +#include +#include + #include "ocstack.h" -#include "logger.h" #include "oic_malloc.h" -#include "cJSON.h" +#include "ocpayload.h" +#include "payload_logging.h" #include "resourcemanager.h" #include "pstatresource.h" +#include "doxmresource.h" #include "psinterface.h" -#include "utlist.h" -#include "base64.h" #include "srmresourcestrings.h" #include "srmutility.h" -#include -#include #define TAG "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 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 OicSecDpom_t gSm = SINGLE_SERVICE_CLIENT_DRIVEN; static OicSecPstat_t gDefaultPstat = { false, // bool isOwned - (OicSecDpm_t)(TAKE_OWNER | BOOTSTRAP_SERVICE | SECURITY_MANAGEMENT_SERVICES | + (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 @@ -47,8 +57,11 @@ 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; void DeletePstatBinData(OicSecPstat_t* pstat) @@ -63,148 +76,271 @@ void DeletePstatBinData(OicSecPstat_t* pstat) } } -char * BinToPstatJSON(const OicSecPstat_t * pstat) +OCStackResult PstatToCBORPayload(const OicSecPstat_t *pstat, uint8_t **payload, size_t *size) { - if(NULL == pstat) + if (NULL == pstat || NULL == payload || NULL != *payload || NULL == size) { - return NULL; + return OC_STACK_INVALID_PARAM; } - cJSON *jsonPstat = NULL; - char *jsonStr = NULL; - cJSON *jsonSmArray = NULL; - char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*) 0)->id)) + 1] = {}; - uint32_t outLen = 0; - B64Result b64Ret = B64_OK; - - cJSON *jsonRoot = cJSON_CreateObject(); - VERIFY_NON_NULL(TAG, jsonRoot, INFO); - - cJSON_AddItemToObject(jsonRoot, OIC_JSON_PSTAT_NAME, jsonPstat=cJSON_CreateObject()); - cJSON_AddBoolToObject(jsonPstat, OIC_JSON_ISOP_NAME, pstat->isOp); + size_t cborLen = *size; + if (0 == cborLen) + { + cborLen = CBOR_SIZE; + } - b64Ret = b64Encode(pstat->deviceID.id, - sizeof(pstat->deviceID.id), base64Buff, sizeof(base64Buff), &outLen); - VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR); + *payload = NULL; + *size = 0; - cJSON_AddStringToObject(jsonPstat, OIC_JSON_DEVICE_ID_NAME, base64Buff); - cJSON_AddNumberToObject(jsonPstat, OIC_JSON_COMMIT_HASH_NAME, pstat->commitHash); - cJSON_AddNumberToObject(jsonPstat, OIC_JSON_CM_NAME, (int)pstat->cm); - cJSON_AddNumberToObject(jsonPstat, OIC_JSON_TM_NAME, (int)pstat->tm); - cJSON_AddNumberToObject(jsonPstat, OIC_JSON_OM_NAME, (int)pstat->om); + OCStackResult ret = OC_STACK_ERROR; - cJSON_AddItemToObject(jsonPstat, OIC_JSON_SM_NAME, jsonSmArray = cJSON_CreateArray()); - VERIFY_NON_NULL(TAG, jsonSmArray, INFO); - for (size_t i = 0; i < pstat->smLen; i++) + CborEncoder encoder = { {.ptr = NULL }, .end = 0 }; + CborEncoder pstatMap = { {.ptr = NULL }, .end = 0 }; + char* strUuid = NULL; + + int64_t cborEncoderResult = CborNoError; + + uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen); + VERIFY_NON_NULL(TAG, outPayload, ERROR); + cbor_encoder_init(&encoder, outPayload, cborLen, 0); + + cborEncoderResult = cbor_encoder_create_map(&encoder, &pstatMap, PSTAT_MAP_SIZE); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Pstat Map."); + + 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); + 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."); + 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_CM_NAME, + strlen(OIC_JSON_CM_NAME)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding CM Name Tag."); + 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, + strlen(OIC_JSON_TM_NAME)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding TM Name Tag."); + 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, + strlen(OIC_JSON_OM_NAME)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding OM Name Tag."); + 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."); + 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_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; + + cborEncoderResult = cbor_encoder_close_container(&encoder, &pstatMap); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Closing PSTAT Map."); + + if (CborNoError == cborEncoderResult) { - cJSON_AddItemToArray(jsonSmArray, cJSON_CreateNumber((int )pstat->sm[i])); + *size = encoder.ptr - outPayload; + *payload = outPayload; + ret = OC_STACK_OK; } - jsonStr = cJSON_Print(jsonRoot); - exit: - if (jsonRoot) + if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE)) { - cJSON_Delete(jsonRoot); + // reallocate and try again! + OICFree(outPayload); + // Since the allocated initial memory failed, double the memory. + cborLen += encoder.ptr - encoder.end; + cborEncoderResult = CborNoError; + ret = PstatToCBORPayload(pstat, payload, &cborLen); + if (OC_STACK_OK == ret) + { + *size = cborLen; + } + } + + if ((CborNoError != cborEncoderResult) || (OC_STACK_OK != ret)) + { + OICFree(outPayload); + outPayload = NULL; + *payload = NULL; + *size = 0; + ret = OC_STACK_ERROR; } - return jsonStr; + + return ret; } -OicSecPstat_t * JSONToPstatBin(const char * jsonStr) +OCStackResult CBORPayloadToPstat(const uint8_t *cborPayload, const size_t size, + OicSecPstat_t **secPstat) { - if(NULL == jsonStr) + if (NULL == cborPayload || NULL == secPstat || NULL != *secPstat) { - return NULL; + return OC_STACK_INVALID_PARAM; } OCStackResult ret = OC_STACK_ERROR; + *secPstat = NULL; + + CborValue pstatCbor; + CborParser parser; + CborError cborFindResult = CborNoError; + char *strUuid = NULL; + int cborLen = size; + size_t len = 0; + if (0 == size) + { + cborLen = CBOR_SIZE; + } + cbor_parser_init(cborPayload, cborLen, 0, &parser, &pstatCbor); + CborValue pstatMap = { .parser = NULL }; + OicSecPstat_t *pstat = NULL; - cJSON *jsonPstat = NULL; - cJSON *jsonObj = NULL; - - unsigned char base64Buff[sizeof(((OicUuid_t*) 0)->id)] = {}; - uint32_t outLen = 0; - B64Result b64Ret = B64_OK; - - cJSON *jsonRoot = cJSON_Parse(jsonStr); - VERIFY_NON_NULL(TAG, jsonRoot, INFO); - - jsonPstat = cJSON_GetObjectItem(jsonRoot, OIC_JSON_PSTAT_NAME); - VERIFY_NON_NULL(TAG, jsonPstat, INFO); - - pstat = (OicSecPstat_t*)OICCalloc(1, sizeof(OicSecPstat_t)); - VERIFY_NON_NULL(TAG, pstat, INFO); - jsonObj = cJSON_GetObjectItem(jsonPstat, OIC_JSON_ISOP_NAME); - VERIFY_NON_NULL(TAG, jsonObj, ERROR); - VERIFY_SUCCESS(TAG, (cJSON_True == jsonObj->type || cJSON_False == jsonObj->type) , ERROR); - pstat->isOp = jsonObj->valueint; - - jsonObj = cJSON_GetObjectItem(jsonPstat, OIC_JSON_DEVICE_ID_NAME); - VERIFY_NON_NULL(TAG, jsonObj, ERROR); - VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR); - b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring), base64Buff, - sizeof(base64Buff), &outLen); - VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(pstat->deviceID.id)), ERROR); - memcpy(pstat->deviceID.id, base64Buff, outLen); - - jsonObj = cJSON_GetObjectItem(jsonPstat, OIC_JSON_COMMIT_HASH_NAME); - VERIFY_NON_NULL(TAG, jsonObj, ERROR); - VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR); - pstat->commitHash = jsonObj->valueint; - - jsonObj = cJSON_GetObjectItem(jsonPstat, OIC_JSON_CM_NAME); - VERIFY_NON_NULL(TAG, jsonObj, ERROR); - VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR); - pstat->cm = (OicSecDpm_t)jsonObj->valueint; - - jsonObj = cJSON_GetObjectItem(jsonPstat, OIC_JSON_OM_NAME); - VERIFY_NON_NULL(TAG, jsonObj, ERROR); - VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR); - pstat->om = (OicSecDpom_t)jsonObj->valueint; - - jsonObj = cJSON_GetObjectItem(jsonPstat, OIC_JSON_SM_NAME); - VERIFY_NON_NULL(TAG, jsonObj, ERROR); - if (cJSON_Array == jsonObj->type) + cborFindResult = cbor_value_enter_container(&pstatCbor, &pstatMap); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PSTAT Map."); + + pstat = (OicSecPstat_t *)OICCalloc(1, sizeof(OicSecPstat_t)); + VERIFY_NON_NULL(TAG, pstat, ERROR); + + cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_ISOP_NAME, &pstatMap); + if (CborNoError == cborFindResult && cbor_value_is_boolean(&pstatMap)) + { + cborFindResult = cbor_value_get_boolean(&pstatMap, &pstat->isOp); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding isOp Value."); + } + + cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_DEVICE_ID_NAME, &pstatMap); + if (CborNoError == cborFindResult && cbor_value_is_text_string(&pstatMap)) { - pstat->smLen = cJSON_GetArraySize(jsonObj); - size_t idxx = 0; - VERIFY_SUCCESS(TAG, pstat->smLen != 0, ERROR); + 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_CM_NAME, &pstatMap); + if (CborNoError == cborFindResult && cbor_value_is_integer(&pstatMap)) + { + cborFindResult = cbor_value_get_int(&pstatMap, (int *) &pstat->cm); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding CM."); + } + + cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_TM_NAME, &pstatMap); + if (CborNoError == cborFindResult && cbor_value_is_integer(&pstatMap)) + { + cborFindResult = cbor_value_get_int(&pstatMap, (int *) &pstat->tm); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding TM."); + } + + 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); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding OM."); + } + + cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_SM_NAME, &pstatMap); + if (CborNoError == cborFindResult && cbor_value_is_integer(&pstatMap)) + { + pstat->smLen = 1; pstat->sm = (OicSecDpom_t*)OICCalloc(pstat->smLen, sizeof(OicSecDpom_t)); - VERIFY_NON_NULL(TAG, pstat->sm, ERROR); - do - { - cJSON *jsonSm = cJSON_GetArrayItem(jsonObj, idxx); - VERIFY_NON_NULL(TAG, jsonSm, ERROR); - pstat->sm[idxx] = (OicSecDpom_t)jsonSm->valueint; - }while ( ++idxx < pstat->smLen); + cborFindResult = cbor_value_get_int(&pstatMap, (int *) &pstat->sm[0]); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding SM."); + + } + + 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; } + + *secPstat = pstat; ret = OC_STACK_OK; exit: - cJSON_Delete(jsonRoot); - if (OC_STACK_OK != ret) + if (CborNoError != cborFindResult) { - OIC_LOG (ERROR, TAG, "JSONToPstatBin failed"); + OIC_LOG(ERROR, TAG, "CBORPayloadToPstat failed"); DeletePstatBinData(pstat); pstat = NULL; + *secPstat = NULL; + ret = OC_STACK_ERROR; } - return pstat; + + return ret; +} + +/** + * Function to update persistent storage + */ +static bool UpdatePersistentStorage(OicSecPstat_t *pstat) +{ + bool bRet = false; + + size_t size = 0; + uint8_t *cborPayload = NULL; + OCStackResult ret = PstatToCBORPayload(pstat, &cborPayload, &size); + if (OC_STACK_OK == ret) + { + if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_PSTAT_NAME, cborPayload, size)) + { + bRet = true; + } + OICFree(cborPayload); + } + + return bRet; } + /** * The entity handler determines how to process a GET request. */ static OCEntityHandlerResult HandlePstatGetRequest (const OCEntityHandlerRequest * ehRequest) { - OIC_LOG (INFO, TAG, "HandlePstatGetRequest processing GET request"); - // Convert ACL data into JSON for transmission - char* jsonStr = BinToPstatJSON(gPstat); + OIC_LOG(INFO, TAG, "HandlePstatGetRequest processing GET request"); - // A device should always have a default pstat. Therefore, jsonStr should never be NULL. - OCEntityHandlerResult ehRet = (jsonStr ? OC_EH_OK : OC_EH_ERROR); + // Convert ACL data into CBOR for transmission + 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; // Send response payload to request originator - SendSRMResponse(ehRequest, ehRet, jsonStr); - OICFree(jsonStr); + SendSRMCBORResponse(ehRequest, ehRet, payload, size); + OICFree(payload); return ehRet; } @@ -217,87 +353,89 @@ static OCEntityHandlerResult HandlePstatGetRequest (const OCEntityHandlerRequest static OCEntityHandlerResult HandlePstatPutRequest(const OCEntityHandlerRequest *ehRequest) { OCEntityHandlerResult ehRet = OC_EH_ERROR; - cJSON *postJson = NULL; - OIC_LOG (INFO, TAG, "HandlePstatPutRequest processing PUT request"); + OIC_LOG(INFO, TAG, "HandlePstatPutRequest processing PUT request"); + OicSecPstat_t *pstat = NULL; if (ehRequest->resource) { - postJson = cJSON_Parse(((OCSecurityPayload*)ehRequest->payload)->securityData); - VERIFY_NON_NULL(TAG, postJson, INFO); - cJSON *jsonPstat = cJSON_GetObjectItem(postJson, OIC_JSON_PSTAT_NAME); - VERIFY_NON_NULL(TAG, jsonPstat, INFO); - cJSON *commitHashJson = cJSON_GetObjectItem(jsonPstat, OIC_JSON_COMMIT_HASH_NAME); - uint16_t commitHash = 0; - if (commitHashJson) + uint8_t *payload = ((OCSecurityPayload *) ehRequest->payload)->securityData1; + size_t size = ((OCSecurityPayload *) ehRequest->payload)->payloadSize; + VERIFY_NON_NULL(TAG, payload, ERROR); + + OCStackResult ret = CBORPayloadToPstat(payload, size, &pstat); + OICFree(payload); + VERIFY_NON_NULL(TAG, pstat, ERROR); + if (OC_STACK_OK == ret) { - commitHash = commitHashJson->valueint; - } - cJSON *tmJson = cJSON_GetObjectItem(jsonPstat, OIC_JSON_TM_NAME); - if (tmJson && gPstat) - { - gPstat->tm = (OicSecDpm_t)tmJson->valueint; - if(0 == tmJson->valueint && gPstat->commitHash == commitHash) + if (false == (pstat->cm & TAKE_OWNER) && false == pstat->isOp) { - gPstat->isOp = true; - gPstat->cm = NORMAL; - OIC_LOG (INFO, TAG, "CommitHash is valid and isOp is TRUE"); + gPstat->cm = pstat->cm; + OIC_LOG (INFO, TAG, "State changed to Ready for Provisioning"); + } + else if (false == (pstat->cm & TAKE_OWNER) && true == pstat->isOp) + { + gPstat->isOp =pstat->isOp; + OIC_LOG (INFO, TAG, "State changed to Ready for Normal Operation"); } else { - OIC_LOG (INFO, TAG, "CommitHash is not valid"); + OIC_LOG(DEBUG, TAG, "Invalid Device provisionig state"); } - } - cJSON *omJson = cJSON_GetObjectItem(jsonPstat, OIC_JSON_OM_NAME); - if (omJson && gPstat) - { - /* - * Check if the operation mode is in the supported provisioning services - * operation mode list. - */ - for(size_t i=0; i< gPstat->smLen; i++) + if (pstat->om != MULTIPLE_SERVICE_SERVER_DRIVEN && gPstat) { - if(gPstat->sm[i] == (unsigned int)omJson->valueint) + /* + * Check if the operation mode is in the supported provisioning services + * operation mode list. + */ + for (size_t i=0; i< gPstat->smLen; i++) { - gPstat->om = (OicSecDpom_t)omJson->valueint; - break; + if(gPstat->sm[i] == pstat->om) + { + gPstat->om = pstat->om; + break; + } } } - } - // Convert pstat data into JSON for update to persistent storage - char *jsonStr = BinToPstatJSON(gPstat); - if (jsonStr) - { - cJSON *jsonPstat = cJSON_Parse(jsonStr); - OICFree(jsonStr); - if (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_PSTAT_NAME, jsonPstat)) + // Convert pstat data into CBOR for update to persistent storage + if (UpdatePersistentStorage(gPstat)) { ehRet = OC_EH_OK; } } } 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 != SendSRMResponse(ehRequest, ehRet, NULL)) + if(OC_STACK_OK != SendSRMCBORResponse(ehRequest, ehRet, NULL, 0)) { OIC_LOG (ERROR, TAG, "SendSRMResponse failed in HandlePstatPostRequest"); } - cJSON_Delete(postJson); + DeletePstatBinData(pstat); return ehRet; } /** * This internal method is the entity handler for pstat resources. */ -OCEntityHandlerResult PstatEntityHandler(OCEntityHandlerFlag flag, - OCEntityHandlerRequest * ehRequest, - void *callbackParam) + OCEntityHandlerResult PstatEntityHandler(OCEntityHandlerFlag flag, + OCEntityHandlerRequest * ehRequest, + void *callbackParam) { (void)callbackParam; OCEntityHandlerResult ehRet = OC_EH_ERROR; // This method will handle REST request (GET/POST) for /oic/sec/pstat if (flag & OC_REQUEST_FLAG) { - OIC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG"); + OIC_LOG(INFO, TAG, "Flag includes OC_REQUEST_FLAG"); switch (ehRequest->method) { case OC_REST_GET: @@ -308,7 +446,7 @@ OCEntityHandlerResult PstatEntityHandler(OCEntityHandlerFlag flag, break; default: ehRet = OC_EH_ERROR; - SendSRMResponse(ehRequest, ehRet, NULL); + SendSRMCBORResponse(ehRequest, ehRet, NULL, 0); break; } } @@ -318,83 +456,78 @@ OCEntityHandlerResult PstatEntityHandler(OCEntityHandlerFlag flag, /** * This internal method is used to create '/oic/sec/pstat' resource. */ -OCStackResult CreatePstatResource() + OCStackResult CreatePstatResource() { - OCStackResult ret; + OCStackResult ret = OCCreateResource(&gPstatHandle, + OIC_RSRC_TYPE_SEC_PSTAT, + OIC_MI_DEF, + OIC_RSRC_PSTAT_URI, + PstatEntityHandler, + NULL, + OC_RES_PROP_NONE); - ret = OCCreateResource(&gPstatHandle, - OIC_RSRC_TYPE_SEC_PSTAT, - OIC_MI_DEF, - OIC_RSRC_PSTAT_URI, - PstatEntityHandler, - NULL, - OC_RES_PROP_NONE); - - if (ret != OC_STACK_OK) + if (OC_STACK_OK != ret) { - OIC_LOG (FATAL, TAG, "Unable to instantiate pstat resource"); + OIC_LOG(FATAL, TAG, "Unable to instantiate pstat resource"); DeInitPstatResource(); } return ret; } /** - * Post ACL hander update the commitHash during ACL provisioning. - */ -void SetCommitHash(uint16_t commitHash) -{ - gPstat->commitHash = commitHash; -} - -/** - * Get the default value - * @retval the gDefaultPstat pointer + * Get the default value. + * + * @return the gDefaultPstat pointer. */ static OicSecPstat_t* GetPstatDefault() { return &gDefaultPstat; } -/** - * Initialize pstat resource by loading data from persistent storage. - * - * @retval OC_STACK_OK for Success, otherwise some error value - */ OCStackResult InitPstatResource() { OCStackResult ret = OC_STACK_ERROR; // Read Pstat resource from PS - char* jsonSVRDatabase = GetSVRDatabase(); - if (jsonSVRDatabase) + uint8_t *data = NULL; + size_t size = 0; + ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_PSTAT_NAME, &data, &size); + // If database read failed + if (OC_STACK_OK != ret) + { + OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed"); + } + if (data) { - // Convert JSON Pstat into binary format - gPstat = JSONToPstatBin(jsonSVRDatabase); + // Read ACL resource from PS + ret = CBORPayloadToPstat(data, size, &gPstat); + OICFree(data); } /* * If SVR database in persistent storage got corrupted or * is not available for some reason, a default pstat is created * which allows user to initiate pstat provisioning again. */ - if(!jsonSVRDatabase || !gPstat) + if ((OC_STACK_OK != ret) || !gPstat) { gPstat = GetPstatDefault(); } + VERIFY_NON_NULL(TAG, gPstat, FATAL); + // Instantiate 'oic.sec.pstat' ret = CreatePstatResource(); - OICFree(jsonSVRDatabase); +exit: + if (OC_STACK_OK != ret) + { + DeInitPstatResource(); + } return ret; } -/** - * Perform cleanup for pstat resources. - * - * @retval OC_STACK_OK for Success, otherwise some error value - */ OCStackResult DeInitPstatResource() { - if(gPstat != &gDefaultPstat) + if (gPstat != &gDefaultPstat) { DeletePstatBinData(gPstat); gPstat = NULL; @@ -402,3 +535,66 @@ OCStackResult DeInitPstatResource() return OCDeleteResource(gPstatHandle); } +/** + * Function to restore pstat resurce to initial status. + * This function will use in case of error while ownership transfer + */ +void RestorePstatToInitState() +{ + if(gPstat) + { + OIC_LOG(INFO, TAG, "PSTAT resource will revert back to initial status."); + + 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) + { + gPstat->sm[0] = SINGLE_SERVICE_CLIENT_DRIVEN; + } + + if (!UpdatePersistentStorage(gPstat)) + { + 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); + 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; +} +