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