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