Enabled Period & Recurrence in ACL resource.
[platform/upstream/iotivity.git] / resource / csdk / security / src / aclresource.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 #include "ocstack.h"
24 #include "logger.h"
25 #include "oic_malloc.h"
26 #include "oic_string.h"
27 #include "cJSON.h"
28 #include "base64.h"
29 #include "resourcemanager.h"
30 #include "aclresource.h"
31 #include "psinterface.h"
32 #include "utlist.h"
33 #include "srmresourcestrings.h"
34 #include "doxmresource.h"
35 #include "srmutility.h"
36 #include <stdlib.h>
37 #include <string.h>
38
39 #define TAG  PCF("SRM-ACL")
40
41 OicSecAcl_t        *gAcl = NULL;
42 static OCResourceHandle    gAclHandle = NULL;
43
44 void DeleteACLList(OicSecAcl_t* acl)
45 {
46     if (acl)
47     {
48         OicSecAcl_t *aclTmp1 = NULL, *aclTmp2 = NULL;
49         LL_FOREACH_SAFE(acl, aclTmp1, aclTmp2)
50         {
51             int i = 0;
52
53             LL_DELETE(acl, aclTmp1);
54
55             // Clean Resources
56             for (i = 0; i < aclTmp1->resourcesLen; i++)
57             {
58                 OICFree(aclTmp1->resources[i]);
59             }
60             OICFree(aclTmp1->resources);
61
62             //Clean Period & Recurrence
63             for(i = 0; i < aclTmp1->prdRecrLen; i++)
64             {
65                 OICFree(aclTmp1->periods[i]);
66                 OICFree(aclTmp1->recurrences[i]);
67             }
68             OICFree(aclTmp1->periods);
69             OICFree(aclTmp1->recurrences);
70
71             // Clean Owners
72             OICFree(aclTmp1->owners);
73
74             // Clean ACL node itself
75             OICFree(aclTmp1);
76         }
77     }
78 }
79
80 /*
81  * This internal method converts ACL data into JSON format.
82  *
83  * Note: Caller needs to invoke 'free' when finished done using
84  * return string.
85  */
86 char * BinToAclJSON(const OicSecAcl_t * acl)
87 {
88     cJSON *jsonRoot = NULL;
89     char *jsonStr = NULL;
90
91     if (acl)
92     {
93         jsonRoot = cJSON_CreateObject();
94         VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
95
96         cJSON *jsonAclArray = NULL;
97         cJSON_AddItemToObject (jsonRoot, OIC_JSON_ACL_NAME, jsonAclArray = cJSON_CreateArray());
98         VERIFY_NON_NULL(TAG, jsonAclArray, ERROR);
99
100         while(acl)
101         {
102             char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {};
103             uint32_t outLen = 0;
104             size_t inLen = 0;
105             B64Result b64Ret = B64_OK;
106
107             cJSON *jsonAcl = cJSON_CreateObject();
108
109             // Subject -- Mandatory
110             outLen = 0;
111             if (memcmp(&(acl->subject), &WILDCARD_SUBJECT_ID, sizeof(OicUuid_t)) == 0)
112             {
113                 inLen = WILDCARD_SUBJECT_ID_LEN;
114             }
115             else
116             {
117                 inLen =  sizeof(OicUuid_t);
118             }
119             b64Ret = b64Encode(acl->subject.id, inLen, base64Buff,
120                 sizeof(base64Buff), &outLen);
121             VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
122             cJSON_AddStringToObject(jsonAcl, OIC_JSON_SUBJECT_NAME, base64Buff );
123
124             // Resources -- Mandatory
125             cJSON *jsonRsrcArray = NULL;
126             cJSON_AddItemToObject (jsonAcl, OIC_JSON_RESOURCES_NAME, jsonRsrcArray = cJSON_CreateArray());
127             VERIFY_NON_NULL(TAG, jsonRsrcArray, ERROR);
128             for (int i = 0; i < acl->resourcesLen; i++)
129             {
130                 cJSON_AddItemToArray (jsonRsrcArray, cJSON_CreateString(acl->resources[i]));
131             }
132
133             // Permissions -- Mandatory
134             cJSON_AddNumberToObject (jsonAcl, OIC_JSON_PERMISSION_NAME, acl->permission);
135
136             //Period & Recurrence -- Not Mandatory
137             if(0 != acl->prdRecrLen)
138             {
139                 cJSON *jsonPeriodArray = NULL;
140                 cJSON_AddItemToObject (jsonAcl, OIC_JSON_PERIODS_NAME,
141                         jsonPeriodArray = cJSON_CreateArray());
142                 VERIFY_NON_NULL(TAG, jsonPeriodArray, ERROR);
143                 for (size_t i = 0; i < acl->prdRecrLen; i++)
144                 {
145                     cJSON_AddItemToArray (jsonPeriodArray,
146                             cJSON_CreateString(acl->periods[i]));
147                 }
148             }
149
150             //Recurrence -- Not Mandatory
151             if(0 != acl->prdRecrLen && acl->recurrences)
152             {
153                 cJSON *jsonRecurArray  = NULL;
154                 cJSON_AddItemToObject (jsonAcl, OIC_JSON_RECURRENCES_NAME,
155                         jsonRecurArray = cJSON_CreateArray());
156                 VERIFY_NON_NULL(TAG, jsonRecurArray, ERROR);
157                 for (size_t i = 0; i < acl->prdRecrLen; i++)
158                 {
159                     cJSON_AddItemToArray (jsonRecurArray,
160                             cJSON_CreateString(acl->recurrences[i]));
161                 }
162             }
163
164             // Owners -- Mandatory
165             cJSON *jsonOwnrArray = NULL;
166             cJSON_AddItemToObject (jsonAcl, OIC_JSON_OWNERS_NAME, jsonOwnrArray = cJSON_CreateArray());
167             VERIFY_NON_NULL(TAG, jsonOwnrArray, ERROR);
168             for (int i = 0; i < acl->ownersLen; i++)
169             {
170                 outLen = 0;
171
172                 b64Ret = b64Encode(acl->owners[i].id, sizeof(((OicUuid_t*)0)->id), base64Buff,
173                     sizeof(base64Buff), &outLen);
174                 VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
175
176                 cJSON_AddItemToArray (jsonOwnrArray, cJSON_CreateString(base64Buff));
177             }
178
179             // Attach current acl node to Acl Array
180             cJSON_AddItemToArray(jsonAclArray, jsonAcl);
181             acl = acl->next;
182         }
183
184         jsonStr = cJSON_PrintUnformatted(jsonRoot);
185     }
186
187 exit:
188     if (jsonRoot)
189     {
190         cJSON_Delete(jsonRoot);
191     }
192     return jsonStr;
193 }
194
195 /*
196  * This internal method converts JSON ACL into binary ACL.
197  */
198 OicSecAcl_t * JSONToAclBin(const char * jsonStr)
199 {
200     OCStackResult ret = OC_STACK_ERROR;
201     OicSecAcl_t * headAcl = NULL;
202     OicSecAcl_t * prevAcl = NULL;
203     cJSON *jsonRoot = NULL;
204     cJSON *jsonAclArray = NULL;
205
206     VERIFY_NON_NULL(TAG, jsonStr, ERROR);
207
208     jsonRoot = cJSON_Parse(jsonStr);
209     VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
210
211     jsonAclArray = cJSON_GetObjectItem(jsonRoot, OIC_JSON_ACL_NAME);
212     VERIFY_NON_NULL(TAG, jsonAclArray, ERROR);
213
214     if (cJSON_Array == jsonAclArray->type)
215     {
216         int numAcl = cJSON_GetArraySize(jsonAclArray);
217         int idx = 0;
218
219         VERIFY_SUCCESS(TAG, numAcl > 0, INFO);
220         do
221         {
222             cJSON *jsonAcl = cJSON_GetArrayItem(jsonAclArray, idx);
223             VERIFY_NON_NULL(TAG, jsonAcl, ERROR);
224
225             OicSecAcl_t *acl = (OicSecAcl_t*)OICCalloc(1, sizeof(OicSecAcl_t));
226             VERIFY_NON_NULL(TAG, acl, ERROR);
227
228             headAcl = (headAcl) ? headAcl : acl;
229             if (prevAcl)
230             {
231                 prevAcl->next = acl;
232             }
233
234             size_t jsonObjLen = 0;
235             cJSON *jsonObj = NULL;
236
237             unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
238             uint32_t outLen = 0;
239             B64Result b64Ret = B64_OK;
240
241             // Subject -- Mandatory
242             jsonObj = cJSON_GetObjectItem(jsonAcl, OIC_JSON_SUBJECT_NAME);
243             VERIFY_NON_NULL(TAG, jsonObj, ERROR);
244             VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR);
245             outLen = 0;
246             b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring), base64Buff,
247                         sizeof(base64Buff), &outLen);
248             VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(acl->subject.id)), ERROR);
249             memcpy(acl->subject.id, base64Buff, outLen);
250
251             // Resources -- Mandatory
252             jsonObj = cJSON_GetObjectItem(jsonAcl, OIC_JSON_RESOURCES_NAME);
253             VERIFY_NON_NULL(TAG, jsonObj, ERROR);
254             VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR);
255
256             acl->resourcesLen = cJSON_GetArraySize(jsonObj);
257             VERIFY_SUCCESS(TAG, acl->resourcesLen > 0, ERROR);
258             acl->resources = (char**)OICCalloc(acl->resourcesLen, sizeof(char*));
259             VERIFY_NON_NULL(TAG, (acl->resources), ERROR);
260
261             int idxx = 0;
262             do
263             {
264                 cJSON *jsonRsrc = cJSON_GetArrayItem(jsonObj, idxx);
265                 VERIFY_NON_NULL(TAG, jsonRsrc, ERROR);
266
267                 jsonObjLen = strlen(jsonRsrc->valuestring) + 1;
268                 acl->resources[idxx] = (char*)OICMalloc(jsonObjLen);
269                 VERIFY_NON_NULL(TAG, (acl->resources[idxx]), ERROR);
270                 OICStrcpy(acl->resources[idxx], jsonObjLen, jsonRsrc->valuestring);
271             } while ( ++idxx < acl->resourcesLen);
272
273             // Permissions -- Mandatory
274             jsonObj = cJSON_GetObjectItem(jsonAcl,
275                                 OIC_JSON_PERMISSION_NAME);
276             VERIFY_NON_NULL(TAG, jsonObj, ERROR);
277             VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
278             acl->permission = jsonObj->valueint;
279
280             //Period -- Not Mandatory
281             cJSON *jsonPeriodObj = cJSON_GetObjectItem(jsonAcl,
282                     OIC_JSON_PERIODS_NAME);
283             if(jsonPeriodObj)
284             {
285                 VERIFY_SUCCESS(TAG, cJSON_Array == jsonPeriodObj->type,
286                                ERROR);
287                 acl->prdRecrLen = cJSON_GetArraySize(jsonPeriodObj);
288                 if(acl->prdRecrLen > 0)
289                 {
290                     acl->periods = (char**)OICCalloc(acl->prdRecrLen,
291                                     sizeof(char*));
292                     VERIFY_NON_NULL(TAG, acl->periods, ERROR);
293
294                     cJSON *jsonPeriod = NULL;
295                     for(size_t i = 0; i < acl->prdRecrLen; i++)
296                     {
297                         jsonPeriod = cJSON_GetArrayItem(jsonPeriodObj, i);
298                         VERIFY_NON_NULL(TAG, jsonPeriod, ERROR);
299
300                         jsonObjLen = strlen(jsonPeriod->valuestring) + 1;
301                         acl->periods[i] = (char*)OICMalloc(jsonObjLen);
302                         VERIFY_NON_NULL(TAG, acl->periods[i], ERROR);
303                         OICStrcpy(acl->periods[i], jsonObjLen,
304                                   jsonPeriod->valuestring);
305                     }
306                 }
307             }
308
309             //Recurrence -- Not mandatory
310             cJSON *jsonRecurObj = cJSON_GetObjectItem(jsonAcl,
311                                         OIC_JSON_RECURRENCES_NAME);
312             if(jsonRecurObj)
313             {
314                 VERIFY_SUCCESS(TAG, cJSON_Array == jsonRecurObj->type,
315                                ERROR);
316                 if(acl->prdRecrLen > 0)
317                 {
318                     acl->recurrences = (char**)OICCalloc(acl->prdRecrLen,
319                                              sizeof(char*));
320                     VERIFY_NON_NULL(TAG, acl->recurrences, ERROR);
321
322                     cJSON *jsonRecur = NULL;
323                     for(size_t i = 0; i < acl->prdRecrLen; i++)
324                     {
325                         jsonRecur = cJSON_GetArrayItem(jsonRecurObj, i);
326                         jsonObjLen = strlen(jsonRecur->valuestring) + 1;
327                         acl->recurrences[i] = (char*)OICMalloc(jsonObjLen);
328                         VERIFY_NON_NULL(TAG, acl->recurrences[i], ERROR);
329                         OICStrcpy(acl->recurrences[i], jsonObjLen,
330                                   jsonRecur->valuestring);
331                     }
332                 }
333             }
334
335             // Owners -- Mandatory
336             jsonObj = cJSON_GetObjectItem(jsonAcl, OIC_JSON_OWNERS_NAME);
337             VERIFY_NON_NULL(TAG, jsonObj, ERROR);
338             VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR);
339
340             acl->ownersLen = cJSON_GetArraySize(jsonObj);
341             VERIFY_SUCCESS(TAG, acl->ownersLen > 0, ERROR);
342             acl->owners = (OicUuid_t*)OICCalloc(acl->ownersLen, sizeof(OicUuid_t));
343             VERIFY_NON_NULL(TAG, (acl->owners), ERROR);
344
345             idxx = 0;
346             do
347             {
348                 cJSON *jsonOwnr = cJSON_GetArrayItem(jsonObj, idxx);
349                 VERIFY_NON_NULL(TAG, jsonOwnr, ERROR);
350                 VERIFY_SUCCESS(TAG, cJSON_String == jsonOwnr->type, ERROR);
351
352                 outLen = 0;
353                 b64Ret = b64Decode(jsonOwnr->valuestring, strlen(jsonOwnr->valuestring), base64Buff,
354                             sizeof(base64Buff), &outLen);
355
356                 VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(acl->owners[idxx].id)),
357                                     ERROR);
358                 memcpy(acl->owners[idxx].id, base64Buff, outLen);
359             } while ( ++idxx < acl->ownersLen);
360
361             prevAcl = acl;
362         } while( ++idx < numAcl);
363     }
364
365     ret = OC_STACK_OK;
366
367 exit:
368     cJSON_Delete(jsonRoot);
369     if (OC_STACK_OK != ret)
370     {
371         DeleteACLList(headAcl);
372         headAcl = NULL;
373     }
374     return headAcl;
375 }
376
377 static OCEntityHandlerResult HandleACLGetRequest (const OCEntityHandlerRequest * ehRequest)
378 {
379     // Convert ACL data into JSON for transmission
380     char* jsonStr = BinToAclJSON(gAcl);
381
382     /*
383      * A device should 'always' have a default ACL. Therefore,
384      * jsonStr should never be NULL.
385      */
386     OCEntityHandlerResult ehRet = (jsonStr ? OC_EH_OK : OC_EH_ERROR);
387
388     // Send response payload to request originator
389     SendSRMResponse(ehRequest, ehRet, jsonStr);
390
391     OICFree(jsonStr);
392
393     OC_LOG_V (INFO, TAG, PCF("%s RetVal %d"), __func__ , ehRet);
394     return ehRet;
395 }
396
397 static OCEntityHandlerResult HandleACLPostRequest (const OCEntityHandlerRequest * ehRequest)
398 {
399     OCEntityHandlerResult ehRet = OC_EH_ERROR;
400
401     // Convert JSON ACL data into binary. This will also validate the ACL data received.
402     OicSecAcl_t* newAcl = JSONToAclBin(((OCSecurityPayload*)ehRequest->payload)->securityData);
403
404     if (newAcl)
405     {
406         // Append the new ACL to existing ACL
407         LL_APPEND(gAcl, newAcl);
408
409         // Convert ACL data into JSON for update to persistent storage
410         char *jsonStr = BinToAclJSON(gAcl);
411         if (jsonStr)
412         {
413             cJSON *jsonAcl = cJSON_Parse(jsonStr);
414             OICFree(jsonStr);
415
416             if ((jsonAcl) &&
417                 (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_ACL_NAME, jsonAcl)))
418             {
419                 ehRet = OC_EH_RESOURCE_CREATED;
420             }
421             cJSON_Delete(jsonAcl);
422         }
423     }
424
425     // Send payload to request originator
426     SendSRMResponse(ehRequest, ehRet, NULL);
427
428     OC_LOG_V (INFO, TAG, PCF("%s RetVal %d"), __func__ , ehRet);
429     return ehRet;
430 }
431
432 /*
433  * This internal method is the entity handler for ACL resources and
434  * will handle REST request (GET/PUT/POST/DEL) for them.
435  */
436 OCEntityHandlerResult ACLEntityHandler (OCEntityHandlerFlag flag,
437                                         OCEntityHandlerRequest * ehRequest,
438                                         void* callbackParameter)
439 {
440     OCEntityHandlerResult ehRet = OC_EH_ERROR;
441
442     if (!ehRequest)
443     {
444         return ehRet;
445     }
446
447     if (flag & OC_REQUEST_FLAG)
448     {
449         // TODO :  Handle PUT and DEL methods
450         OC_LOG (INFO, TAG, PCF("Flag includes OC_REQUEST_FLAG"));
451         switch (ehRequest->method)
452         {
453             case OC_REST_GET:
454                 ehRet = HandleACLGetRequest(ehRequest);
455                 break;
456
457             case OC_REST_POST:
458                 ehRet = HandleACLPostRequest(ehRequest);
459                 break;
460
461             default:
462                 ehRet = OC_EH_ERROR;
463                 SendSRMResponse(ehRequest, ehRet, NULL);
464         }
465     }
466
467     return ehRet;
468 }
469
470 /*
471  * This internal method is used to create '/oic/sec/acl' resource.
472  */
473 OCStackResult CreateACLResource()
474 {
475     OCStackResult ret;
476
477     ret = OCCreateResource(&gAclHandle,
478                            OIC_RSRC_TYPE_SEC_ACL,
479                            OIC_MI_DEF,
480                            OIC_RSRC_ACL_URI,
481                            ACLEntityHandler,
482                            NULL,
483                            OC_OBSERVABLE | OC_SECURE | OC_EXPLICIT_DISCOVERABLE);
484
485     if (OC_STACK_OK != ret)
486     {
487         OC_LOG (FATAL, TAG, PCF("Unable to instantiate ACL resource"));
488         DeInitACLResource();
489     }
490     return ret;
491 }
492
493 /*
494  * This internal method is to retrieve the default ACL.
495  * If SVR database in persistent storage got corrupted or
496  * is not available for some reason, a default ACL is created
497  * which allows user to initiate ACL provisioning again.
498  */
499 OCStackResult  GetDefaultACL(OicSecAcl_t** defaultAcl)
500 {
501     OCStackResult ret = OC_STACK_ERROR;
502
503     OicUuid_t ownerId = {};
504
505     /*
506      * TODO In future, when new virtual resources will be added in OIC
507      * specification, Iotivity stack should be able to add them in
508      * existing SVR database. To support this, we need to add 'versioning'
509      * mechanism in SVR database.
510      */
511
512     const char *rsrcs[] = {
513         OC_RSRVD_WELL_KNOWN_URI,
514         OC_RSRVD_DEVICE_URI,
515         OC_RSRVD_PLATFORM_URI,
516         OC_RSRVD_RESOURCE_TYPES_URI,
517 #ifdef WITH_PRESENCE
518         OC_RSRVD_PRESENCE_URI,
519 #endif //WITH_PRESENCE
520         OIC_RSRC_ACL_URI,
521         OIC_RSRC_DOXM_URI,
522         OIC_RSRC_PSTAT_URI,
523     };
524
525     if (!defaultAcl)
526     {
527         return OC_STACK_INVALID_PARAM;
528     }
529
530     OicSecAcl_t *acl = (OicSecAcl_t *)OICCalloc(1, sizeof(OicSecAcl_t));
531     VERIFY_NON_NULL(TAG, acl, ERROR);
532
533     // Subject -- Mandatory
534     memcpy(&(acl->subject), &WILDCARD_SUBJECT_ID, sizeof(acl->subject));
535
536     // Resources -- Mandatory
537     acl->resourcesLen = sizeof(rsrcs)/sizeof(rsrcs[0]);
538
539     acl->resources = (char**)OICCalloc(acl->resourcesLen, sizeof(char*));
540     VERIFY_NON_NULL(TAG, (acl->resources), ERROR);
541
542     for (int i = 0; i <  acl->resourcesLen; i++)
543     {
544         size_t len = strlen(rsrcs[i]) + 1;
545         acl->resources[i] = (char*)OICMalloc(len * sizeof(char));
546         VERIFY_NON_NULL(TAG, (acl->resources[i]), ERROR);
547         OICStrcpy(acl->resources[i], len, rsrcs[i]);
548     }
549
550     acl->permission = PERMISSION_READ;
551     acl->prdRecrLen = 0;
552     acl->periods = NULL;
553     acl->recurrences = NULL;
554
555     // Device ID is the owner of this default ACL
556     ret = GetDoxmDeviceID( &ownerId);
557     VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, FATAL);
558
559     acl->ownersLen = 1;
560     acl->owners = (OicUuid_t*)OICMalloc(sizeof(OicUuid_t));
561     VERIFY_NON_NULL(TAG, (acl->owners), ERROR);
562     memcpy(acl->owners, &ownerId, sizeof(OicUuid_t));
563
564     acl->next = NULL;
565
566     *defaultAcl = acl;
567     ret = OC_STACK_OK;
568
569 exit:
570
571     if (ret != OC_STACK_OK)
572     {
573         DeleteACLList(acl);
574         acl = NULL;
575     }
576
577     return ret;
578 }
579
580 /**
581  * Initialize ACL resource by loading data from persistent storage.
582  *
583  * @retval  OC_STACK_OK for Success, otherwise some error value
584  */
585 OCStackResult InitACLResource()
586 {
587     OCStackResult ret = OC_STACK_ERROR;
588
589     // Read ACL resource from PS
590     char* jsonSVRDatabase = GetSVRDatabase();
591
592     if (jsonSVRDatabase)
593     {
594         // Convert JSON ACL into binary format
595         gAcl = JSONToAclBin(jsonSVRDatabase);
596         OICFree(jsonSVRDatabase);
597     }
598     /*
599      * If SVR database in persistent storage got corrupted or
600      * is not available for some reason, a default ACL is created
601      * which allows user to initiate ACL provisioning again.
602      */
603     if (!jsonSVRDatabase || !gAcl)
604     {
605         GetDefaultACL(&gAcl);
606         // TODO Needs to update persistent storage
607     }
608     VERIFY_NON_NULL(TAG, gAcl, FATAL);
609
610     // Instantiate 'oic.sec.acl'
611     ret = CreateACLResource();
612
613 exit:
614     if (OC_STACK_OK != ret)
615     {
616         DeInitACLResource();
617     }
618     return ret;
619 }
620
621 /**
622  * Perform cleanup for ACL resources.
623  *
624  * @retval  none
625  */
626 void DeInitACLResource()
627 {
628     OCDeleteResource(gAclHandle);
629     gAclHandle = NULL;
630
631     DeleteACLList(gAcl);
632     gAcl = NULL;
633 }
634
635 /**
636  * This method is used by PolicyEngine to retrieve ACL for a Subject.
637  *
638  * @param subjectId ID of the subject for which ACL is required.
639  * @param savePtr is used internally by @ref GetACLResourceData to maintain index between
640  *                successive calls for same subjectId.
641  *
642  * @retval  reference to @ref OicSecAcl_t if ACL is found, else NULL
643  *
644  * @note On the first call to @ref GetACLResourceData, savePtr should point to NULL
645  */
646 const OicSecAcl_t* GetACLResourceData(const OicUuid_t* subjectId, OicSecAcl_t **savePtr)
647 {
648     OicSecAcl_t *acl = NULL;
649     OicSecAcl_t *begin = NULL;
650
651     if ( NULL == subjectId)
652     {
653         return NULL;
654     }
655
656     /*
657      * savePtr MUST point to NULL if this is the 'first' call to retrieve ACL for
658      * subjectID.
659      */
660     if (NULL == *savePtr)
661     {
662         begin = gAcl;
663     }
664     else
665     {
666         /*
667          * If this is a 'successive' call, search for location pointed by
668          * savePtr and assign 'begin' to the next ACL after it in the linked
669          * list and start searching from there.
670          */
671         LL_FOREACH(gAcl, acl)
672         {
673             if (acl == *savePtr)
674             {
675                 begin = acl->next;
676             }
677         }
678     }
679
680     // Find the next ACL corresponding to the 'subjectID' and return it.
681     LL_FOREACH(begin, acl)
682     {
683         if (memcmp(&(acl->subject), subjectId, sizeof(OicUuid_t)) == 0)
684         {
685             *savePtr = acl;
686             return acl;
687         }
688     }
689
690     // Cleanup in case no ACL is found
691     *savePtr = NULL;
692     return NULL;
693 }