Commit 208de841 authored by Nathan Heldt-Sheller's avatar Nathan Heldt-Sheller Committed by Greg Zaverucha

[IOT-1763] Implemented device onboarding state CR 23

Added oic.r.pstat Property "dos" as made mandatory by
OCF Security Specification CR 23.

patch set 2: Functional cbor marshalling.

patch set 3: Updated json2cbor tool and every svr.json and
.dat file I could find to use the new pstat.dos property.

patch set 4: Updated json2cbor tool to support oic 1.1 format
but print warning if .dos property not found.

patch set 5: Added better handling for .dat files that don't
contain "dos" Property, to aid in legacy app migration.

patch set 6: Rebase.

patch set 7: Fixed unittest issue that appeared after re-base,
and addressed misc comments on patch set 5.

patch set 8: commit msg fix.

patch set 9: added "TODO" items for UPDATE handling once
other CRs are done.

patch set 10: addressed a few of Kevin's comments.

patch set 11: rebase

patch set 12: addressed Greg's request for specific JIRA numbers.

Change-Id: I6d9751ff1e6d7d88789e1462819736b38f176a53
Signed-off-by: Nathan Heldt-Sheller's avatarNathan Heldt-Sheller <nathan.heldt-sheller@intel.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/17993Tested-by: default avatarjenkins-iotivity <jenkins@iotivity.org>
Reviewed-by: default avatarPhil Coval <philippe.coval@osg.samsung.com>
Reviewed-by: default avatarGreg Zaverucha <gregz@microsoft.com>
parent 13baa549
......@@ -61,6 +61,7 @@
"rowneruuid" : "61646D69-6E44-6576-6963-655575696430"
},
"pstat": {
"dos": {"s": 3, "p": false},
"isop": true,
"cm": 2,
"tm": 0,
......
......@@ -49,6 +49,7 @@
"rowneruuid" : "61646D69-6E44-6576-6963-655575696430"
},
"pstat": {
"dos": {"s": 3, "p": false},
"isop": true,
"cm": 2,
"tm": 0,
......
......@@ -49,6 +49,7 @@
"rowneruuid" : "32323232-3232-3232-3232-323232323232"
},
"pstat": {
"dos": {"s": 3, "p": false},
"isop": true,
"deviceuuid": "32323232-3232-3232-3232-323232323232",
"rowneruuid": "32323232-3232-3232-3232-323232323232",
......
......@@ -79,6 +79,7 @@
"rowneruuid" : "31313131-3131-3131-3131-313131313131"
},
"pstat": {
"dos": {"s": 3, "p": false},
"isop": true,
"deviceuuid": "31313131-3131-3131-3131-313131313131",
"rowneruuid": "31313131-3131-3131-3131-313131313131",
......
......@@ -24,6 +24,7 @@
}
],
"pstat": {
"dos": {"s": 3, "p": false},
"isop": true,
"deviceid": "YWRtaW5EZXZpY2VVVUlEMA==",
"ch": 0,
......
......@@ -24,6 +24,7 @@
}
],
"pstat": {
"dos": {"s": 3, "p": false},
"isop": true,
"deviceid": "ZGV2aWNlaWQAAAAAABhanw==",
"ch": 0,
......
......@@ -24,6 +24,7 @@
}
],
"pstat": {
"dos": {"s": 3, "p": false},
"isop": true,
"deviceid": "ZGV2aWNlaWQAAAAAABhanw==",
"ch": 0,
......
......@@ -67,6 +67,7 @@
"rowneruuid" : "31313131-3131-3131-3131-313131313131"
},
"pstat": {
"dos": {"s": 3, "p": false},
"isop": true,
"deviceuuid": "31313131-3131-3131-3131-313131313131",
"rowneruuid": "31313131-3131-3131-3131-313131313131",
......
......@@ -157,6 +157,9 @@ extern const char * OIC_JSON_EOWNERID_NAME;
extern const char * OIC_JSON_ENCODING_NAME;
extern const char * OIC_JSON_DATA_NAME;
extern const char * OIC_JSON_SEC_V_NAME;
extern const char * OIC_JSON_DOS_NAME;
extern const char * OIC_JSON_S_NAME;
extern const char * OIC_JSON_P_NAME;
extern const char * OIC_JSON_EMPTY_STRING;
......
......@@ -218,6 +218,21 @@ typedef unsigned int OSCTBitmask_t;
*/
typedef OSCTBitmask_t OicSecCredType_t;
typedef enum OicSecDeviceOnboardingState
{
DOS_RESET = 0,
DOS_RFOTM,
DOS_RFPRO,
DOS_RFNOP,
DOS_SRESET
} OicSecDeviceOnboardingState_t;
typedef struct OicSecDostype
{
OicSecDeviceOnboardingState_t state;
bool pending;
} OicSecDostype_t;
typedef struct OicSecDoxm OicSecDoxm_t;
/**
......@@ -541,6 +556,7 @@ struct OicSecDoxm
struct OicSecPstat
{
// <Attribute ID>:<Read/Write>:<Multiple/Single>:<Mandatory?>:<Type>
OicSecDostype_t dos; // -:RW:S:Y:oic.sec.dostype
bool isOp; // 0:R:S:Y:Boolean
OicSecDpm_t cm; // 1:R:S:Y:oic.sec.dpmtype
OicSecDpm_t tm; // 2:RW:S:Y:oic.sec.dpmtype
......
This diff was suppressed by a .gitattributes entry.
......@@ -47,6 +47,7 @@
"rowneruuid" : "61646D69-6E44-6576-6963-655575696430"
},
"pstat": {
"dos": {"s": 3, "p": false},
"isop": true,
"cm": 0,
"tm": 0,
......
......@@ -47,6 +47,7 @@
"rowneruuid" : "61646D69-6E44-6576-6963-655575696430"
},
"pstat": {
"dos": {"s": 3, "p": false},
"isop": true,
"cm": 0,
"tm": 0,
......
......@@ -53,6 +53,7 @@
"rowneruuid" : ""
},
"pstat": {
"dos": {"s": 1, "p": false},
"isop": false,
"deviceuuid": "",
"rowneruuid": "",
......
......@@ -53,6 +53,7 @@
"rowneruuid" : "6A757374-776F-726B-4465-765575696430"
},
"pstat": {
"dos": {"s": 1, "p": false},
"isop": false,
"deviceuuid": "6A757374-776F-726B-4465-765575696430",
"rowneruuid": "6A757374-776F-726B-4465-765575696430",
......
......@@ -53,6 +53,7 @@
"rowneruuid" : "6D766A75-7374-776F-726B-735575696430"
},
"pstat": {
"dos": {"s": 1, "p": false},
"isop": false,
"deviceuuid": "6D766A75-7374-776F-726B-735575696430",
"rowneruuid": "6D766A75-7374-776F-726B-735575696430",
......
......@@ -53,6 +53,7 @@
"rowneruuid" : "50726563-6F6E-6669-6775-72656450494E"
},
"pstat": {
"dos": {"s": 1, "p": false},
"isop": false,
"deviceuuid": "50726563-6F6E-6669-6775-72656450494E",
"rowneruuid": "50726563-6F6E-6669-6775-72656450494E",
......
......@@ -53,6 +53,7 @@
"rowneruuid" : "72616E64-5069-6E44-6576-557569643030"
},
"pstat": {
"dos": {"s": 1, "p": false},
"isop": false,
"deviceuuid": "72616E64-5069-6E44-6576-557569643030",
"rowneruuid": "72616E64-5069-6E44-6576-557569643030",
......
......@@ -65,6 +65,7 @@
"rowneruuid" : "5375624F-776E-6572-436C-69656E743030"
},
"pstat": {
"dos": {"s": 3, "p": false},
"isop": true,
"cm": 0,
"tm": 0,
......
......@@ -43,14 +43,18 @@ static const uint16_t CBOR_SIZE = 512;
static const uint16_t CBOR_MAX_SIZE = 4400;
// PSTAT Map size - Number of mandatory items
static const uint8_t PSTAT_MAP_SIZE = 6;
static const uint8_t PSTAT_MAP_SIZE = 7;
// .dos Property map size
static const uint8_t PSTAT_DOS_MAP_SIZE = 2;
// Number of writeable property
static const uint8_t WRITEABLE_PROPERTY_SIZE = 2;
static const uint8_t WRITEABLE_PROPERTY_SIZE = 3;
static OicSecDpom_t gSm = SINGLE_SERVICE_CLIENT_DRIVEN;
static OicSecPstat_t gDefaultPstat =
{
{DOS_RFOTM, false}, // OicSecDostype_t dos
false, // bool isop
TAKE_OWNER, // OicSecDpm_t cm
NORMAL, // OicSecDpm_t tm
......@@ -65,6 +69,16 @@ static OicSecPstat_t *gPstat = NULL;
static OCResourceHandle gPstatHandle = NULL;
/**
* Get the default value.
*
* @return the gDefaultPstat pointer.
*/
static OicSecPstat_t* GetPstatDefault()
{
return &gDefaultPstat;
}
/**
* This method is internal method.
* the param roParsed is optionally used to know whether cborPayload has
......@@ -85,6 +99,28 @@ void DeletePstatBinData(OicSecPstat_t* pstat)
}
}
/**
* 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, false);
if (OC_STACK_OK == ret)
{
if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_PSTAT_NAME, cborPayload, size))
{
bRet = true;
}
OICFree(cborPayload);
}
return bRet;
}
OCStackResult PstatToCBORPayload(const OicSecPstat_t *pstat, uint8_t **payload, size_t *size,
bool writableOnly)
{
......@@ -120,27 +156,59 @@ OCStackResult PstatToCBORPayload(const OicSecPstat_t *pstat, uint8_t **payload,
pstatMapSize += WRITEABLE_PROPERTY_SIZE;
}
// Top Level Pstat Map
cborEncoderResult = cbor_encoder_create_map(&encoder, &pstatMap, pstatMapSize);
VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Pstat Map.");
// Device Onboarding State Property tag
cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_DOS_NAME,
strlen(OIC_JSON_DOS_NAME));
VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding dos Name Tag.");
// Device Onboarding State Property map
CborEncoder dosMap;
cborEncoderResult = cbor_encoder_create_map(&pstatMap, &dosMap, PSTAT_DOS_MAP_SIZE);
VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed creating pstat.dos map");
cborEncoderResult = cbor_encode_text_string(&dosMap, OIC_JSON_S_NAME,
strlen(OIC_JSON_S_NAME));
VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding pstat.dos.s tag.");
cborEncoderResult = cbor_encode_int(&dosMap, pstat->dos.state);
VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding pstat.dos.s value.");
cborEncoderResult = cbor_encode_text_string(&dosMap, OIC_JSON_P_NAME,
strlen(OIC_JSON_P_NAME));
VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding pstat.dos.p tag.");
cborEncoderResult = cbor_encode_boolean(&dosMap, pstat->dos.pending);
VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding pstat.dos.p value.");
cborEncoderResult = cbor_encoder_close_container(&pstatMap, &dosMap);
VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed closing pstat.dos map");
// IsOp Property
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.");
// cm Property
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.");
// tm Property
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.");
// om Property
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.");
......@@ -149,12 +217,14 @@ OCStackResult PstatToCBORPayload(const OicSecPstat_t *pstat, uint8_t **payload,
if (false == writableOnly)
{
// sm Property
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.");
// rowneruuid property
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.");
......@@ -250,24 +320,108 @@ static OCStackResult CBORPayloadToPstatBin(const uint8_t *cborPayload, const siz
}
OCStackResult ret = OC_STACK_ERROR;
*secPstat = NULL;
CborValue pstatCbor;
CborParser parser;
CborValue pstatCbor = { .parser = NULL };
CborValue pstatMap = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
CborValue dosMap = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
CborParser parser = { .end = NULL };
CborError cborFindResult = CborNoError;
char *strUuid = NULL;
char *dosTagName = NULL;
size_t len = 0;
size_t dosLen = 0;
OicSecPstat_t *pstat = NULL;
cbor_parser_init(cborPayload, size, 0, &parser, &pstatCbor);
CborValue pstatMap = { .parser = NULL };
*secPstat = NULL;
OicSecPstat_t *pstat = NULL;
cborFindResult = cbor_value_enter_container(&pstatCbor, &pstatMap);
VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PSTAT Map.");
// init cbor parser
cbor_parser_init(cborPayload, size, 0, &parser, &pstatCbor);
// allocate pstat struct
pstat = (OicSecPstat_t *)OICCalloc(1, sizeof(OicSecPstat_t));
VERIFY_NOT_NULL(TAG, pstat, ERROR);
// Individual Properties missing from cbor representation may result in
// pstat Property assignment to existing gPstat values. Therefore,
// we must ensure that gPstat to a valid value, to avoid null deref.
if (!gPstat)
{
gPstat = GetPstatDefault();
}
VERIFY_NOT_NULL(TAG, gPstat, FATAL);
// Enter pstat Map
cborFindResult = cbor_value_enter_container(&pstatCbor, &pstatMap);
VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering pstat Map.");
// Find pstat.dos tag
cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_DOS_NAME, &pstatMap);
VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding dos tag.");
if (CborInvalidType != pstatMap.type)
{
// found pstat.dos tag "dos" in pstatMap
OIC_LOG(INFO, TAG, "Found pstat.dos tag in pstatMap.");
if (CborNoError == cborFindResult && cbor_value_is_container(&pstatMap))
{
OIC_LOG(INFO, TAG, "Found pstat.dos cbor container; entering.");
cborFindResult = cbor_value_enter_container(&pstatMap, &dosMap);
VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering dos map.");
}
while (cbor_value_is_valid(&dosMap) && cbor_value_is_text_string(&dosMap))
{
cborFindResult = cbor_value_dup_text_string(&dosMap, &dosTagName, &dosLen, NULL);
VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed getting dos map next tag.");
cborFindResult = cbor_value_advance(&dosMap);
VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed advancing dos map.");
if (NULL != dosTagName)
{
if (strcmp(dosTagName, OIC_JSON_S_NAME) == 0)
{
OIC_LOG(INFO, TAG, "Found pstat.dos.s tag; getting int value.");
int s = -1;
cborFindResult = cbor_value_get_int(&dosMap, &s);
VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed getting pstat.dos.s value.");
OIC_LOG_V(INFO, TAG, "Read pstat.dos.s value = %d.", s);
pstat->dos.state = (OicSecDeviceOnboardingState_t)s;
}
else if (strcmp(dosTagName, OIC_JSON_P_NAME) == 0)
{
OIC_LOG(INFO, TAG, "Found pstat.dos.p tag; getting boolean value.");
bool p = false;
cborFindResult = cbor_value_get_boolean(&dosMap, &p);
VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed getting pstat.dos.p value.");
OIC_LOG_V(INFO, TAG, "Read pstat.dos.p value = %s.", p?"true":"false");
pstat->dos.pending = p;
}
else
{
OIC_LOG_V(WARNING, TAG, "Unknown tag name in dos map: %s", dosTagName);
}
free(dosTagName);
dosTagName = NULL;
}
if (cbor_value_is_valid(&dosMap))
{
cborFindResult = cbor_value_advance(&dosMap);
VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed advancing dos map.");
}
}
}
else
{
// didn't find pstat.dos tag "dos" in pstatMap
OIC_LOG(WARNING, TAG, "Did not find mandatory pstat.dos tag in pstatMap.");
OIC_LOG(WARNING, TAG, "If this is not an intentionally-partial pstat representation,");
OIC_LOG(WARNING, TAG, "it may be an outdated .dat file that is missing the \"dos\" Property.");
OIC_LOG(WARNING, TAG, "Using existing pstat.dos value from gPstat.");
pstat->dos.state = gPstat->dos.state;
pstat->dos.pending = gPstat->dos.pending;
cborFindResult = CborNoError;
}
// end pstat.dos map
cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_ISOP_NAME, &pstatMap);
if (CborNoError == cborFindResult && cbor_value_is_boolean(&pstatMap))
{
......@@ -368,6 +522,7 @@ static OCStackResult CBORPayloadToPstatBin(const uint8_t *cborPayload, const siz
}
*secPstat = pstat;
ret = OC_STACK_OK;
exit:
......@@ -383,28 +538,6 @@ exit:
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, false);
if (OC_STACK_OK == ret)
{
if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_PSTAT_NAME, cborPayload, size))
{
bRet = true;
}
OICFree(cborPayload);
}
return bRet;
}
static bool ValidateQuery(const char * query)
{
OIC_LOG (DEBUG, TAG, "In ValidateQuery");
......@@ -481,7 +614,7 @@ static OCEntityHandlerResult HandlePstatGetRequest (const OCEntityHandlerRequest
* 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.
* For pstat, it updates only dos, isOp, tm, om, and rowneruuid.
*/
static OCEntityHandlerResult HandlePstatPostRequest(OCEntityHandlerRequest *ehRequest)
{
......@@ -540,7 +673,8 @@ static OCEntityHandlerResult HandlePstatPostRequest(OCEntityHandlerRequest *ehRe
}
validReq = false;
//Currently, IoTivity only supports Single Service Client Directed provisioning
// Currently, IoTivity only supports Single Service Client Directed provisioning
// TODO [IOT-1763]: update this state management logic as part of CR 32.
if (pstat->om == SINGLE_SERVICE_CLIENT_DRIVEN)
{
if ((pstat->cm & RESET) && false == pstat->isOp)
......@@ -591,10 +725,13 @@ static OCEntityHandlerResult HandlePstatPostRequest(OCEntityHandlerRequest *ehRe
goto exit;
}
// TODO [IOT-1763]: use SetState() function on dos as part of CR 32.
gPstat->dos.state = pstat->dos.state;
gPstat->dos.pending = pstat->dos.pending;
gPstat->isOp = pstat->isOp;
gPstat->om = pstat->om;
gPstat->tm = pstat->tm;
gPstat->cm = pstat->cm;
gPstat->cm = pstat->cm; // TODO [IOT-1900]: remove once tm change is done in prov tool etc.
memcpy(&(gPstat->rownerID), &(pstat->rownerID), sizeof(OicUuid_t));
// Convert pstat data into CBOR for update to persistent storage
......@@ -717,16 +854,6 @@ static OCEntityHandlerResult HandlePstatPostRequest(OCEntityHandlerRequest *ehRe
return ret;
}
/**
* Get the default value.
*
* @return the gDefaultPstat pointer.
*/
static OicSecPstat_t* GetPstatDefault()
{
return &gDefaultPstat;
}
OCStackResult InitPstatResource()
{
OCStackResult ret = OC_STACK_ERROR;
......@@ -787,7 +914,8 @@ void RestorePstatToInitState()
if(gPstat)
{
OIC_LOG(INFO, TAG, "PSTAT resource will revert back to initial status.");
gPstat->dos.state = DOS_RFOTM;
gPstat->dos.pending = false;
gPstat->cm = (OicSecDpm_t)(gPstat->cm | TAKE_OWNER);
gPstat->tm = (OicSecDpm_t)(gPstat->tm & (~TAKE_OWNER));
gPstat->om = SINGLE_SERVICE_CLIENT_DRIVEN;
......
......@@ -151,6 +151,9 @@ const char * OIC_JSON_EOWNERID_NAME = "x.org.iotivity.eowneruuid";
const char * OIC_JSON_ENCODING_NAME = "encoding";
const char * OIC_JSON_DATA_NAME = "data";
const char * OIC_JSON_SEC_V_NAME = "secv";
const char * OIC_JSON_DOS_NAME = "dos";
const char * OIC_JSON_S_NAME = "s";
const char * OIC_JSON_P_NAME = "p";
const char * OIC_JSON_EMPTY_STRING = "";
......
......@@ -739,10 +739,14 @@ OicSecPstat_t* JSONToPstatBin(const char * jsonStr)
return NULL;
}
OIC_LOG(INFO, TAG, "Using pstat with mandatory .dos object.");
OCStackResult ret = OC_STACK_ERROR;
OicSecPstat_t *pstat = NULL;
cJSON *jsonPstat = NULL;
cJSON *jsonObj = NULL;
cJSON *jsonPstat = NULL;
cJSON *jsonDos = NULL;
cJSON *jsonDosObj = NULL;
cJSON *jsonRoot = cJSON_Parse(jsonStr);
VERIFY_NOT_NULL(TAG, jsonRoot, INFO);
......@@ -752,6 +756,35 @@ OicSecPstat_t* JSONToPstatBin(const char * jsonStr)
pstat = (OicSecPstat_t*)OICCalloc(1, sizeof(OicSecPstat_t));
VERIFY_NOT_NULL(TAG, pstat, INFO);
jsonDos = cJSON_GetObjectItem(jsonPstat, OIC_JSON_DOS_NAME);
if (jsonDos) // do not abort if no .dos found, but print warning