Merge branch 'plugin-interface' into master
[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 "ocserverrequest.h"
37 #include <stdlib.h>
38 #ifdef WITH_ARDUINO
39 #include <string.h>
40 #else
41 #include <strings.h>
42 #endif
43
44 #define TAG  "SRM-ACL"
45
46 OicSecAcl_t               *gAcl = NULL;
47 static OCResourceHandle    gAclHandle = NULL;
48
49 /**
50  * This function frees OicSecAcl_t object's fields and object itself.
51  */
52 static void FreeACE(OicSecAcl_t *ace)
53 {
54     size_t i;
55     if(NULL == ace)
56     {
57         OC_LOG (ERROR, TAG, "Invalid Parameter");
58         return;
59     }
60
61     // Clean Resources
62     for (i = 0; i < ace->resourcesLen; i++)
63     {
64         OICFree(ace->resources[i]);
65     }
66     OICFree(ace->resources);
67
68     //Clean Period
69     if(ace->periods)
70     {
71         for(i = 0; i < ace->prdRecrLen; i++)
72         {
73             OICFree(ace->periods[i]);
74         }
75         OICFree(ace->periods);
76     }
77
78     //Clean Recurrence
79     if(ace->recurrences)
80     {
81         for(i = 0; i < ace->prdRecrLen; i++)
82         {
83             OICFree(ace->recurrences[i]);
84         }
85         OICFree(ace->recurrences);
86     }
87
88     // Clean Owners
89     OICFree(ace->owners);
90
91     // Clean ACL node itself
92     OICFree(ace);
93 }
94
95 void DeleteACLList(OicSecAcl_t* acl)
96 {
97     if (acl)
98     {
99         OicSecAcl_t *aclTmp1 = NULL;
100         OicSecAcl_t *aclTmp2 = NULL;
101         LL_FOREACH_SAFE(acl, aclTmp1, aclTmp2)
102         {
103             LL_DELETE(acl, aclTmp1);
104             FreeACE(aclTmp1);
105         }
106     }
107 }
108
109 /*
110  * This internal method converts ACL data into JSON format.
111  *
112  * Note: Caller needs to invoke 'free' when finished done using
113  * return string.
114  */
115 char * BinToAclJSON(const OicSecAcl_t * acl)
116 {
117     cJSON *jsonRoot = NULL;
118     char *jsonStr = NULL;
119
120     if (acl)
121     {
122         jsonRoot = cJSON_CreateObject();
123         VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
124
125         cJSON *jsonAclArray = NULL;
126         cJSON_AddItemToObject (jsonRoot, OIC_JSON_ACL_NAME, jsonAclArray = cJSON_CreateArray());
127         VERIFY_NON_NULL(TAG, jsonAclArray, ERROR);
128
129         while(acl)
130         {
131             char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {};
132             uint32_t outLen = 0;
133             size_t inLen = 0;
134             B64Result b64Ret = B64_OK;
135
136             cJSON *jsonAcl = cJSON_CreateObject();
137
138             // Subject -- Mandatory
139             outLen = 0;
140             if (memcmp(&(acl->subject), &WILDCARD_SUBJECT_ID, sizeof(OicUuid_t)) == 0)
141             {
142                 inLen = WILDCARD_SUBJECT_ID_LEN;
143             }
144             else
145             {
146                 inLen =  sizeof(OicUuid_t);
147             }
148             b64Ret = b64Encode(acl->subject.id, inLen, base64Buff,
149                 sizeof(base64Buff), &outLen);
150             VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
151             cJSON_AddStringToObject(jsonAcl, OIC_JSON_SUBJECT_NAME, base64Buff );
152
153             // Resources -- Mandatory
154             cJSON *jsonRsrcArray = NULL;
155             cJSON_AddItemToObject (jsonAcl, OIC_JSON_RESOURCES_NAME, jsonRsrcArray = cJSON_CreateArray());
156             VERIFY_NON_NULL(TAG, jsonRsrcArray, ERROR);
157             for (size_t i = 0; i < acl->resourcesLen; i++)
158             {
159                 cJSON_AddItemToArray (jsonRsrcArray, cJSON_CreateString(acl->resources[i]));
160             }
161
162             // Permissions -- Mandatory
163             cJSON_AddNumberToObject (jsonAcl, OIC_JSON_PERMISSION_NAME, acl->permission);
164
165             //Period & Recurrence -- Not Mandatory
166             if(0 != acl->prdRecrLen)
167             {
168                 cJSON *jsonPeriodArray = NULL;
169                 cJSON_AddItemToObject (jsonAcl, OIC_JSON_PERIODS_NAME,
170                         jsonPeriodArray = cJSON_CreateArray());
171                 VERIFY_NON_NULL(TAG, jsonPeriodArray, ERROR);
172                 for (size_t i = 0; i < acl->prdRecrLen; i++)
173                 {
174                     cJSON_AddItemToArray (jsonPeriodArray,
175                             cJSON_CreateString(acl->periods[i]));
176                 }
177             }
178
179             //Recurrence -- Not Mandatory
180             if(0 != acl->prdRecrLen && acl->recurrences)
181             {
182                 cJSON *jsonRecurArray  = NULL;
183                 cJSON_AddItemToObject (jsonAcl, OIC_JSON_RECURRENCES_NAME,
184                         jsonRecurArray = cJSON_CreateArray());
185                 VERIFY_NON_NULL(TAG, jsonRecurArray, ERROR);
186                 for (size_t i = 0; i < acl->prdRecrLen; i++)
187                 {
188                     cJSON_AddItemToArray (jsonRecurArray,
189                             cJSON_CreateString(acl->recurrences[i]));
190                 }
191             }
192
193             // Owners -- Mandatory
194             cJSON *jsonOwnrArray = NULL;
195             cJSON_AddItemToObject (jsonAcl, OIC_JSON_OWNERS_NAME, jsonOwnrArray = cJSON_CreateArray());
196             VERIFY_NON_NULL(TAG, jsonOwnrArray, ERROR);
197             for (size_t i = 0; i < acl->ownersLen; i++)
198             {
199                 outLen = 0;
200
201                 b64Ret = b64Encode(acl->owners[i].id, sizeof(((OicUuid_t*)0)->id), base64Buff,
202                     sizeof(base64Buff), &outLen);
203                 VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
204
205                 cJSON_AddItemToArray (jsonOwnrArray, cJSON_CreateString(base64Buff));
206             }
207
208             // Attach current acl node to Acl Array
209             cJSON_AddItemToArray(jsonAclArray, jsonAcl);
210             acl = acl->next;
211         }
212
213         jsonStr = cJSON_PrintUnformatted(jsonRoot);
214     }
215
216 exit:
217     if (jsonRoot)
218     {
219         cJSON_Delete(jsonRoot);
220     }
221     return jsonStr;
222 }
223
224 /*
225  * This internal method converts JSON ACL into binary ACL.
226  */
227 OicSecAcl_t * JSONToAclBin(const char * jsonStr)
228 {
229     OCStackResult ret = OC_STACK_ERROR;
230     OicSecAcl_t * headAcl = NULL;
231     OicSecAcl_t * prevAcl = NULL;
232     cJSON *jsonRoot = NULL;
233     cJSON *jsonAclArray = NULL;
234
235     VERIFY_NON_NULL(TAG, jsonStr, ERROR);
236
237     jsonRoot = cJSON_Parse(jsonStr);
238     VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
239
240     jsonAclArray = cJSON_GetObjectItem(jsonRoot, OIC_JSON_ACL_NAME);
241     VERIFY_NON_NULL(TAG, jsonAclArray, ERROR);
242
243     if (cJSON_Array == jsonAclArray->type)
244     {
245         int numAcl = cJSON_GetArraySize(jsonAclArray);
246         int idx = 0;
247
248         VERIFY_SUCCESS(TAG, numAcl > 0, INFO);
249         do
250         {
251             cJSON *jsonAcl = cJSON_GetArrayItem(jsonAclArray, idx);
252             VERIFY_NON_NULL(TAG, jsonAcl, ERROR);
253
254             OicSecAcl_t *acl = (OicSecAcl_t*)OICCalloc(1, sizeof(OicSecAcl_t));
255             VERIFY_NON_NULL(TAG, acl, ERROR);
256
257             headAcl = (headAcl) ? headAcl : acl;
258             if (prevAcl)
259             {
260                 prevAcl->next = acl;
261             }
262
263             size_t jsonObjLen = 0;
264             cJSON *jsonObj = NULL;
265
266             unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
267             uint32_t outLen = 0;
268             B64Result b64Ret = B64_OK;
269
270             // Subject -- Mandatory
271             jsonObj = cJSON_GetObjectItem(jsonAcl, OIC_JSON_SUBJECT_NAME);
272             VERIFY_NON_NULL(TAG, jsonObj, ERROR);
273             VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR);
274             outLen = 0;
275             b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring), base64Buff,
276                         sizeof(base64Buff), &outLen);
277             VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(acl->subject.id)), ERROR);
278             memcpy(acl->subject.id, base64Buff, outLen);
279
280             // Resources -- Mandatory
281             jsonObj = cJSON_GetObjectItem(jsonAcl, OIC_JSON_RESOURCES_NAME);
282             VERIFY_NON_NULL(TAG, jsonObj, ERROR);
283             VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR);
284
285             acl->resourcesLen = cJSON_GetArraySize(jsonObj);
286             VERIFY_SUCCESS(TAG, acl->resourcesLen > 0, ERROR);
287             acl->resources = (char**)OICCalloc(acl->resourcesLen, sizeof(char*));
288             VERIFY_NON_NULL(TAG, (acl->resources), ERROR);
289
290             size_t idxx = 0;
291             do
292             {
293                 cJSON *jsonRsrc = cJSON_GetArrayItem(jsonObj, idxx);
294                 VERIFY_NON_NULL(TAG, jsonRsrc, ERROR);
295
296                 jsonObjLen = strlen(jsonRsrc->valuestring) + 1;
297                 acl->resources[idxx] = (char*)OICMalloc(jsonObjLen);
298                 VERIFY_NON_NULL(TAG, (acl->resources[idxx]), ERROR);
299                 OICStrcpy(acl->resources[idxx], jsonObjLen, jsonRsrc->valuestring);
300             } while ( ++idxx < acl->resourcesLen);
301
302             // Permissions -- Mandatory
303             jsonObj = cJSON_GetObjectItem(jsonAcl,
304                                 OIC_JSON_PERMISSION_NAME);
305             VERIFY_NON_NULL(TAG, jsonObj, ERROR);
306             VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
307             acl->permission = jsonObj->valueint;
308
309             //Period -- Not Mandatory
310             cJSON *jsonPeriodObj = cJSON_GetObjectItem(jsonAcl,
311                     OIC_JSON_PERIODS_NAME);
312             if(jsonPeriodObj)
313             {
314                 VERIFY_SUCCESS(TAG, cJSON_Array == jsonPeriodObj->type,
315                                ERROR);
316                 acl->prdRecrLen = cJSON_GetArraySize(jsonPeriodObj);
317                 if(acl->prdRecrLen > 0)
318                 {
319                     acl->periods = (char**)OICCalloc(acl->prdRecrLen,
320                                     sizeof(char*));
321                     VERIFY_NON_NULL(TAG, acl->periods, ERROR);
322
323                     cJSON *jsonPeriod = NULL;
324                     for(size_t i = 0; i < acl->prdRecrLen; i++)
325                     {
326                         jsonPeriod = cJSON_GetArrayItem(jsonPeriodObj, i);
327                         VERIFY_NON_NULL(TAG, jsonPeriod, ERROR);
328
329                         jsonObjLen = strlen(jsonPeriod->valuestring) + 1;
330                         acl->periods[i] = (char*)OICMalloc(jsonObjLen);
331                         VERIFY_NON_NULL(TAG, acl->periods[i], ERROR);
332                         OICStrcpy(acl->periods[i], jsonObjLen,
333                                   jsonPeriod->valuestring);
334                     }
335                 }
336             }
337
338             //Recurrence -- Not mandatory
339             cJSON *jsonRecurObj = cJSON_GetObjectItem(jsonAcl,
340                                         OIC_JSON_RECURRENCES_NAME);
341             if(jsonRecurObj)
342             {
343                 VERIFY_SUCCESS(TAG, cJSON_Array == jsonRecurObj->type,
344                                ERROR);
345
346                 if(acl->prdRecrLen > 0)
347                 {
348                     acl->recurrences = (char**)OICCalloc(acl->prdRecrLen,
349                                              sizeof(char*));
350                     VERIFY_NON_NULL(TAG, acl->recurrences, ERROR);
351
352                     cJSON *jsonRecur = NULL;
353                     for(size_t i = 0; i < acl->prdRecrLen; i++)
354                     {
355                         jsonRecur = cJSON_GetArrayItem(jsonRecurObj, i);
356                         VERIFY_NON_NULL(TAG, jsonRecur, ERROR);
357                         jsonObjLen = strlen(jsonRecur->valuestring) + 1;
358                         acl->recurrences[i] = (char*)OICMalloc(jsonObjLen);
359                         VERIFY_NON_NULL(TAG, acl->recurrences[i], ERROR);
360                         OICStrcpy(acl->recurrences[i], jsonObjLen,
361                               jsonRecur->valuestring);
362                     }
363                 }
364             }
365
366             // Owners -- Mandatory
367             jsonObj = cJSON_GetObjectItem(jsonAcl, OIC_JSON_OWNERS_NAME);
368             VERIFY_NON_NULL(TAG, jsonObj, ERROR);
369             VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR);
370
371             acl->ownersLen = cJSON_GetArraySize(jsonObj);
372             VERIFY_SUCCESS(TAG, acl->ownersLen > 0, ERROR);
373             acl->owners = (OicUuid_t*)OICCalloc(acl->ownersLen, sizeof(OicUuid_t));
374             VERIFY_NON_NULL(TAG, (acl->owners), ERROR);
375
376             idxx = 0;
377             do
378             {
379                 cJSON *jsonOwnr = cJSON_GetArrayItem(jsonObj, idxx);
380                 VERIFY_NON_NULL(TAG, jsonOwnr, ERROR);
381                 VERIFY_SUCCESS(TAG, cJSON_String == jsonOwnr->type, ERROR);
382
383                 outLen = 0;
384                 b64Ret = b64Decode(jsonOwnr->valuestring, strlen(jsonOwnr->valuestring), base64Buff,
385                             sizeof(base64Buff), &outLen);
386
387                 VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(acl->owners[idxx].id)),
388                                     ERROR);
389                 memcpy(acl->owners[idxx].id, base64Buff, outLen);
390             } while ( ++idxx < acl->ownersLen);
391
392             prevAcl = acl;
393         } while( ++idx < numAcl);
394     }
395
396     ret = OC_STACK_OK;
397
398 exit:
399     cJSON_Delete(jsonRoot);
400     if (OC_STACK_OK != ret)
401     {
402         DeleteACLList(headAcl);
403         headAcl = NULL;
404     }
405     return headAcl;
406 }
407
408 static bool UpdatePersistentStorage(const OicSecAcl_t *acl)
409 {
410     // Convert ACL data into JSON for update to persistent storage
411     char *jsonStr = BinToAclJSON(acl);
412     if (jsonStr)
413     {
414         cJSON *jsonAcl = cJSON_Parse(jsonStr);
415         OICFree(jsonStr);
416
417         if ((jsonAcl) && (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_ACL_NAME, jsonAcl)))
418         {
419             return true;
420         }
421         cJSON_Delete(jsonAcl);
422     }
423     return false;
424 }
425
426 /*
427  * This method removes ACE for the subject and resource from the ACL
428  *
429  * @param subject  - subject of the ACE
430  * @param resource - resource of the ACE
431  *
432  * @return
433  *     OC_STACK_RESOURCE_DELETED on success
434  *     OC_STACK_NO_RESOURC on failure to find the appropriate ACE
435  *     OC_STACK_INVALID_PARAM on invalid parameter
436  */
437 static OCStackResult RemoveACE(const OicUuid_t * subject,
438                                const char * resource)
439 {
440     OC_LOG(DEBUG, TAG, "IN RemoveACE");
441
442     OicSecAcl_t *acl = NULL;
443     OicSecAcl_t *tempAcl = NULL;
444     bool deleteFlag = false;
445     OCStackResult ret = OC_STACK_NO_RESOURCE;
446
447     if(memcmp(subject->id, &WILDCARD_SUBJECT_ID, sizeof(subject->id)) == 0)
448     {
449         OC_LOG_V (ERROR, TAG, "%s received invalid parameter", __func__ );
450         return  OC_STACK_INVALID_PARAM;
451     }
452
453     //If resource is NULL then delete all the ACE for the subject.
454     if(NULL == resource || resource[0] == '\0')
455     {
456         LL_FOREACH_SAFE(gAcl, acl, tempAcl)
457         {
458             if(memcmp(acl->subject.id, subject->id, sizeof(subject->id)) == 0)
459             {
460                 LL_DELETE(gAcl, acl);
461                 FreeACE(acl);
462                 deleteFlag = true;
463             }
464         }
465     }
466     else
467     {
468         //Looping through ACL to find the right ACE to delete. If the required resource is the only
469         //resource in the ACE for the subject then delete the whole ACE. If there are more resources
470         //than the required resource in the ACE, for the subject then just delete the resource from
471         //the resource array
472         LL_FOREACH_SAFE(gAcl, acl, tempAcl)
473         {
474             if(memcmp(acl->subject.id, subject->id, sizeof(subject->id)) == 0)
475             {
476                 if(1 == acl->resourcesLen && strcmp(acl->resources[0],  resource) == 0)
477                 {
478                     LL_DELETE(gAcl, acl);
479                     FreeACE(acl);
480                     deleteFlag = true;
481                     break;
482                 }
483                 else
484                 {
485                     int resPos = -1;
486                     size_t i;
487                     for(i = 0; i < acl->resourcesLen; i++)
488                     {
489                         if(strcmp(acl->resources[i],  resource) == 0)
490                         {
491                             resPos = i;
492                             break;
493                         }
494                     }
495                     if((0 <= resPos))
496                     {
497                         OICFree(acl->resources[resPos]);
498                         acl->resources[resPos] = NULL;
499                         acl->resourcesLen -= 1;
500                         for(i = resPos; i < acl->resourcesLen; i++)
501                         {
502                             acl->resources[i] = acl->resources[i+1];
503                         }
504                         deleteFlag = true;
505                         break;
506                     }
507                 }
508             }
509         }
510     }
511
512     if(deleteFlag)
513     {
514         if(UpdatePersistentStorage(gAcl))
515         {
516             ret = OC_STACK_RESOURCE_DELETED;
517         }
518     }
519     return ret;
520 }
521
522 /*
523  * This method parses the query string received for REST requests and
524  * retrieves the 'subject' field.
525  *
526  * @param query querystring passed in REST request
527  * @param subject subject UUID parsed from query string
528  *
529  * @return true if query parsed successfully and found 'subject', else false.
530  */
531 static bool GetSubjectFromQueryString(const char *query, OicUuid_t *subject)
532 {
533     OicParseQueryIter_t parseIter = {.attrPos=NULL};
534
535     ParseQueryIterInit((unsigned char *)query, &parseIter);
536
537
538     while(GetNextQuery(&parseIter))
539     {
540         if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_SUBJECT_NAME, parseIter.attrLen) == 0)
541         {
542             VERIFY_SUCCESS(TAG, 0 != parseIter.valLen, ERROR);
543             unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
544             uint32_t outLen = 0;
545             B64Result b64Ret = B64_OK;
546             b64Ret = b64Decode((char *)parseIter.valPos, parseIter.valLen, base64Buff,
547                     sizeof(base64Buff), &outLen);
548             VERIFY_SUCCESS(TAG, (B64_OK == b64Ret && outLen <= sizeof(subject->id)), ERROR);
549             memcpy(subject->id, base64Buff, outLen);
550
551             return true;
552         }
553     }
554
555 exit:
556    return false;
557 }
558
559 /*
560  * This method parses the query string received for REST requests and
561  * retrieves the 'resource' field.
562  *
563  * @param query querystring passed in REST request
564  * @param resource resource parsed from query string
565  * @param resourceSize size of the memory pointed to resource
566  *
567  * @return true if query parsed successfully and found 'resource', else false.
568  */
569 static bool GetResourceFromQueryString(const char *query, char *resource, size_t resourceSize)
570 {
571     OicParseQueryIter_t parseIter = {.attrPos=NULL};
572
573     ParseQueryIterInit((unsigned char *)query, &parseIter);
574
575     while(GetNextQuery(&parseIter))
576     {
577         if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_RESOURCES_NAME, parseIter.attrLen) == 0)
578         {
579             VERIFY_SUCCESS(TAG, 0 != parseIter.valLen, ERROR);
580             OICStrcpy(resource, resourceSize, (char *)parseIter.valPos);
581
582             return true;
583         }
584     }
585
586 exit:
587    return false;
588 }
589
590
591
592 static OCEntityHandlerResult HandleACLGetRequest (const OCEntityHandlerRequest * ehRequest)
593 {
594     OCEntityHandlerResult ehRet = OC_EH_ERROR;
595     char* jsonStr = NULL;
596
597     // Process the REST querystring parameters
598     if(ehRequest->query)
599     {
600         OC_LOG (DEBUG, TAG, "HandleACLGetRequest processing query");
601
602         OicUuid_t subject = {.id={0}};
603         char resource[MAX_URI_LENGTH] = {0};
604
605         OicSecAcl_t *savePtr = NULL;
606         const OicSecAcl_t *currentAce = NULL;
607
608         // 'Subject' field is MUST for processing a querystring in REST request.
609         VERIFY_SUCCESS(TAG,
610                        true == GetSubjectFromQueryString(ehRequest->query, &subject),
611                        ERROR);
612
613         GetResourceFromQueryString(ehRequest->query, resource, sizeof(resource));
614
615         /*
616          * TODO : Currently, this code only provides one ACE for a Subject.
617          * Below code needs to be updated for scenarios when Subject have
618          * multiple ACE's in ACL resource.
619          */
620         while((currentAce = GetACLResourceData(&subject, &savePtr)))
621         {
622             /*
623              * If REST querystring contains a specific resource, we need
624              * to search for that resource in ACE.
625              */
626             if (resource[0] != '\0')
627             {
628                 for(size_t n = 0; n < currentAce->resourcesLen; n++)
629                 {
630                     if((currentAce->resources[n]) &&
631                             (0 == strcmp(resource, currentAce->resources[n]) ||
632                              0 == strcmp(WILDCARD_RESOURCE_URI, currentAce->resources[n])))
633                     {
634                         // Convert ACL data into JSON for transmission
635                         jsonStr = BinToAclJSON(currentAce);
636                         goto exit;
637                     }
638                 }
639             }
640             else
641             {
642                 // Convert ACL data into JSON for transmission
643                 jsonStr = BinToAclJSON(currentAce);
644                 goto exit;
645             }
646         }
647     }
648     else
649     {
650         // Convert ACL data into JSON for transmission
651         jsonStr = BinToAclJSON(gAcl);
652     }
653
654 exit:
655     ehRet = (jsonStr ? OC_EH_OK : OC_EH_ERROR);
656
657     // Send response payload to request originator
658     SendSRMResponse(ehRequest, ehRet, jsonStr);
659
660     OICFree(jsonStr);
661
662     OC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
663     return ehRet;
664 }
665
666 static OCEntityHandlerResult HandleACLPostRequest (const OCEntityHandlerRequest * ehRequest)
667 {
668     OCEntityHandlerResult ehRet = OC_EH_ERROR;
669
670     // Convert JSON ACL data into binary. This will also validate the ACL data received.
671     OicSecAcl_t* newAcl = JSONToAclBin(((OCSecurityPayload*)ehRequest->payload)->securityData);
672
673     if (newAcl)
674     {
675         // Append the new ACL to existing ACL
676         LL_APPEND(gAcl, newAcl);
677
678         if(UpdatePersistentStorage(gAcl))
679         {
680             ehRet = OC_EH_RESOURCE_CREATED;
681         }
682     }
683
684     // Send payload to request originator
685     SendSRMResponse(ehRequest, ehRet, NULL);
686
687     OC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
688     return ehRet;
689 }
690
691 static OCEntityHandlerResult HandleACLDeleteRequest(const OCEntityHandlerRequest *ehRequest)
692 {
693     OC_LOG (DEBUG, TAG, "Processing ACLDeleteRequest");
694     OCEntityHandlerResult ehRet = OC_EH_ERROR;
695     OicUuid_t subject = {.id={0}};
696     char resource[MAX_URI_LENGTH] = {0};
697
698     VERIFY_NON_NULL(TAG, ehRequest->query, ERROR);
699
700     // 'Subject' field is MUST for processing a querystring in REST request.
701     VERIFY_SUCCESS(TAG,
702             true == GetSubjectFromQueryString(ehRequest->query, &subject),
703             ERROR);
704
705     GetResourceFromQueryString(ehRequest->query, resource, sizeof(resource));
706
707     if(OC_STACK_RESOURCE_DELETED == RemoveACE(&subject, resource))
708     {
709         ehRet = OC_EH_RESOURCE_DELETED;
710     }
711
712 exit:
713     // Send payload to request originator
714     SendSRMResponse(ehRequest, ehRet, NULL);
715
716     return ehRet;
717 }
718
719 /*
720  * This internal method is the entity handler for ACL resources and
721  * will handle REST request (GET/PUT/POST/DEL) for them.
722  */
723 OCEntityHandlerResult ACLEntityHandler (OCEntityHandlerFlag flag,
724                                         OCEntityHandlerRequest * ehRequest,
725                                         void* callbackParameter)
726 {
727     OC_LOG(DEBUG, TAG, "Received request ACLEntityHandler");
728     (void)callbackParameter;
729     OCEntityHandlerResult ehRet = OC_EH_ERROR;
730
731     if (!ehRequest)
732     {
733         return ehRet;
734     }
735
736     if (flag & OC_REQUEST_FLAG)
737     {
738         // TODO :  Handle PUT method
739         OC_LOG (DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
740         switch (ehRequest->method)
741         {
742             case OC_REST_GET:
743                 ehRet = HandleACLGetRequest(ehRequest);
744                 break;
745
746             case OC_REST_POST:
747                 ehRet = HandleACLPostRequest(ehRequest);
748                 break;
749
750             case OC_REST_DELETE:
751                 ehRet = HandleACLDeleteRequest(ehRequest);
752                 break;
753
754             default:
755                 ehRet = OC_EH_ERROR;
756                 SendSRMResponse(ehRequest, ehRet, NULL);
757         }
758     }
759
760     return ehRet;
761 }
762
763 /*
764  * This internal method is used to create '/oic/sec/acl' resource.
765  */
766 OCStackResult CreateACLResource()
767 {
768     OCStackResult ret;
769
770     ret = OCCreateResource(&gAclHandle,
771                            OIC_RSRC_TYPE_SEC_ACL,
772                            OIC_MI_DEF,
773                            OIC_RSRC_ACL_URI,
774                            ACLEntityHandler,
775                            NULL,
776                            OC_OBSERVABLE | OC_SECURE | OC_EXPLICIT_DISCOVERABLE);
777
778     if (OC_STACK_OK != ret)
779     {
780         OC_LOG (FATAL, TAG, "Unable to instantiate ACL resource");
781         DeInitACLResource();
782     }
783     return ret;
784 }
785
786 /*
787  * This internal method is to retrieve the default ACL.
788  * If SVR database in persistent storage got corrupted or
789  * is not available for some reason, a default ACL is created
790  * which allows user to initiate ACL provisioning again.
791  */
792 OCStackResult  GetDefaultACL(OicSecAcl_t** defaultAcl)
793 {
794     OCStackResult ret = OC_STACK_ERROR;
795
796     OicUuid_t ownerId = {.id = {0}};
797
798     /*
799      * TODO In future, when new virtual resources will be added in OIC
800      * specification, Iotivity stack should be able to add them in
801      * existing SVR database. To support this, we need to add 'versioning'
802      * mechanism in SVR database.
803      */
804
805     const char *rsrcs[] = {
806         OC_RSRVD_WELL_KNOWN_URI,
807         OC_RSRVD_DEVICE_URI,
808         OC_RSRVD_PLATFORM_URI,
809         OC_RSRVD_RESOURCE_TYPES_URI,
810 #ifdef WITH_PRESENCE
811         OC_RSRVD_PRESENCE_URI,
812 #endif //WITH_PRESENCE
813         OIC_RSRC_ACL_URI,
814         OIC_RSRC_DOXM_URI,
815         OIC_RSRC_PSTAT_URI,
816     };
817
818     if (!defaultAcl)
819     {
820         return OC_STACK_INVALID_PARAM;
821     }
822
823     OicSecAcl_t *acl = (OicSecAcl_t *)OICCalloc(1, sizeof(OicSecAcl_t));
824     VERIFY_NON_NULL(TAG, acl, ERROR);
825
826     // Subject -- Mandatory
827     memcpy(&(acl->subject), &WILDCARD_SUBJECT_ID, sizeof(acl->subject));
828
829     // Resources -- Mandatory
830     acl->resourcesLen = sizeof(rsrcs)/sizeof(rsrcs[0]);
831
832     acl->resources = (char**)OICCalloc(acl->resourcesLen, sizeof(char*));
833     VERIFY_NON_NULL(TAG, (acl->resources), ERROR);
834
835     for (size_t i = 0; i <  acl->resourcesLen; i++)
836     {
837         size_t len = strlen(rsrcs[i]) + 1;
838         acl->resources[i] = (char*)OICMalloc(len * sizeof(char));
839         VERIFY_NON_NULL(TAG, (acl->resources[i]), ERROR);
840         OICStrcpy(acl->resources[i], len, rsrcs[i]);
841     }
842
843     acl->permission = PERMISSION_READ;
844     acl->prdRecrLen = 0;
845     acl->periods = NULL;
846     acl->recurrences = NULL;
847
848     // Device ID is the owner of this default ACL
849     ret = GetDoxmDeviceID( &ownerId);
850     VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, FATAL);
851
852     acl->ownersLen = 1;
853     acl->owners = (OicUuid_t*)OICMalloc(sizeof(OicUuid_t));
854     VERIFY_NON_NULL(TAG, (acl->owners), ERROR);
855     memcpy(acl->owners, &ownerId, sizeof(OicUuid_t));
856
857     acl->next = NULL;
858
859     *defaultAcl = acl;
860     ret = OC_STACK_OK;
861
862 exit:
863
864     if (ret != OC_STACK_OK)
865     {
866         DeleteACLList(acl);
867         acl = NULL;
868     }
869
870     return ret;
871 }
872
873 /**
874  * Initialize ACL resource by loading data from persistent storage.
875  *
876  * @retval  OC_STACK_OK for Success, otherwise some error value
877  */
878 OCStackResult InitACLResource()
879 {
880     OCStackResult ret = OC_STACK_ERROR;
881
882     // Read ACL resource from PS
883     char* jsonSVRDatabase = GetSVRDatabase();
884
885     if (jsonSVRDatabase)
886     {
887         // Convert JSON ACL into binary format
888         gAcl = JSONToAclBin(jsonSVRDatabase);
889         OICFree(jsonSVRDatabase);
890     }
891     /*
892      * If SVR database in persistent storage got corrupted or
893      * is not available for some reason, a default ACL is created
894      * which allows user to initiate ACL provisioning again.
895      */
896     if (!jsonSVRDatabase || !gAcl)
897     {
898         GetDefaultACL(&gAcl);
899         // TODO Needs to update persistent storage
900     }
901     VERIFY_NON_NULL(TAG, gAcl, FATAL);
902
903     // Instantiate 'oic.sec.acl'
904     ret = CreateACLResource();
905
906 exit:
907     if (OC_STACK_OK != ret)
908     {
909         DeInitACLResource();
910     }
911     return ret;
912 }
913
914 /**
915  * Perform cleanup for ACL resources.
916  *
917  * @retval  none
918  */
919 void DeInitACLResource()
920 {
921     OCDeleteResource(gAclHandle);
922     gAclHandle = NULL;
923
924     DeleteACLList(gAcl);
925     gAcl = NULL;
926 }
927
928 /**
929  * This method is used by PolicyEngine to retrieve ACL for a Subject.
930  *
931  * @param subjectId ID of the subject for which ACL is required.
932  * @param savePtr is used internally by @ref GetACLResourceData to maintain index between
933  *                successive calls for same subjectId.
934  *
935  * @retval  reference to @ref OicSecAcl_t if ACL is found, else NULL
936  *
937  * @note On the first call to @ref GetACLResourceData, savePtr should point to NULL
938  */
939 const OicSecAcl_t* GetACLResourceData(const OicUuid_t* subjectId, OicSecAcl_t **savePtr)
940 {
941     OicSecAcl_t *acl = NULL;
942     OicSecAcl_t *begin = NULL;
943
944     if ( NULL == subjectId)
945     {
946         return NULL;
947     }
948
949     /*
950      * savePtr MUST point to NULL if this is the 'first' call to retrieve ACL for
951      * subjectID.
952      */
953     if (NULL == *savePtr)
954     {
955         begin = gAcl;
956     }
957     else
958     {
959         /*
960          * If this is a 'successive' call, search for location pointed by
961          * savePtr and assign 'begin' to the next ACL after it in the linked
962          * list and start searching from there.
963          */
964         LL_FOREACH(gAcl, acl)
965         {
966             if (acl == *savePtr)
967             {
968                 begin = acl->next;
969             }
970         }
971     }
972
973     // Find the next ACL corresponding to the 'subjectID' and return it.
974     LL_FOREACH(begin, acl)
975     {
976         if (memcmp(&(acl->subject), subjectId, sizeof(OicUuid_t)) == 0)
977         {
978             *savePtr = acl;
979             return acl;
980         }
981     }
982
983     // Cleanup in case no ACL is found
984     *savePtr = NULL;
985     return NULL;
986 }
987
988
989 OCStackResult InstallNewACL(const char* newJsonStr)
990 {
991     OCStackResult ret = OC_STACK_ERROR;
992
993     // Convert JSON ACL data into binary. This will also validate the ACL data received.
994     OicSecAcl_t* newAcl = JSONToAclBin(newJsonStr);
995
996     if (newAcl)
997     {
998         // Append the new ACL to existing ACL
999         LL_APPEND(gAcl, newAcl);
1000
1001         // Convert ACL data into JSON for update to persistent storage
1002         char *jsonStr = BinToAclJSON(gAcl);
1003         if (jsonStr)
1004         {
1005             cJSON *jsonAcl = cJSON_Parse(jsonStr);
1006             OICFree(jsonStr);
1007
1008             if (jsonAcl)
1009             {
1010                 ret = UpdateSVRDatabase(OIC_JSON_ACL_NAME, jsonAcl);
1011             }
1012             cJSON_Delete(jsonAcl);
1013         }
1014     }
1015
1016     return ret;
1017 }