X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=resource%2Fcsdk%2Fsecurity%2Fsrc%2Fpstatresource.c;h=ceb8949d2047b1b36e1cbe62d2e9ef43272d354d;hb=8e5920fe42063aa445bb20a0e092cbfbd3c3ee72;hp=360eb65b431d87bbc8ee894b20cd2a89ed928eb7;hpb=9a31ef80095f6382985404ba0a6c71437c9d8c43;p=platform%2Fupstream%2Fiotivity.git diff --git a/resource/csdk/security/src/pstatresource.c b/resource/csdk/security/src/pstatresource.c index 360eb65..ceb8949 100644 --- a/resource/csdk/security/src/pstatresource.c +++ b/resource/csdk/security/src/pstatresource.c @@ -32,6 +32,9 @@ #include "psinterface.h" #include "srmresourcestrings.h" #include "srmutility.h" +#include "aclresource.h" +#include "credresource.h" +#include "ocprovisioningmanager.h" #define TAG "OIC_SRM_PSTAT" @@ -224,6 +227,7 @@ exit: { // reallocate and try again! OICFree(outPayload); + outPayload = NULL; // Since the allocated initial memory failed, double the memory. cborLen += cbor_encoder_get_buffer_size(&encoder, encoder.end); cborEncoderResult = CborNoError; @@ -278,6 +282,7 @@ static OCStackResult CBORPayloadToPstatBin(const uint8_t *cborPayload, const siz pstat = (OicSecPstat_t *)OICCalloc(1, sizeof(OicSecPstat_t)); VERIFY_NON_NULL(TAG, pstat, ERROR); + pstat->sm = NULL; cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_ISOP_NAME, &pstatMap); if (CborNoError == cborFindResult && cbor_value_is_boolean(&pstatMap)) @@ -287,6 +292,7 @@ static OCStackResult CBORPayloadToPstatBin(const uint8_t *cborPayload, const siz } else { + VERIFY_NON_NULL(TAG, gPstat, ERROR); pstat->isOp = gPstat->isOp; cborFindResult = CborNoError; } @@ -301,13 +307,10 @@ static OCStackResult CBORPayloadToPstatBin(const uint8_t *cborPayload, const siz OICFree(strUuid ); strUuid = NULL; - if (roParsed) - { - *roParsed = true; - } } else { + VERIFY_NON_NULL(TAG, gPstat, ERROR); memcpy(&pstat->deviceID, &gPstat->deviceID, sizeof(OicUuid_t)); cborFindResult = CborNoError; } @@ -323,6 +326,7 @@ static OCStackResult CBORPayloadToPstatBin(const uint8_t *cborPayload, const siz } else { + VERIFY_NON_NULL(TAG, gPstat, ERROR); pstat->cm = gPstat->cm; cborFindResult = CborNoError; } @@ -338,6 +342,7 @@ static OCStackResult CBORPayloadToPstatBin(const uint8_t *cborPayload, const siz } else { + VERIFY_NON_NULL(TAG, gPstat, ERROR); pstat->tm = gPstat->tm; cborFindResult = CborNoError; } @@ -353,6 +358,7 @@ static OCStackResult CBORPayloadToPstatBin(const uint8_t *cborPayload, const siz } else { + VERIFY_NON_NULL(TAG, gPstat, ERROR); pstat->om = gPstat->om; cborFindResult = CborNoError; } @@ -364,6 +370,7 @@ static OCStackResult CBORPayloadToPstatBin(const uint8_t *cborPayload, const siz 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; @@ -378,6 +385,7 @@ static OCStackResult CBORPayloadToPstatBin(const uint8_t *cborPayload, const siz 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; } @@ -466,6 +474,30 @@ static bool ValidateQuery(const char * query) 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. */ @@ -510,17 +542,98 @@ static OCEntityHandlerResult HandlePstatGetRequest (const OCEntityHandlerRequest } /** + * Checks if device can change state to Ready for Normal Operation. + */ +static OCEntityHandlerResult ValidateReadyForNOP(const OicSecPstat_t *pstat) +{ + OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__); + + const OicSecDoxm_t *doxm = GetDoxmResourceData(); + OicUuid_t rowneruuid; + + if (!doxm) + { + OIC_LOG(WARNING, TAG, "DOXM is NULL"); + return OC_EH_NOT_ACCEPTABLE; + } + + if (!doxm->owned) + { + OIC_LOG(WARNING, TAG, "Can't change state to Ready for Normal Operation: the device is unowned"); + return OC_EH_NOT_ACCEPTABLE; + } + + if (IsNilUuid(&doxm->owner)) + { + OIC_LOG(WARNING, TAG, "Can't change state to Ready for Normal Operation: the device owner is NIL"); + return OC_EH_INTERNAL_SERVER_ERROR; + } + + if (IsNilUuid(&doxm->deviceID)) + { + OIC_LOG(WARNING, TAG, + "Can't change state to Ready for Normal Operation: the device owner ID is NIL"); + return OC_EH_INTERNAL_SERVER_ERROR; + } + + if (IsNilUuid(&doxm->rownerID)) + { + OIC_LOG(WARNING, TAG, "Can't change state to Ready for Normal Operation: the doxm rowner is NIL"); + return OC_EH_INTERNAL_SERVER_ERROR; + } + + + if (IsNilUuid(&pstat->rownerID)) + { + OIC_LOG(WARNING, TAG, "Can't change state to Ready for Normal Operation: the pstat rowner is NIL"); + return OC_EH_INTERNAL_SERVER_ERROR; + } + + memset(&rowneruuid, 0, sizeof(OicUuid_t)); + if (OC_STACK_OK != GetAclRownerId(&rowneruuid)) + { + OIC_LOG(WARNING, TAG, "Can't change state to Ready for Normal Operation: can't get acl"); + return OC_EH_INTERNAL_SERVER_ERROR; + } + + if (IsNilUuid(&rowneruuid)) + { + OIC_LOG(WARNING, TAG, "Can't change state to Ready for Normal Operation: the acl rowner is NIL"); + return OC_EH_INTERNAL_SERVER_ERROR; + } + + memset(&rowneruuid, 0, sizeof(OicUuid_t)); + if (OC_STACK_OK != GetCredRownerId(&rowneruuid)) + { + OIC_LOG(WARNING, TAG, "Can't change state to Ready for Normal Operation: can't get cred"); + return OC_EH_INTERNAL_SERVER_ERROR; + } + + if (IsNilUuid(&rowneruuid)) + { + OIC_LOG(WARNING, TAG, "Can't change state to Ready for Normal Operation: the cred rowner is NIL"); + return OC_EH_INTERNAL_SERVER_ERROR; + } + + OIC_LOG_V(DEBUG, TAG, "%s: OUT", __func__); + + return OC_EH_OK; + +} + +/** * The entity handler determines how to process a POST request. * Per the REST paradigm, POST can also be used to update representation of existing * resource or create a new resource. * For pstat, it updates only tm and om. */ -static OCEntityHandlerResult HandlePstatPostRequest(const OCEntityHandlerRequest *ehRequest) +static OCEntityHandlerResult HandlePstatPostRequest(OCEntityHandlerRequest *ehRequest) { OCEntityHandlerResult ehRet = OC_EH_ERROR; OIC_LOG(INFO, TAG, "HandlePstatPostRequest processing POST request"); OicSecPstat_t *pstat = NULL; - static uint16_t prevMsgId = 0; + static uint16_t previousMsgId = 0; + bool isDuplicatedMsg = false; if (ehRequest->payload && NULL != gPstat) { @@ -535,6 +648,17 @@ static OCEntityHandlerResult HandlePstatPostRequest(const OCEntityHandlerRequest { 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"); @@ -580,6 +704,11 @@ static OCEntityHandlerResult HandlePstatPostRequest(const OCEntityHandlerRequest } else if (false == (pstat->cm & TAKE_OWNER) && true == pstat->isOp) { + ehRet = ValidateReadyForNOP(pstat); + if(OC_EH_OK != ehRet) + { + goto exit; + } validReq = true; OIC_LOG (INFO, TAG, "State changed to Ready for Normal Operation"); } @@ -603,6 +732,7 @@ static OCEntityHandlerResult HandlePstatPostRequest(const OCEntityHandlerRequest 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 @@ -638,22 +768,32 @@ static OCEntityHandlerResult HandlePstatPostRequest(const OCEntityHandlerRequest * ownership transfer related resource should be revert back to initial status. */ const OicSecDoxm_t* doxm = GetDoxmResourceData(); - if(doxm) + if(doxm && !doxm->owned) { - if(!doxm->owned && prevMsgId != ehRequest->messageID) - { - RestoreDoxmToInitState(); - RestorePstatToInitState(); - } + 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 + ResetSecureResourceInPS(); + OIC_LOG(INFO, TAG, "DOXM will be reverted."); + } } else { OIC_LOG(ERROR, TAG, "Invalid DOXM resource."); + ResetSecureResourceInPS(); } } else { - prevMsgId = ehRequest->messageID; + if(ehRequest->devAddr.adapter == OC_ADAPTER_IP) + { + previousMsgId = ehRequest->messageID; + } } // Send response payload to request originator @@ -858,7 +998,15 @@ exit: */ bool GetPstatIsop() { - return gPstat->isOp; + if(NULL != gPstat) + { + return gPstat->isOp; + } + else + { + //In case of gPstat is NULL + return false; + } } OCStackResult GetPstatRownerId(OicUuid_t *rowneruuid) @@ -871,3 +1019,44 @@ OCStackResult GetPstatRownerId(OicUuid_t *rowneruuid) } 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; +} +