#include "psinterface.h"
#include "srmresourcestrings.h"
#include "srmutility.h"
+#include "aclresource.h"
+#include "credresource.h"
+#include "ocprovisioningmanager.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. */
if (CborNoError == cborEncoderResult)
{
- *size = encoder.ptr - outPayload;
+ *size = cbor_encoder_get_buffer_size(&encoder, outPayload);
*payload = outPayload;
ret = OC_STACK_OK;
}
{
// 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, writableOnly);
if (OC_STACK_OK == ret)
OICFree(strUuid );
strUuid = NULL;
- if (roParsed)
- {
- *roParsed = true;
- }
}
else
{
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;
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;
}
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.
*/
}
/**
+ * 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)
{
{
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");
}
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");
}
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
* 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
+ RestoreDoxmToInitState();
+ RestorePstatToInitState();
+ OIC_LOG(WARNING, 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
*/
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)
}
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;
+}
+