RAML v1.1 sync-up in SVR DB
[platform/upstream/iotivity.git] / resource / csdk / security / src / pstatresource.c
1 //******************************************************************
2 //
3 // Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 #include <stdlib.h>
22 #include <string.h>
23
24 #include "ocstack.h"
25 #include "oic_malloc.h"
26 #include "ocpayload.h"
27 #include "payload_logging.h"
28 #include "resourcemanager.h"
29 #include "pstatresource.h"
30 #include "doxmresource.h"
31 #include "psinterface.h"
32 #include "srmresourcestrings.h"
33 #include "srmutility.h"
34
35 #define TAG  "SRM-PSTAT"
36
37 /** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
38  * The value of payload size is increased until reaching below max cbor size. */
39 static const uint16_t CBOR_SIZE = 512;
40
41 // Max cbor size payload.
42 static const uint16_t CBOR_MAX_SIZE = 4400;
43
44 // PSTAT Map size - Number of mandatory items
45 static const uint8_t PSTAT_MAP_SIZE = 7;
46
47 static OicSecDpom_t gSm = SINGLE_SERVICE_CLIENT_DRIVEN;
48 static OicSecPstat_t gDefaultPstat =
49 {
50     false,                                    // bool isOwned
51     (OicSecDpm_t)(BOOTSTRAP_SERVICE | SECURITY_MANAGEMENT_SERVICES |
52     PROVISION_CREDENTIALS | PROVISION_ACLS),   // OicSecDpm_t cm
53     (OicSecDpm_t)(TAKE_OWNER | BOOTSTRAP_SERVICE | SECURITY_MANAGEMENT_SERVICES |
54     PROVISION_CREDENTIALS | PROVISION_ACLS),   // OicSecDpm_t tm
55     {.id = {0}},                              // OicUuid_t deviceID
56     SINGLE_SERVICE_CLIENT_DRIVEN,             // OicSecDpom_t om */
57     1,                                        // the number of elts in Sms
58     &gSm,                                     // OicSecDpom_t *sm
59     0,                                        // uint16_t commitHash
60     {.id = {0}},                              // OicUuid_t rownerID
61 };
62
63 static OicSecPstat_t    *gPstat = NULL;
64
65 static OCResourceHandle gPstatHandle = NULL;
66
67 void DeletePstatBinData(OicSecPstat_t* pstat)
68 {
69     if (pstat)
70     {
71         //Clean 'supported modes' field
72         OICFree(pstat->sm);
73
74         //Clean pstat itself
75         OICFree(pstat);
76     }
77 }
78
79 OCStackResult PstatToCBORPayload(const OicSecPstat_t *pstat, uint8_t **payload, size_t *size)
80 {
81     if (NULL == pstat || NULL == payload || NULL != *payload || NULL == size)
82     {
83         return OC_STACK_INVALID_PARAM;
84     }
85
86     size_t cborLen = *size;
87     if (0 == cborLen)
88     {
89         cborLen = CBOR_SIZE;
90     }
91
92     *payload = NULL;
93     *size = 0;
94
95     OCStackResult ret = OC_STACK_ERROR;
96
97     CborEncoder encoder = { {.ptr = NULL }, .end = 0 };
98     CborEncoder pstatMap = { {.ptr = NULL }, .end = 0 };
99     char* strUuid = NULL;
100
101     int64_t cborEncoderResult = CborNoError;
102
103     uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
104     VERIFY_NON_NULL(TAG, outPayload, ERROR);
105     cbor_encoder_init(&encoder, outPayload, cborLen, 0);
106
107     cborEncoderResult = cbor_encoder_create_map(&encoder, &pstatMap, PSTAT_MAP_SIZE);
108     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Pstat Map.");
109
110     cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_ISOP_NAME,
111         strlen(OIC_JSON_ISOP_NAME));
112     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ISOP Name Tag.");
113     cborEncoderResult = cbor_encode_boolean(&pstatMap, pstat->isOp);
114     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ISOP Name Value.");
115
116     cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_DEVICE_ID_NAME,
117         strlen(OIC_JSON_DEVICE_ID_NAME));
118     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Id Tag.");
119     ret = ConvertUuidToStr(&pstat->deviceID, &strUuid);
120     VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
121     cborEncoderResult = cbor_encode_text_string(&pstatMap, strUuid, strlen(strUuid));
122     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Id Value.");
123     OICFree(strUuid);
124     strUuid = NULL;
125
126     cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_CM_NAME,
127         strlen(OIC_JSON_CM_NAME));
128     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding CM Name Tag.");
129     cborEncoderResult = cbor_encode_int(&pstatMap, pstat->cm);
130     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding CM Name Value.");
131
132     cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_TM_NAME,
133         strlen(OIC_JSON_TM_NAME));
134     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding TM Name Tag.");
135     cborEncoderResult = cbor_encode_int(&pstatMap, pstat->tm);
136     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding TM Name Value.");
137
138     cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_OM_NAME,
139         strlen(OIC_JSON_OM_NAME));
140     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding OM Name Tag.");
141     cborEncoderResult = cbor_encode_int(&pstatMap, pstat->om);
142     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding OM Name Value.");
143
144     cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_SM_NAME,
145         strlen(OIC_JSON_SM_NAME));
146     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SM Name Tag.");
147     {
148         CborEncoder sm = {{.ptr = NULL }, .end = 0 };
149         cborEncoderResult = cbor_encoder_create_array(&pstatMap, &sm, pstat->smLen);
150         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SM Array.");
151
152         for (size_t i = 0; i < pstat->smLen; i++)
153         {
154             cborEncoderResult = cbor_encode_int(&sm, pstat->sm[i]);
155             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SM Value in Array.");
156         }
157         cborEncoderResult = cbor_encoder_close_container(&pstatMap, &sm);
158         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing SM Array.");
159     }
160
161     cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_ROWNERID_NAME,
162         strlen(OIC_JSON_ROWNERID_NAME));
163     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ROwner Id Tag.");
164     ret = ConvertUuidToStr(&pstat->rownerID, &strUuid);
165     VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
166     cborEncoderResult = cbor_encode_text_string(&pstatMap, strUuid, strlen(strUuid));
167     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ROwner Id Value.");
168     OICFree(strUuid);
169     strUuid = NULL;
170
171     cborEncoderResult = cbor_encoder_close_container(&encoder, &pstatMap);
172     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Closing PSTAT Map.");
173
174     if (CborNoError == cborEncoderResult)
175     {
176         *size = encoder.ptr - outPayload;
177         *payload = outPayload;
178         ret = OC_STACK_OK;
179     }
180 exit:
181     if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
182     {
183         // reallocate and try again!
184         OICFree(outPayload);
185         // Since the allocated initial memory failed, double the memory.
186         cborLen += encoder.ptr - encoder.end;
187         cborEncoderResult = CborNoError;
188         ret = PstatToCBORPayload(pstat, payload, &cborLen);
189         if (OC_STACK_OK == ret)
190         {
191             *size = cborLen;
192         }
193     }
194
195     if ((CborNoError != cborEncoderResult) || (OC_STACK_OK != ret))
196     {
197         OICFree(outPayload);
198         outPayload = NULL;
199         *payload = NULL;
200         *size = 0;
201         ret = OC_STACK_ERROR;
202     }
203
204     return ret;
205 }
206
207 OCStackResult CBORPayloadToPstat(const uint8_t *cborPayload, const size_t size,
208                                  OicSecPstat_t **secPstat)
209 {
210     if (NULL == cborPayload || NULL == secPstat || NULL != *secPstat)
211     {
212         return OC_STACK_INVALID_PARAM;
213     }
214
215     OCStackResult ret = OC_STACK_ERROR;
216     *secPstat = NULL;
217
218     CborValue pstatCbor;
219     CborParser parser;
220     CborError cborFindResult = CborNoError;
221     char *strUuid = NULL;
222     int cborLen = size;
223     size_t len = 0;
224     if (0 == size)
225     {
226         cborLen = CBOR_SIZE;
227     }
228     cbor_parser_init(cborPayload, cborLen, 0, &parser, &pstatCbor);
229     CborValue pstatMap = { .parser = NULL };
230
231     OicSecPstat_t *pstat = NULL;
232     cborFindResult = cbor_value_enter_container(&pstatCbor, &pstatMap);
233     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PSTAT Map.");
234
235     pstat = (OicSecPstat_t *)OICCalloc(1, sizeof(OicSecPstat_t));
236     VERIFY_NON_NULL(TAG, pstat, ERROR);
237
238     cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_ISOP_NAME, &pstatMap);
239     if (CborNoError == cborFindResult && cbor_value_is_boolean(&pstatMap))
240     {
241         cborFindResult = cbor_value_get_boolean(&pstatMap, &pstat->isOp);
242         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding isOp Value.");
243     }
244
245     cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_DEVICE_ID_NAME, &pstatMap);
246     if (CborNoError == cborFindResult && cbor_value_is_text_string(&pstatMap))
247     {
248         cborFindResult = cbor_value_dup_text_string(&pstatMap, &strUuid , &len, NULL);
249         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Device Id Value.");
250         ret = ConvertStrToUuid(strUuid , &pstat->deviceID);
251         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
252         OICFree(strUuid );
253         strUuid  = NULL;
254     }
255
256     cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_CM_NAME, &pstatMap);
257     if (CborNoError == cborFindResult && cbor_value_is_integer(&pstatMap))
258     {
259         cborFindResult = cbor_value_get_int(&pstatMap, (int *) &pstat->cm);
260         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding CM.");
261     }
262
263     cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_TM_NAME, &pstatMap);
264     if (CborNoError == cborFindResult && cbor_value_is_integer(&pstatMap))
265     {
266         cborFindResult = cbor_value_get_int(&pstatMap, (int *) &pstat->tm);
267         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding TM.");
268     }
269
270     cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_OM_NAME, &pstatMap);
271     if (CborNoError == cborFindResult && cbor_value_is_integer(&pstatMap))
272     {
273         cborFindResult = cbor_value_get_int(&pstatMap, (int *) &pstat->om);
274         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding OM.");
275     }
276
277     cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_SM_NAME, &pstatMap);
278     if (CborNoError == cborFindResult && cbor_value_is_array(&pstatMap))
279     {
280         CborValue sm = { .parser = NULL };
281         cborFindResult = cbor_value_get_array_length(&pstatMap, &pstat->smLen);
282         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Array Len.");
283
284         pstat->sm = (OicSecDpom_t *)OICCalloc(pstat->smLen, sizeof(OicSecDpom_t));
285         VERIFY_NON_NULL(TAG, pstat->sm, ERROR);
286
287         cborFindResult = cbor_value_enter_container(&pstatMap, &sm);
288         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering SM.");
289
290         int i = 0;
291         while (cbor_value_is_valid(&sm))
292         {
293             cborFindResult = cbor_value_get_int(&sm, (int *)&pstat->sm[i++]);
294             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding SM.");
295             cborFindResult = cbor_value_advance(&sm);
296             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Closing SM.");
297         }
298     }
299
300     cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_ROWNERID_NAME, &pstatMap);
301     if (CborNoError == cborFindResult && cbor_value_is_text_string(&pstatMap))
302     {
303         cborFindResult = cbor_value_dup_text_string(&pstatMap, &strUuid , &len, NULL);
304         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding ROwner Id Value.");
305         ret = ConvertStrToUuid(strUuid , &pstat->rownerID);
306         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
307         OICFree(strUuid );
308         strUuid  = NULL;
309     }
310
311     *secPstat = pstat;
312     ret = OC_STACK_OK;
313
314 exit:
315     if (CborNoError != cborFindResult)
316     {
317         OIC_LOG(ERROR, TAG, "CBORPayloadToPstat failed");
318         DeletePstatBinData(pstat);
319         pstat = NULL;
320         *secPstat = NULL;
321         ret = OC_STACK_ERROR;
322     }
323
324     return ret;
325 }
326
327 /**
328  * Function to update persistent storage
329  */
330 static bool UpdatePersistentStorage(OicSecPstat_t *pstat)
331 {
332     bool bRet = false;
333
334     size_t size = 0;
335     uint8_t *cborPayload = NULL;
336     OCStackResult ret = PstatToCBORPayload(pstat, &cborPayload, &size);
337     if (OC_STACK_OK == ret)
338     {
339         if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_PSTAT_NAME, cborPayload, size))
340         {
341             bRet = true;
342         }
343         OICFree(cborPayload);
344     }
345
346     return bRet;
347 }
348
349
350 /**
351  * The entity handler determines how to process a GET request.
352  */
353 static OCEntityHandlerResult HandlePstatGetRequest (const OCEntityHandlerRequest * ehRequest)
354 {
355     OIC_LOG(INFO, TAG, "HandlePstatGetRequest  processing GET request");
356
357     // Convert ACL data into CBOR for transmission
358     size_t size = 0;
359     uint8_t *payload = NULL;
360     OCStackResult res = PstatToCBORPayload(gPstat, &payload, &size);
361
362     // A device should always have a default pstat. Therefore, payload should never be NULL.
363     OCEntityHandlerResult ehRet = (res == OC_STACK_OK) ? OC_EH_OK : OC_EH_ERROR;
364
365     // Send response payload to request originator
366     SendSRMCBORResponse(ehRequest, ehRet, payload, size);
367     OICFree(payload);
368     return ehRet;
369 }
370
371 /**
372  * The entity handler determines how to process a POST request.
373  * Per the REST paradigm, POST can also be used to update representation of existing
374  * resource or create a new resource.
375  * For pstat, it updates only tm and om.
376  */
377 static OCEntityHandlerResult HandlePstatPutRequest(const OCEntityHandlerRequest *ehRequest)
378 {
379     OCEntityHandlerResult ehRet = OC_EH_ERROR;
380     OIC_LOG(INFO, TAG, "HandlePstatPutRequest  processing PUT request");
381     OicSecPstat_t *pstat = NULL;
382
383     if (ehRequest->resource)
384     {
385         uint8_t *payload = ((OCSecurityPayload *) ehRequest->payload)->securityData1;
386         size_t size = ((OCSecurityPayload *) ehRequest->payload)->payloadSize;
387         VERIFY_NON_NULL(TAG, payload, ERROR);
388
389         OCStackResult ret = CBORPayloadToPstat(payload, size, &pstat);
390         OICFree(payload);
391         VERIFY_NON_NULL(TAG, pstat, ERROR);
392         if (OC_STACK_OK == ret)
393         {
394             if (false == (pstat->cm & TAKE_OWNER))
395             {
396                 gPstat->isOp = true;
397                 gPstat->cm = pstat->cm;
398                 OIC_LOG (INFO, TAG, "Taken owner succeed and isOp is TRUE");
399             }
400             else
401             {
402                 OIC_LOG(DEBUG, TAG, "Taken owner failed");
403             }
404             if (pstat->om != MULTIPLE_SERVICE_SERVER_DRIVEN && gPstat)
405             {
406                 /*
407                  * Check if the operation mode is in the supported provisioning services
408                  * operation mode list.
409                  */
410                 for (size_t i=0; i< gPstat->smLen; i++)
411                 {
412                     if(gPstat->sm[i] == pstat->om)
413                     {
414                         gPstat->om = pstat->om;
415                         break;
416                     }
417                 }
418             }
419             // Convert pstat data into CBOR for update to persistent storage
420             if (UpdatePersistentStorage(gPstat))
421             {
422                 ehRet = OC_EH_OK;
423             }
424         }
425     }
426  exit:
427     if(OC_EH_OK != ehRet)
428     {
429         /*
430           * If some error is occured while ownership transfer,
431           * ownership transfer related resource should be revert back to initial status.
432           */
433         RestoreDoxmToInitState();
434         RestorePstatToInitState();
435     }
436
437     //Send payload to request originator
438     if(OC_STACK_OK != SendSRMCBORResponse(ehRequest, ehRet, NULL, 0))
439     {
440         OIC_LOG (ERROR, TAG, "SendSRMResponse failed in HandlePstatPostRequest");
441     }
442     DeletePstatBinData(pstat);
443     return ehRet;
444 }
445
446 /**
447  * This internal method is the entity handler for pstat resources.
448  */
449  OCEntityHandlerResult PstatEntityHandler(OCEntityHandlerFlag flag,
450                                           OCEntityHandlerRequest * ehRequest,
451                                           void *callbackParam)
452 {
453     (void)callbackParam;
454     OCEntityHandlerResult ehRet = OC_EH_ERROR;
455     // This method will handle REST request (GET/POST) for /oic/sec/pstat
456     if (flag & OC_REQUEST_FLAG)
457     {
458         OIC_LOG(INFO, TAG, "Flag includes OC_REQUEST_FLAG");
459         switch (ehRequest->method)
460         {
461             case OC_REST_GET:
462                 ehRet = HandlePstatGetRequest(ehRequest);
463                 break;
464             case OC_REST_PUT:
465                 ehRet = HandlePstatPutRequest(ehRequest);
466                 break;
467             default:
468                 ehRet = OC_EH_ERROR;
469                 SendSRMCBORResponse(ehRequest, ehRet, NULL, 0);
470                 break;
471         }
472     }
473     return ehRet;
474 }
475
476 /**
477  * This internal method is used to create '/oic/sec/pstat' resource.
478  */
479  OCStackResult CreatePstatResource()
480 {
481     OCStackResult ret = OCCreateResource(&gPstatHandle,
482                                          OIC_RSRC_TYPE_SEC_PSTAT,
483                                          OIC_MI_DEF,
484                                          OIC_RSRC_PSTAT_URI,
485                                          PstatEntityHandler,
486                                          NULL,
487                                          OC_RES_PROP_NONE);
488
489     if (OC_STACK_OK != ret)
490     {
491         OIC_LOG(FATAL, TAG, "Unable to instantiate pstat resource");
492         DeInitPstatResource();
493     }
494     return ret;
495 }
496
497 /**
498  * Get the default value.
499  *
500  * @return the gDefaultPstat pointer.
501  */
502 static OicSecPstat_t* GetPstatDefault()
503 {
504     return &gDefaultPstat;
505 }
506
507 OCStackResult InitPstatResource()
508 {
509     OCStackResult ret = OC_STACK_ERROR;
510
511     // Read Pstat resource from PS
512     uint8_t *data = NULL;
513     size_t size = 0;
514     ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_PSTAT_NAME, &data, &size);
515     // If database read failed
516     if (OC_STACK_OK != ret)
517     {
518         OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
519     }
520     if (data)
521     {
522         // Read ACL resource from PS
523         ret = CBORPayloadToPstat(data, size, &gPstat);
524         OICFree(data);
525     }
526     /*
527      * If SVR database in persistent storage got corrupted or
528      * is not available for some reason, a default pstat is created
529      * which allows user to initiate pstat provisioning again.
530      */
531     if ((OC_STACK_OK != ret) || !gPstat)
532     {
533         gPstat = GetPstatDefault();
534     }
535     VERIFY_NON_NULL(TAG, gPstat, FATAL);
536
537     // Instantiate 'oic.sec.pstat'
538     ret = CreatePstatResource();
539
540 exit:
541     if (OC_STACK_OK != ret)
542     {
543         DeInitPstatResource();
544     }
545     return ret;
546 }
547
548 OCStackResult DeInitPstatResource()
549 {
550     if (gPstat != &gDefaultPstat)
551     {
552         DeletePstatBinData(gPstat);
553         gPstat = NULL;
554     }
555     return OCDeleteResource(gPstatHandle);
556 }
557
558 /**
559  * Function to restore pstat resurce to initial status.
560  * This function will use in case of error while ownership transfer
561  */
562 void RestorePstatToInitState()
563 {
564     if(gPstat)
565     {
566         OIC_LOG(INFO, TAG, "PSTAT resource will revert back to initial status.");
567
568         gPstat->cm = (OicSecDpm_t)(gPstat->cm | TAKE_OWNER);
569         gPstat->tm = (OicSecDpm_t)(gPstat->tm & (~TAKE_OWNER));
570         gPstat->om = SINGLE_SERVICE_CLIENT_DRIVEN;
571         if(gPstat->sm && 0 < gPstat->smLen)
572         {
573             gPstat->sm[0] = SINGLE_SERVICE_CLIENT_DRIVEN;
574         }
575
576         if (!UpdatePersistentStorage(gPstat))
577         {
578             OIC_LOG(ERROR, TAG, "Failed to revert PSTAT in persistent storage");
579         }
580     }
581 }