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