RAML v1.1 sync-up in SVR DB
[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 #ifdef WITH_ARDUINO
22 #include <string.h>
23 #else
24 #include <strings.h>
25 #endif
26 #include <stdlib.h>
27
28 #include "ocstack.h"
29 #include "ocserverrequest.h"
30 #include "oic_malloc.h"
31 #include "oic_string.h"
32 #include "ocrandom.h"
33 #include "ocpayload.h"
34 #include "utlist.h"
35 #include "payload_logging.h"
36 #include "srmresourcestrings.h"
37 #include "aclresource.h"
38 #include "doxmresource.h"
39 #include "resourcemanager.h"
40 #include "srmutility.h"
41 #include "psinterface.h"
42
43 #include "security_internals.h"
44
45 #define TAG  "SRM-ACL"
46 #define NUMBER_OF_SEC_PROV_RSCS 4
47 #define NUMBER_OF_DEFAULT_SEC_RSCS 2
48
49 static const uint8_t ACL_MAP_SIZE = 2;
50 static const uint8_t ACL_ACLIST_MAP_SIZE = 1;
51 static const uint8_t ACL_ACES_MAP_SIZE = 3;
52 static const uint8_t ACL_RESOURCE_MAP_SIZE = 3;
53
54
55 // CborSize is the default cbor payload size being used.
56 static const uint16_t CBOR_SIZE = 2048;
57
58 static OicSecAcl_t *gAcl = NULL;
59 static OCResourceHandle gAclHandle = NULL;
60
61 /**
62  * This function frees OicSecAcl_t object's fields and object itself.
63  */
64 static void FreeACE(OicSecAcl_t *ace)
65 {
66     size_t i;
67     if (NULL == ace)
68     {
69         OIC_LOG(ERROR, TAG, "Invalid Parameter");
70         return;
71     }
72
73     // Clean Resources
74     for (i = 0; i < ace->resourcesLen; i++)
75     {
76         OICFree(ace->resources[i]);
77     }
78     OICFree(ace->resources);
79
80     //Clean Period
81     if (ace->periods)
82     {
83         for (i = 0; i < ace->prdRecrLen; i++)
84         {
85             OICFree(ace->periods[i]);
86         }
87         OICFree(ace->periods);
88     }
89
90     //Clean Recurrence
91     if (ace->recurrences)
92     {
93         for (i = 0; i < ace->prdRecrLen; i++)
94         {
95             OICFree(ace->recurrences[i]);
96         }
97         OICFree(ace->recurrences);
98     }
99
100     // Clean Owners
101     OICFree(ace->owners);
102
103     // Clean ACL node itself
104     OICFree(ace);
105 }
106
107 void DeleteACLList(OicSecAcl_t* acl)
108 {
109     if (acl)
110     {
111         OicSecAcl_t *aclTmp1 = NULL;
112         OicSecAcl_t *aclTmp2 = NULL;
113         LL_FOREACH_SAFE(acl, aclTmp1, aclTmp2)
114         {
115             LL_DELETE(acl, aclTmp1);
116             FreeACE(aclTmp1);
117         }
118     }
119 }
120
121 static size_t OicSecAclSize(const OicSecAcl_t *secAcl)
122 {
123     if (!secAcl)
124     {
125         return 0;
126     }
127     OicSecAcl_t *acl = (OicSecAcl_t *)secAcl;
128     size_t size = 0;
129     while (acl)
130     {
131        size++;
132        acl = acl->next;
133     }
134     return size;
135 }
136
137 OCStackResult AclToCBORPayload(const OicSecAcl_t *secAcl, uint8_t **payload, size_t *size)
138 {
139      if (NULL == secAcl || NULL == payload || NULL != *payload || NULL == size)
140     {
141         return OC_STACK_INVALID_PARAM;
142     }
143
144     OCStackResult ret = OC_STACK_ERROR;
145     CborError cborEncoderResult = CborNoError;
146     OicSecAcl_t *acl = (OicSecAcl_t *)secAcl;
147     CborEncoder encoder = { {.ptr = NULL }, .end = 0 };
148     CborEncoder aclMap = { {.ptr = NULL }, .end = 0 };
149     CborEncoder aclListMap = { {.ptr = NULL }, .end = 0 };
150     CborEncoder acesArray = { {.ptr = NULL }, .end = 0 };
151     uint8_t *outPayload = NULL;
152     size_t cborLen = *size;
153     *size = 0;
154     *payload = NULL;
155
156     if (cborLen == 0)
157     {
158         cborLen = CBOR_SIZE;
159     }
160
161     outPayload = (uint8_t *)OICCalloc(1, cborLen);
162     VERIFY_NON_NULL(TAG, outPayload, ERROR);
163     cbor_encoder_init(&encoder, outPayload, cborLen, 0);
164
165     // Create ACL Map (aclist, rownerid)
166     cborEncoderResult = cbor_encoder_create_map(&encoder, &aclMap, ACL_MAP_SIZE);
167     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Creating ACL Map.");
168
169     cborEncoderResult = cbor_encode_text_string(&aclMap, OIC_JSON_ACLIST_NAME,
170         strlen(OIC_JSON_ACLIST_NAME));
171     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding aclist Name Tag.");
172
173     // Create ACLIST Map (aces)
174     cborEncoderResult = cbor_encoder_create_map(&aclMap, &aclListMap, ACL_ACLIST_MAP_SIZE);
175     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Creating ACLIST Map.");
176
177     cborEncoderResult = cbor_encode_text_string(&aclListMap, OIC_JSON_ACES_NAME,
178         strlen(OIC_JSON_ACES_NAME));
179     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ACES Name Tag.");
180
181     // Create ACES Array
182     cborEncoderResult = cbor_encoder_create_array(&aclListMap, &acesArray, OicSecAclSize(secAcl));
183     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Creating ACES Array.");
184
185     while (acl)
186     {
187         CborEncoder oicSecAclMap = { {.ptr = NULL }, .end = 0, .added = 0, .flags = 0 };
188         // ACL Map size - Number of mandatory items
189         uint8_t aclMapSize = ACL_ACES_MAP_SIZE;
190         size_t inLen = 0;
191
192         // Create ACL Map
193         if (acl->periods)
194         {
195             ++aclMapSize;
196         }
197         if (acl->recurrences)
198         {
199             ++aclMapSize;
200         }
201
202         cborEncoderResult = cbor_encoder_create_map(&acesArray, &oicSecAclMap, aclMapSize);
203         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Creating ACES Map");
204
205         // Subject -- Mandatory
206         cborEncoderResult = cbor_encode_text_string(&oicSecAclMap, OIC_JSON_SUBJECT_NAME,
207             strlen(OIC_JSON_SUBJECT_NAME));
208         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Subject Name Tag.");
209         inLen = (memcmp(&(acl->subject), &WILDCARD_SUBJECT_ID, sizeof(OicUuid_t)) == 0) ?
210             WILDCARD_SUBJECT_ID_LEN : sizeof(OicUuid_t);
211         if(inLen == WILDCARD_SUBJECT_ID_LEN)
212         {
213             char *subject = NULL;
214             cborEncoderResult = cbor_encode_text_string(&oicSecAclMap, WILDCARD_RESOURCE_URI,
215                 strlen(WILDCARD_RESOURCE_URI));
216             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Subject Id wildcard Value.");
217         }
218         else
219         {
220             char *subject = NULL;
221             ret = ConvertUuidToStr(&acl->subject, &subject);
222             VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
223             cborEncoderResult = cbor_encode_text_string(&oicSecAclMap, subject, strlen(subject));
224             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Subject Id Value.");
225             OICFree(subject);
226         }
227
228         // Resources
229         {
230             CborEncoder resources = { {.ptr = NULL }, .end = 0, .added = 0, .flags = 0 };
231             cborEncoderResult = cbor_encode_text_string(&oicSecAclMap, OIC_JSON_RESOURCES_NAME,
232                 strlen(OIC_JSON_RESOURCES_NAME));
233             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Resource Name Tag.");
234
235             cborEncoderResult = cbor_encoder_create_array(&oicSecAclMap, &resources, acl->resourcesLen);
236             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Resource Name Array.");
237
238             for (size_t i = 0; i < acl->resourcesLen; i++)
239             {
240
241                 CborEncoder rMap = { {.ptr = NULL }, .end = 0 };
242                 cborEncoderResult = cbor_encoder_create_map(&resources, &rMap, ACL_RESOURCE_MAP_SIZE);
243                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Resource Map.");
244
245                 cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_HREF_NAME,
246                         strlen(OIC_JSON_HREF_NAME));
247                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding HREF Name Tag.");
248                 cborEncoderResult = cbor_encode_text_string(&rMap, acl->resources[i],
249                         strlen(acl->resources[i]));
250                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding HREF Value in Map.");
251
252                 cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_RT_NAME,
253                         strlen(OIC_JSON_RT_NAME));
254                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Name Tag.");
255
256                 // TODO : Need to assign real value of RT
257                 cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_EMPTY_STRING,
258                         strlen(OIC_JSON_EMPTY_STRING));
259                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Value.");
260
261                 cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_IF_NAME,
262                         strlen(OIC_JSON_IF_NAME));
263                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Name Tag.");
264
265                 // TODO : Need to assign real value of IF
266                 cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_EMPTY_STRING,
267                         strlen(OIC_JSON_EMPTY_STRING));
268                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Value.");
269
270
271                 cborEncoderResult = cbor_encoder_close_container(&resources, &rMap);
272                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Resource Map.");
273
274             }
275             cborEncoderResult = cbor_encoder_close_container(&oicSecAclMap, &resources);
276             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Resource Name Array.");
277         }
278
279
280         // Permissions -- Mandatory
281         cborEncoderResult = cbor_encode_text_string(&oicSecAclMap, OIC_JSON_PERMISSION_NAME,
282             strlen(OIC_JSON_PERMISSION_NAME));
283         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Permission Name Tag.");
284         cborEncoderResult = cbor_encode_int(&oicSecAclMap, acl->permission);
285         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Permission Name Value.");
286
287         // Period -- Not Mandatory
288         if (acl->periods)
289         {
290
291             CborEncoder period;
292             cborEncoderResult = cbor_encode_text_string(&oicSecAclMap, OIC_JSON_PERIOD_NAME,
293                 strlen(OIC_JSON_PERIOD_NAME));
294             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Period Tag.");
295             cborEncoderResult = cbor_encoder_create_array(&oicSecAclMap, &period, acl->prdRecrLen);
296             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Period Array.");
297             for (size_t i = 0; i < acl->prdRecrLen; i++)
298             {
299                 cborEncoderResult = cbor_encode_text_string(&period, acl->periods[i],
300                     strlen(acl->periods[i]));
301                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Period Value in Array.");
302             }
303             cborEncoderResult = cbor_encoder_close_container(&oicSecAclMap, &period);
304             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Period Array.");
305         }
306
307         // Recurrence -- Not Mandatory
308         if (acl->recurrences)
309         {
310             CborEncoder recurrences;
311             cborEncoderResult = cbor_encode_text_string(&oicSecAclMap, OIC_JSON_RECURRENCES_NAME,
312                 strlen(OIC_JSON_RECURRENCES_NAME));
313             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Recurrence Tag.");
314             cborEncoderResult = cbor_encoder_create_array(&oicSecAclMap, &recurrences, acl->prdRecrLen);
315             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Recurrence Array.");
316
317             for (size_t i = 0; i < acl->prdRecrLen; i++)
318             {
319                 cborEncoderResult = cbor_encode_text_string(&recurrences, acl->recurrences[i],
320                     strlen(acl->recurrences[i]));
321                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Recurrence Array Value.");
322             }
323             cborEncoderResult = cbor_encoder_close_container(&oicSecAclMap, &recurrences);
324             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Recurrence Array");
325
326         }
327
328
329         cborEncoderResult = cbor_encoder_close_container(&acesArray, &oicSecAclMap);
330         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing ACES Map.");
331         acl = acl->next;
332     }
333
334
335
336     // Close ACES Array
337     cborEncoderResult = cbor_encoder_close_container(&aclListMap, &acesArray);
338     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing ACES Array.");
339
340
341
342     // Close ACLIST Map
343     cborEncoderResult = cbor_encoder_close_container(&aclMap, &aclListMap);
344     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing ACLIST Map.");
345
346
347
348     // TODO : Need to modify acl->owners[0] to acl->rownerid based on RAML spec.
349     acl = (OicSecAcl_t *)secAcl;
350     // Rownerid
351     if(acl->owners && acl->ownersLen > 0)
352     {
353         cborEncoderResult = cbor_encode_text_string(&aclMap, OIC_JSON_ROWNERID_NAME,
354             strlen(OIC_JSON_ROWNERID_NAME));
355         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding rownerid Name.");
356
357         char *rowner = NULL;
358         ret = ConvertUuidToStr(&acl->owners[0], &rowner);
359         VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
360         cborEncoderResult = cbor_encode_text_string(&aclMap, rowner, strlen(rowner));
361         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding rownerid Value.");
362         OICFree(rowner);
363     }
364
365     // Close ACL Map
366     cborEncoderResult = cbor_encoder_close_container(&encoder, &aclMap);
367     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing ACL Map.");
368
369     if (CborNoError == cborEncoderResult)
370     {
371         OIC_LOG(DEBUG, TAG, "AclToCBORPayload Successed");
372         *size = encoder.ptr - outPayload;
373         *payload = outPayload;
374         ret = OC_STACK_OK;
375     }
376 exit:
377     if (CborErrorOutOfMemory == cborEncoderResult)
378     {
379         OIC_LOG(DEBUG, TAG, "AclToCBORPayload:CborErrorOutOfMemory : retry with more memory");
380
381         // reallocate and try again!
382         OICFree(outPayload);
383         // Since the allocated initial memory failed, double the memory.
384         cborLen += encoder.ptr - encoder.end;
385         cborEncoderResult = CborNoError;
386         ret = AclToCBORPayload(secAcl, payload, &cborLen);
387         *size = cborLen;
388     }
389     else if (cborEncoderResult != CborNoError)
390     {
391         OIC_LOG(ERROR, TAG, "Failed to AclToCBORPayload");
392         OICFree(outPayload);
393         outPayload = NULL;
394         *size = 0;
395         *payload = NULL;
396         ret = OC_STACK_ERROR;
397     }
398
399     return ret;
400 }
401
402 // This function converts CBOR format to ACL data.
403 // Caller needs to invoke 'free' when done using
404 // note: This function is used in unit test hence not declared static,
405 OicSecAcl_t* CBORPayloadToAcl(const uint8_t *cborPayload, const size_t size)
406 {
407     if (NULL == cborPayload)
408     {
409         return NULL;
410     }
411     OCStackResult ret = OC_STACK_ERROR;
412     CborValue aclCbor = { .parser = NULL };
413     CborParser parser = { .end = NULL };
414     CborError cborFindResult = CborNoError;
415     cbor_parser_init(cborPayload, size, 0, &parser, &aclCbor);
416
417     OicSecAcl_t *headAcl = (OicSecAcl_t *) OICCalloc(1, sizeof(OicSecAcl_t));
418
419     // Enter ACL Map
420     CborValue aclMap = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
421     cborFindResult = cbor_value_enter_container(&aclCbor, &aclMap);
422     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering ACL Map.");
423
424     while (cbor_value_is_valid(&aclMap))
425     {
426         char* tagName = NULL;
427         size_t len = 0;
428         CborType type = cbor_value_get_type(&aclMap);
429         if (type == CborTextStringType)
430         {
431             cborFindResult = cbor_value_dup_text_string(&aclMap, &tagName, &len, NULL);
432             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Name in ACL Map.");
433             cborFindResult = cbor_value_advance(&aclMap);
434             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Value in ACL Map.");
435         }
436         if(tagName)
437         {
438             if (strcmp(tagName, OIC_JSON_ACLIST_NAME)  == 0)
439             {
440                 // Enter ACLIST Map
441                 CborValue aclistMap = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
442                 cborFindResult = cbor_value_enter_container(&aclMap, &aclistMap);
443                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering ACLIST Map.");
444
445
446                 while (cbor_value_is_valid(&aclistMap))
447                 {
448                     char* acName = NULL;
449                     size_t acLen = 0;
450                     CborType acType = cbor_value_get_type(&aclistMap);
451                     if (acType == CborTextStringType)
452                     {
453                         cborFindResult = cbor_value_dup_text_string(&aclistMap, &acName, &acLen, NULL);
454                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Name in ACLIST Map.");
455                         cborFindResult = cbor_value_advance(&aclistMap);
456                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Value in ACLIST Map.");
457                     }
458                     if(acName)
459                     {
460                         if (strcmp(acName, OIC_JSON_ACES_NAME)  == 0)
461                         {
462
463                             // Enter ACES Array
464                             CborValue aclArray = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
465                             cborFindResult = cbor_value_enter_container(&aclistMap, &aclArray);
466                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering ACL Array.");
467
468                             int acesCount = 0;
469                             while (cbor_value_is_valid(&aclArray))
470                             {
471                                 acesCount++;
472
473                                 CborValue aclMap = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
474                                 cborFindResult = cbor_value_enter_container(&aclArray, &aclMap);
475                                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering ACL Map.");
476                                 OicSecAcl_t *acl = NULL;
477
478                                 if(acesCount == 1)
479                                 {
480                                     acl = headAcl;
481                                 }
482                                 else
483                                 {
484                                     acl = (OicSecAcl_t *) OICCalloc(1, sizeof(OicSecAcl_t));
485                                     OicSecAcl_t *temp = headAcl;
486                                     while (temp->next)
487                                     {
488                                         temp = temp->next;
489                                     }
490                                     temp->next = acl;
491                                 }
492                                 VERIFY_NON_NULL(TAG, acl, ERROR);
493
494                                 while (cbor_value_is_valid(&aclMap))
495                                 {
496                                     char* name = NULL;
497                                     size_t len = 0;
498                                     CborType type = cbor_value_get_type(&aclMap);
499                                     if (type == CborTextStringType)
500                                     {
501                                         cborFindResult = cbor_value_dup_text_string(&aclMap, &name, &len, NULL);
502                                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Name in ACL Map.");
503                                         cborFindResult = cbor_value_advance(&aclMap);
504                                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Value in ACL Map.");
505                                     }
506                                     if (name)
507                                     {
508                                         // Subject -- Mandatory
509                                         if (strcmp(name, OIC_JSON_SUBJECT_NAME)  == 0)
510                                         {
511                                             char *subject = NULL;
512                                             cborFindResult = cbor_value_dup_text_string(&aclMap, &subject, &len, NULL);
513                                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding subject Value.");
514                                             if(strcmp(subject, WILDCARD_RESOURCE_URI) == 0)
515                                             {
516                                                 acl->subject.id[0] = '*';
517                                             }
518                                             else
519                                             {
520                                                 ret = ConvertStrToUuid(subject, &acl->subject);
521                                                 VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
522                                             }
523                                             OICFree(subject);
524                                         }
525
526                                         // Resources -- Mandatory
527                                         if (strcmp(name, OIC_JSON_RESOURCES_NAME) == 0)
528                                         {
529                                             CborValue resources = { .parser = NULL };
530                                             cborFindResult = cbor_value_get_array_length(&aclMap, &acl->resourcesLen);
531                                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a Resource Array Len Value.");
532                                             cborFindResult = cbor_value_enter_container(&aclMap, &resources);
533                                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering a Resource Array.");
534
535                                             acl->resources = (char **) OICMalloc(acl->resourcesLen * sizeof(char*));
536                                             VERIFY_NON_NULL(TAG, acl->resources, ERROR);
537                                             int i = 0;
538                                             while (cbor_value_is_valid(&resources))
539                                             {
540                                                 // rMap
541                                                 CborValue rMap = { .parser = NULL  };
542                                                 cborFindResult = cbor_value_enter_container(&resources, &rMap);
543                                                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering Resource Map");
544
545
546                                                 while(cbor_value_is_valid(&rMap))
547                                                 {
548                                                     char *rMapName = NULL;
549                                                     size_t rMapNameLen = 0;
550                                                     cborFindResult = cbor_value_dup_text_string(&rMap, &rMapName, &rMapNameLen, NULL);
551                                                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding RMap Data Name Tag.");
552                                                     cborFindResult = cbor_value_advance(&rMap);
553                                                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding RMap Data Value.");
554
555                                                     // "href"
556                                                     if (0 == strcmp(OIC_JSON_HREF_NAME, rMapName))
557                                                     {
558                                                         // TODO : Need to check data structure of OicSecAcl_t based on RAML spec.
559                                                         cborFindResult = cbor_value_dup_text_string(&rMap, &acl->resources[i++], &len, NULL);
560                                                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Href Value.");
561                                                     }
562
563                                                     // "rt"
564                                                     if (0 == strcmp(OIC_JSON_RT_NAME, rMapName))
565                                                     {
566                                                         // TODO : Need to check data structure of OicSecAcl_t and assign based on RAML spec.
567                                                         char *rtData = NULL;
568                                                         cborFindResult = cbor_value_dup_text_string(&rMap, &rtData, &len, NULL);
569                                                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding RT Value.");
570                                                         OICFree(rtData);
571                                                     }
572
573                                                     // "if"
574                                                     if (0 == strcmp(OIC_JSON_IF_NAME, rMapName))
575                                                     {
576                                                         // TODO : Need to check data structure of OicSecAcl_t and assign based on RAML spec.
577                                                         char *ifData = NULL;
578                                                         cborFindResult = cbor_value_dup_text_string(&rMap, &ifData, &len, NULL);
579                                                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding IF Value.");
580                                                         OICFree(ifData);
581                                                     }
582
583                                                     if (cbor_value_is_valid(&rMap))
584                                                     {
585                                                         cborFindResult = cbor_value_advance(&rMap);
586                                                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Rlist Map.");
587                                                     }
588                                                     OICFree(rMapName);
589                                                 }
590
591                                                 if (cbor_value_is_valid(&resources))
592                                                 {
593                                                     cborFindResult = cbor_value_advance(&resources);
594                                                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Resource Array.");
595                                                 }
596                                             }
597                                         }
598
599                                         // Permissions -- Mandatory
600                                         if (strcmp(name, OIC_JSON_PERMISSION_NAME) == 0)
601                                         {
602                                             cborFindResult = cbor_value_get_uint64(&aclMap, (uint64_t *) &acl->permission);
603                                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a PERM Value.");
604                                         }
605
606                                         // Period -- Not mandatory
607                                         if (strcmp(name, OIC_JSON_PERIOD_NAME) == 0)
608                                         {
609                                             CborValue period = { .parser = NULL };
610                                             cborFindResult = cbor_value_get_array_length(&aclMap, &acl->prdRecrLen);
611                                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a Period Array Len.");
612                                             cborFindResult = cbor_value_enter_container(&aclMap, &period);
613                                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a Period Array Map.");
614                                             acl->periods = (char**)OICCalloc(acl->prdRecrLen, sizeof(char*));
615                                             VERIFY_NON_NULL(TAG, acl->periods, ERROR);
616                                             int i = 0;
617                                             while (cbor_value_is_text_string(&period))
618                                             {
619                                                 cborFindResult = cbor_value_dup_text_string(&period, &acl->periods[i++],
620                                                     &len, NULL);
621                                                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a Period Array Value.");
622                                                 cborFindResult = cbor_value_advance(&period);
623                                                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing a Period Array.");
624                                             }
625                                         }
626
627                                         // Recurrence -- Not mandatory
628                                         if (strcmp(name, OIC_JSON_RECURRENCES_NAME) == 0)
629                                         {
630                                             CborValue recurrences = { .parser = NULL };
631                                             cborFindResult = cbor_value_enter_container(&aclMap, &recurrences);
632                                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Adding Recurrence Array.");
633                                             acl->recurrences = (char**)OICCalloc(acl->prdRecrLen, sizeof(char*));
634                                             VERIFY_NON_NULL(TAG, acl->recurrences, ERROR);
635                                             int i = 0;
636                                             while (cbor_value_is_text_string(&recurrences))
637                                             {
638                                                 cborFindResult = cbor_value_dup_text_string(&recurrences,
639                                                     &acl->recurrences[i++], &len, NULL);
640                                                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Adding Recurrence Array Value.");
641                                                 cborFindResult = cbor_value_advance(&recurrences);
642                                                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Closing Recurrence Array.");
643                                             }
644                                         }
645
646                                         OICFree(name);
647                                     }
648
649                                     if (type != CborMapType && cbor_value_is_valid(&aclMap))
650                                     {
651                                         cborFindResult = cbor_value_advance(&aclMap);
652                                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing the Array.");
653                                     }
654                                 }
655
656                                 acl->next = NULL;
657
658                                 if (cbor_value_is_valid(&aclArray))
659                                 {
660                                     cborFindResult = cbor_value_advance(&aclArray);
661                                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing ACL Array.");
662                                 }
663                             }
664                         }
665                         OICFree(acName);
666                     }
667
668                     if (cbor_value_is_valid(&aclistMap))
669                     {
670                         cborFindResult = cbor_value_advance(&aclistMap);
671                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing ACLIST Map.");
672                     }
673                 }
674             }
675
676             // TODO : Need to modify headAcl->owners[0].id to headAcl->rowner based on RAML spec.
677             if (strcmp(tagName, OIC_JSON_ROWNERID_NAME)  == 0)
678             {
679                 char *stRowner = NULL;
680                 cborFindResult = cbor_value_dup_text_string(&aclMap, &stRowner, &len, NULL);
681                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Rownerid Value.");
682                 headAcl->ownersLen = 1;
683                 headAcl->owners = (OicUuid_t *)OICCalloc(headAcl->ownersLen, sizeof(*headAcl->owners));
684                 VERIFY_NON_NULL(TAG, headAcl->owners, ERROR);
685                 ret = ConvertStrToUuid(stRowner, &headAcl->owners[0]);
686                 VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
687                 OICFree(stRowner);
688             }
689             OICFree(tagName);
690         }
691         if (cbor_value_is_valid(&aclMap))
692         {
693             cborFindResult = cbor_value_advance(&aclMap);
694             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing ACL Map.");
695         }
696     }
697
698 exit:
699     if (cborFindResult != CborNoError)
700     {
701         OIC_LOG(ERROR, TAG, "Failed to CBORPayloadToAcl");
702         DeleteACLList(headAcl);
703         headAcl = NULL;
704     }
705     return headAcl;
706 }
707
708 /**
709  * This method removes ACE for the subject and resource from the ACL
710  *
711  * @param subject of the ACE
712  * @param resource of the ACE
713  *
714  * @return
715  *     ::OC_STACK_RESOURCE_DELETED on success
716  *     ::OC_STACK_NO_RESOURCE on failure to find the appropriate ACE
717  *     ::OC_STACK_INVALID_PARAM on invalid parameter
718  */
719 static OCStackResult RemoveACE(const OicUuid_t * subject, const char * resource)
720 {
721     OIC_LOG(DEBUG, TAG, "IN RemoveACE");
722
723     OicSecAcl_t *acl = NULL;
724     OicSecAcl_t *tempAcl = NULL;
725     bool deleteFlag = false;
726     OCStackResult ret = OC_STACK_NO_RESOURCE;
727
728     if (memcmp(subject->id, &WILDCARD_SUBJECT_ID, sizeof(subject->id)) == 0)
729     {
730         OIC_LOG_V(ERROR, TAG, "%s received invalid parameter", __func__ );
731         return  OC_STACK_INVALID_PARAM;
732     }
733
734     //If resource is NULL then delete all the ACE for the subject.
735     if (NULL == resource || resource[0] == '\0')
736     {
737         LL_FOREACH_SAFE(gAcl, acl, tempAcl)
738         {
739             if (memcmp(acl->subject.id, subject->id, sizeof(subject->id)) == 0)
740             {
741                 LL_DELETE(gAcl, acl);
742                 FreeACE(acl);
743                 deleteFlag = true;
744             }
745         }
746     }
747     else
748     {
749         //Looping through ACL to find the right ACE to delete. If the required resource is the only
750         //resource in the ACE for the subject then delete the whole ACE. If there are more resources
751         //than the required resource in the ACE, for the subject then just delete the resource from
752         //the resource array
753         LL_FOREACH_SAFE(gAcl, acl, tempAcl)
754         {
755             if (memcmp(acl->subject.id, subject->id, sizeof(subject->id)) == 0)
756             {
757                 if (1 == acl->resourcesLen && strcmp(acl->resources[0], resource) == 0)
758                 {
759                     LL_DELETE(gAcl, acl);
760                     FreeACE(acl);
761                     deleteFlag = true;
762                     break;
763                 }
764                 else
765                 {
766                     size_t resPos = -1;
767                     size_t i;
768                     for (i = 0; i < acl->resourcesLen; i++)
769                     {
770                         if (strcmp(acl->resources[i], resource) == 0)
771                         {
772                             resPos = i;
773                             break;
774                         }
775                     }
776                     if (0 <= (int) resPos)
777                     {
778                         OICFree(acl->resources[resPos]);
779                         acl->resources[resPos] = NULL;
780                         acl->resourcesLen -= 1;
781                         for (i = resPos; i < acl->resourcesLen; i++)
782                         {
783                             acl->resources[i] = acl->resources[i + 1];
784                         }
785                         deleteFlag = true;
786                         break;
787                     }
788                 }
789             }
790         }
791     }
792
793     if (deleteFlag)
794     {
795         // In case of unit test do not update persistant storage.
796         if (memcmp(subject->id, &WILDCARD_SUBJECT_B64_ID, sizeof(subject->id)) == 0)
797         {
798             ret = OC_STACK_RESOURCE_DELETED;
799         }
800         else
801         {
802             uint8_t *payload = NULL;
803             size_t size = 0;
804             if (OC_STACK_OK == AclToCBORPayload(gAcl, &payload, &size))
805             {
806                 if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_ACL_NAME, payload, size))
807                 {
808                     ret = OC_STACK_RESOURCE_DELETED;
809                 }
810                 OICFree(payload);
811             }
812         }
813     }
814     return ret;
815 }
816
817 /**
818  * This method parses the query string received for REST requests and
819  * retrieves the 'subject' field.
820  *
821  * @param query querystring passed in REST request
822  * @param subject subject UUID parsed from query string
823  *
824  * @return true if query parsed successfully and found 'subject', else false.
825  */
826 static bool GetSubjectFromQueryString(const char *query, OicUuid_t *subject)
827 {
828     OicParseQueryIter_t parseIter = { .attrPos = NULL };
829
830     ParseQueryIterInit((unsigned char *) query, &parseIter);
831
832     while (GetNextQuery (&parseIter))
833     {
834         if (strncasecmp((char *) parseIter.attrPos, OIC_JSON_SUBJECT_NAME, parseIter.attrLen) == 0)
835         {
836             VERIFY_SUCCESS(TAG, 0 != parseIter.valLen, ERROR);
837             memcpy(subject->id, parseIter.valPos, parseIter.valLen);
838             return true;
839         }
840     }
841
842 exit:
843     return false;
844 }
845
846 /**
847  * This method parses the query string received for REST requests and
848  * retrieves the 'resource' field.
849  *
850  * @param query querystring passed in REST request
851  * @param resource resource parsed from query string
852  * @param resourceSize size of the memory pointed to resource
853  *
854  * @return true if query parsed successfully and found 'resource', else false.
855  */
856 static bool GetResourceFromQueryString(const char *query, char *resource, size_t resourceSize)
857 {
858     OicParseQueryIter_t parseIter = { .attrPos = NULL };
859
860     ParseQueryIterInit((unsigned char *) query, &parseIter);
861
862     while (GetNextQuery (&parseIter))
863     {
864         if (strncasecmp((char *) parseIter.attrPos, OIC_JSON_RESOURCES_NAME, parseIter.attrLen)
865                 == 0)
866         {
867             VERIFY_SUCCESS(TAG, 0 != parseIter.valLen, ERROR);
868             OICStrcpy(resource, resourceSize, (char *) parseIter.valPos);
869
870             return true;
871         }
872     }
873
874 exit:
875    return false;
876 }
877
878 static OCEntityHandlerResult HandleACLGetRequest(const OCEntityHandlerRequest *ehRequest)
879 {
880     OIC_LOG(INFO, TAG, "HandleACLGetRequest processing the request");
881     uint8_t* payload = NULL;
882     size_t size = 0;
883     OCEntityHandlerResult ehRet;
884
885     // Process the REST querystring parameters
886     if (ehRequest->query)
887     {
888         OIC_LOG(DEBUG, TAG, "HandleACLGetRequest processing query");
889
890         OicUuid_t subject = {.id= { 0 } };
891         char resource[MAX_URI_LENGTH] = { 0 };
892
893         OicSecAcl_t *savePtr = NULL;
894         const OicSecAcl_t *currentAce = NULL;
895
896         // 'Subject' field is MUST for processing a querystring in REST request.
897         VERIFY_SUCCESS(TAG, true == GetSubjectFromQueryString(ehRequest->query, &subject), ERROR);
898
899         GetResourceFromQueryString(ehRequest->query, resource, sizeof(resource));
900
901         /*
902          * TODO : Currently, this code only provides one ACE for a Subject.
903          * Below code needs to be updated for scenarios when Subject have
904          * multiple ACE's in ACL resource.
905          */
906         while ((currentAce = GetACLResourceData(&subject, &savePtr)))
907         {
908             /*
909              * If REST querystring contains a specific resource, we need
910              * to search for that resource in ACE.
911              */
912             if (resource[0] != '\0')
913             {
914                 for (size_t n = 0; n < currentAce->resourcesLen; n++)
915                 {
916                     if ((currentAce->resources[n])
917                             && (0 == strcmp(resource, currentAce->resources[n])
918                                     || 0 == strcmp(WILDCARD_RESOURCE_URI, currentAce->resources[n])))
919                     {
920                         // Convert ACL data into CBOR format for transmission
921                         if (OC_STACK_OK != AclToCBORPayload(currentAce, &payload, &size))
922                         {
923                             ehRet = OC_EH_ERROR;
924                         }
925                         goto exit;
926                     }
927                 }
928             }
929             else
930             {
931                 // Convert ACL data into CBOR format for transmission
932                 if (OC_STACK_OK != AclToCBORPayload(currentAce, &payload, &size))
933                 {
934                     ehRet = OC_EH_ERROR;
935                 }
936                 goto exit;
937             }
938         }
939     }
940     else
941     {
942         // Convert ACL data into CBOR format for transmission.
943         if (OC_STACK_OK != AclToCBORPayload(gAcl, &payload, &size))
944         {
945             ehRet = OC_EH_ERROR;
946         }
947     }
948 exit:
949     // A device should always have a default acl. Therefore, payload should never be NULL.
950     ehRet = (payload ? OC_EH_OK : OC_EH_ERROR);
951
952     // Send response payload to request originator
953     SendSRMCBORResponse(ehRequest, ehRet, payload, size);
954
955     OIC_LOG_V(DEBUG, TAG, "%s RetVal %d", __func__, ehRet);
956     return ehRet;
957 }
958
959 static OCEntityHandlerResult HandleACLPostRequest(const OCEntityHandlerRequest *ehRequest)
960 {
961     OIC_LOG(INFO, TAG, "HandleACLPostRequest processing the request");
962     OCEntityHandlerResult ehRet = OC_EH_ERROR;
963
964     // Convert CBOR into ACL data and update to SVR buffers. This will also validate the ACL data received.
965     uint8_t *payload = ((OCSecurityPayload *) ehRequest->payload)->securityData1;
966     size_t size = ((OCSecurityPayload *) ehRequest->payload)->payloadSize;
967     if (payload)
968     {
969         OicSecAcl_t *newAcl = CBORPayloadToAcl(payload, size);
970         if (newAcl)
971         {
972             // Append the new ACL to existing ACL
973             LL_APPEND(gAcl, newAcl);
974             size_t size = 0;
975             // In case of unit test do not update persistant storage.
976             if (memcmp(newAcl->subject.id, &WILDCARD_SUBJECT_ID, sizeof(newAcl->subject.id)) == 0
977                 || memcmp(newAcl->subject.id, &WILDCARD_SUBJECT_B64_ID, sizeof(newAcl->subject.id)) == 0)
978             {
979                 ehRet = OC_EH_RESOURCE_CREATED;
980             }
981             else
982             {
983                 uint8_t *cborPayload = NULL;
984                 if (OC_STACK_OK == AclToCBORPayload(gAcl, &cborPayload, &size))
985                 {
986                     if (UpdateSecureResourceInPS(OIC_JSON_ACL_NAME, cborPayload, size) == OC_STACK_OK)
987                     {
988                         ehRet = OC_EH_RESOURCE_CREATED;
989                     }
990                     OICFree(cborPayload);
991                 }
992             }
993         }
994     }
995
996     // Send payload to request originator
997     SendSRMCBORResponse(ehRequest, ehRet, NULL, 0);
998
999     OIC_LOG_V(DEBUG, TAG, "%s RetVal %d", __func__, ehRet);
1000     return ehRet;
1001 }
1002
1003 static OCEntityHandlerResult HandleACLDeleteRequest(const OCEntityHandlerRequest *ehRequest)
1004 {
1005     OIC_LOG(DEBUG, TAG, "Processing ACLDeleteRequest");
1006     OCEntityHandlerResult ehRet = OC_EH_ERROR;
1007     OicUuid_t subject = { .id= { 0 } };
1008     char resource[MAX_URI_LENGTH] = { 0 };
1009
1010     VERIFY_NON_NULL(TAG, ehRequest->query, ERROR);
1011
1012     // 'Subject' field is MUST for processing a querystring in REST request.
1013     VERIFY_SUCCESS(TAG, true == GetSubjectFromQueryString(ehRequest->query, &subject), ERROR);
1014
1015     GetResourceFromQueryString(ehRequest->query, resource, sizeof(resource));
1016
1017     if (OC_STACK_RESOURCE_DELETED == RemoveACE(&subject, resource))
1018     {
1019         ehRet = OC_EH_RESOURCE_DELETED;
1020     }
1021
1022 exit:
1023     // Send payload to request originator
1024     SendSRMCBORResponse(ehRequest, ehRet, NULL, 0);
1025
1026     return ehRet;
1027 }
1028
1029 OCEntityHandlerResult ACLEntityHandler(OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehRequest,
1030         void* callbackParameter)
1031 {
1032     OIC_LOG(DEBUG, TAG, "Received request ACLEntityHandler");
1033     (void)callbackParameter;
1034     OCEntityHandlerResult ehRet = OC_EH_ERROR;
1035
1036     if (!ehRequest)
1037     {
1038         return ehRet;
1039     }
1040
1041     if (flag & OC_REQUEST_FLAG)
1042     {
1043         // TODO :  Handle PUT method
1044         OIC_LOG(DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
1045         switch (ehRequest->method)
1046         {
1047             case OC_REST_GET:
1048                 ehRet = HandleACLGetRequest(ehRequest);
1049                 break;
1050
1051             case OC_REST_POST:
1052                 ehRet = HandleACLPostRequest(ehRequest);
1053                 break;
1054
1055             case OC_REST_DELETE:
1056                 ehRet = HandleACLDeleteRequest(ehRequest);
1057                 break;
1058
1059             default:
1060                 ehRet = OC_EH_ERROR;
1061                 SendSRMCBORResponse(ehRequest, ehRet, NULL, 0);
1062         }
1063     }
1064
1065     return ehRet;
1066 }
1067
1068 /**
1069  * This internal method is used to create '/oic/sec/acl' resource.
1070  */
1071 static OCStackResult CreateACLResource()
1072 {
1073     OCStackResult ret;
1074
1075     ret = OCCreateResource(&gAclHandle,
1076                            OIC_RSRC_TYPE_SEC_ACL,
1077                            OIC_MI_DEF,
1078                            OIC_RSRC_ACL_URI,
1079                            ACLEntityHandler,
1080                            NULL,
1081                            OC_OBSERVABLE | OC_SECURE | OC_EXPLICIT_DISCOVERABLE);
1082
1083     if (OC_STACK_OK != ret)
1084     {
1085         OIC_LOG(FATAL, TAG, "Unable to instantiate ACL resource");
1086         DeInitACLResource();
1087     }
1088     return ret;
1089 }
1090
1091 // This function sets the default ACL and is defined for the unit test only.
1092 OCStackResult SetDefaultACL(OicSecAcl_t *acl)
1093 {
1094     gAcl = acl;
1095     return OC_STACK_OK;
1096 }
1097
1098 OCStackResult GetDefaultACL(OicSecAcl_t** defaultAcl)
1099 {
1100     OCStackResult ret = OC_STACK_ERROR;
1101
1102     OicUuid_t ownerId = { .id = { 0 } };
1103
1104     /*
1105      * TODO In future, when new virtual resources will be added in OIC
1106      * specification, Iotivity stack should be able to add them in
1107      * existing SVR database. To support this, we need to add 'versioning'
1108      * mechanism in SVR database.
1109      */
1110
1111     const char *rsrcs[] = {
1112         OC_RSRVD_WELL_KNOWN_URI,
1113         OC_RSRVD_DEVICE_URI,
1114         OC_RSRVD_PLATFORM_URI,
1115         OC_RSRVD_RESOURCE_TYPES_URI,
1116 #ifdef WITH_PRESENCE
1117         OC_RSRVD_PRESENCE_URI,
1118 #endif //WITH_PRESENCE
1119         OIC_RSRC_ACL_URI,
1120         OIC_RSRC_DOXM_URI,
1121         OIC_RSRC_PSTAT_URI,
1122     };
1123
1124     if (!defaultAcl)
1125     {
1126         return OC_STACK_INVALID_PARAM;
1127     }
1128
1129     OicSecAcl_t *acl = (OicSecAcl_t *) OICCalloc(1, sizeof(OicSecAcl_t));
1130     VERIFY_NON_NULL(TAG, acl, ERROR);
1131
1132     // Subject -- Mandatory
1133     memcpy(&(acl->subject), &WILDCARD_SUBJECT_ID, sizeof(acl->subject));
1134
1135     // Resources -- Mandatory
1136     acl->resourcesLen = sizeof(rsrcs) / sizeof(rsrcs[0]);
1137
1138     acl->resources = (char**) OICCalloc(acl->resourcesLen, sizeof(char*));
1139     VERIFY_NON_NULL(TAG, (acl->resources), ERROR);
1140
1141     for (size_t i = 0; i < acl->resourcesLen; i++)
1142     {
1143         size_t len = strlen(rsrcs[i]) + 1;
1144         acl->resources[i] = (char*) OICMalloc(len * sizeof(char));
1145         VERIFY_NON_NULL(TAG, (acl->resources[i]), ERROR);
1146         OICStrcpy(acl->resources[i], len, rsrcs[i]);
1147     }
1148
1149     acl->permission = PERMISSION_READ;
1150     acl->prdRecrLen = 0;
1151     acl->periods = NULL;
1152     acl->recurrences = NULL;
1153
1154     // Device ID is the owner of this default ACL
1155     if (GetDoxmResourceData() != NULL)
1156     {
1157         ret = GetDoxmDeviceID(&ownerId);
1158         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, FATAL);
1159     }
1160     else
1161     {
1162         OCRandomUuidResult rdm = OCGenerateUuid(ownerId.id);
1163         VERIFY_SUCCESS(TAG, RAND_UUID_OK == rdm, FATAL);
1164     }
1165     acl->ownersLen = 1;
1166     acl->owners = (OicUuid_t*) OICMalloc(sizeof(OicUuid_t));
1167     VERIFY_NON_NULL(TAG, (acl->owners), ERROR);
1168     memcpy(acl->owners, &ownerId, sizeof(OicUuid_t));
1169
1170     acl->next = NULL;
1171
1172     *defaultAcl = acl;
1173     ret = OC_STACK_OK;
1174
1175 exit:
1176
1177     if (ret != OC_STACK_OK)
1178     {
1179         DeleteACLList(acl);
1180         acl = NULL;
1181     }
1182
1183     return ret;
1184 }
1185
1186 OCStackResult InitACLResource()
1187 {
1188     OCStackResult ret = OC_STACK_ERROR;
1189
1190     uint8_t *data = NULL;
1191     size_t size = 0;
1192     ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_ACL_NAME, &data, &size);
1193     // If database read failed
1194     if (ret != OC_STACK_OK)
1195     {
1196         OIC_LOG(DEBUG, TAG, "ReadSVDataFromPS failed");
1197     }
1198     if (data)
1199     {
1200         // Read ACL resource from PS
1201         gAcl = CBORPayloadToAcl(data, size);
1202     }
1203     /*
1204      * If SVR database in persistent storage got corrupted or
1205      * is not available for some reason, a default ACL is created
1206      * which allows user to initiate ACL provisioning again.
1207      */
1208     if (!gAcl)
1209     {
1210         GetDefaultACL(&gAcl);
1211         // TODO Needs to update persistent storage
1212     }
1213     VERIFY_NON_NULL(TAG, gAcl, FATAL);
1214
1215     // Instantiate 'oic.sec.acl'
1216     ret = CreateACLResource();
1217
1218 exit:
1219     if (OC_STACK_OK != ret)
1220     {
1221         DeInitACLResource();
1222     }
1223     return ret;
1224 }
1225
1226 OCStackResult DeInitACLResource()
1227 {
1228     OCStackResult ret =  OCDeleteResource(gAclHandle);
1229     gAclHandle = NULL;
1230
1231     if (gAcl)
1232     {
1233         DeleteACLList(gAcl);
1234         gAcl = NULL;
1235     }
1236     return ret;
1237 }
1238
1239 const OicSecAcl_t* GetACLResourceData(const OicUuid_t* subjectId, OicSecAcl_t **savePtr)
1240 {
1241     OicSecAcl_t *acl = NULL;
1242     OicSecAcl_t *begin = NULL;
1243
1244     if (NULL == subjectId)
1245     {
1246         return NULL;
1247     }
1248
1249     /*
1250      * savePtr MUST point to NULL if this is the 'first' call to retrieve ACL for
1251      * subjectID.
1252      */
1253     if (NULL == *savePtr)
1254     {
1255         begin = gAcl;
1256     }
1257     else
1258     {
1259         /*
1260          * If this is a 'successive' call, search for location pointed by
1261          * savePtr and assign 'begin' to the next ACL after it in the linked
1262          * list and start searching from there.
1263          */
1264         LL_FOREACH(gAcl, acl)
1265         {
1266             if (acl == *savePtr)
1267             {
1268                 begin = acl->next;
1269             }
1270         }
1271     }
1272
1273     // Find the next ACL corresponding to the 'subjectID' and return it.
1274     LL_FOREACH(begin, acl)
1275     {
1276         if (memcmp(&(acl->subject), subjectId, sizeof(OicUuid_t)) == 0)
1277         {
1278             *savePtr = acl;
1279             return acl;
1280         }
1281     }
1282
1283     // Cleanup in case no ACL is found
1284     *savePtr = NULL;
1285     return NULL;
1286 }
1287
1288 OCStackResult InstallNewACL(const uint8_t *cborPayload, const size_t size)
1289 {
1290     OCStackResult ret = OC_STACK_ERROR;
1291
1292     // Convert CBOR format to ACL data. This will also validate the ACL data received.
1293     OicSecAcl_t* newAcl = CBORPayloadToAcl(cborPayload, size);
1294
1295     if (newAcl)
1296     {
1297         // Append the new ACL to existing ACL
1298         LL_APPEND(gAcl, newAcl);
1299
1300         // Update persistent storage only if it is not WILDCARD_SUBJECT_ID
1301         if (memcmp(newAcl->subject.id, &WILDCARD_SUBJECT_ID, sizeof(newAcl->subject.id)) == 0
1302             || memcmp(newAcl->subject.id, &WILDCARD_SUBJECT_B64_ID, sizeof(newAcl->subject.id)) == 0)
1303         {
1304             ret = OC_STACK_OK;
1305         }
1306         else
1307         {
1308             size_t size = 0;
1309             uint8_t *payload = NULL;
1310             if (OC_STACK_OK == AclToCBORPayload(gAcl, &payload, &size))
1311             {
1312                 if (UpdateSecureResourceInPS(OIC_JSON_ACL_NAME, payload, size) == OC_STACK_OK)
1313                 {
1314                     ret = OC_STACK_OK;
1315                 }
1316                 OICFree(payload);
1317             }
1318         }
1319     }
1320
1321     return ret;
1322 }
1323
1324 /**
1325  * This function generates default ACL for security resource in case of owned status.
1326  *
1327  * @return Default ACL for security resource.
1328  */
1329 static OicSecAcl_t* GetSecDefaultACL()
1330 {
1331     const char *sec_rsrcs[] = {
1332         OIC_RSRC_DOXM_URI,
1333         OIC_RSRC_PSTAT_URI
1334     };
1335     OicUuid_t ownerId = {.id = {0}};
1336     OCStackResult res = OC_STACK_ERROR;
1337     OicSecAcl_t* newDefaultAcl = (OicSecAcl_t*)OICCalloc(1, sizeof(OicSecAcl_t));
1338     VERIFY_NON_NULL(TAG, newDefaultAcl, ERROR);
1339
1340     // Subject -- Mandatory
1341     memcpy(&(newDefaultAcl->subject), &WILDCARD_SUBJECT_ID, WILDCARD_SUBJECT_ID_LEN);
1342
1343     // Resources -- Mandatory
1344     newDefaultAcl->resourcesLen = NUMBER_OF_DEFAULT_SEC_RSCS;
1345     newDefaultAcl->resources = (char**)OICCalloc(NUMBER_OF_DEFAULT_SEC_RSCS, sizeof(char*));
1346     VERIFY_NON_NULL(TAG, (newDefaultAcl->resources), ERROR);
1347
1348     for (size_t i = 0; i <  NUMBER_OF_DEFAULT_SEC_RSCS; i++)
1349     {
1350         size_t len = strlen(sec_rsrcs[i]) + 1;
1351         newDefaultAcl->resources[i] = (char*)OICMalloc(len * sizeof(char));
1352         VERIFY_NON_NULL(TAG, (newDefaultAcl->resources[i]), ERROR);
1353         OICStrcpy(newDefaultAcl->resources[i], len, sec_rsrcs[i]);
1354     }
1355
1356     // Permissions -- Mandatory
1357     newDefaultAcl->permission = PERMISSION_READ;
1358
1359     //Period -- Not Mandatory
1360     newDefaultAcl->prdRecrLen = 0;
1361     newDefaultAcl->periods = NULL;
1362
1363     //Recurrence -- Not Mandatory
1364     newDefaultAcl->recurrences = NULL;
1365
1366     // Device ID is the owner of this default ACL
1367     res = GetDoxmDeviceID(&ownerId);
1368     VERIFY_SUCCESS(TAG, OC_STACK_OK == res, FATAL);
1369
1370     // Owners -- Mandatory
1371     newDefaultAcl->ownersLen = 1;
1372     newDefaultAcl->owners = (OicUuid_t*)OICMalloc(sizeof(OicUuid_t));
1373     VERIFY_NON_NULL(TAG, (newDefaultAcl->owners), ERROR);
1374     memcpy(newDefaultAcl->owners, &ownerId, sizeof(OicUuid_t));
1375
1376     return newDefaultAcl;
1377 exit:
1378     DeleteACLList(newDefaultAcl);
1379     return NULL;
1380
1381 }
1382
1383 OCStackResult UpdateDefaultSecProvACL()
1384 {
1385     OCStackResult ret = OC_STACK_OK;
1386     OicSecAcl_t *acl = NULL;
1387     OicSecAcl_t *tmp = NULL;
1388
1389     if(gAcl)
1390     {
1391         int matchedRsrc = 0;
1392         bool isRemoved = false;
1393
1394         LL_FOREACH_SAFE(gAcl, acl, tmp)
1395         {
1396             //Find default security resource ACL
1397             if(memcmp(&acl->subject, &WILDCARD_SUBJECT_ID, sizeof(OicUuid_t)) == 0 &&
1398                 ((PERMISSION_READ | PERMISSION_WRITE) == acl->permission))
1399             {
1400                 matchedRsrc = 0;
1401
1402                 for(size_t i = 0; i < acl->resourcesLen; i++)
1403                 {
1404                     if(strncmp(acl->resources[i], OIC_RSRC_DOXM_URI,
1405                                strlen(OIC_RSRC_DOXM_URI) + 1) == 0 ||
1406                        strncmp(acl->resources[i], OIC_RSRC_CRED_URI,
1407                                strlen(OIC_RSRC_CRED_URI) + 1) == 0 ||
1408                        strncmp(acl->resources[i], OIC_RSRC_ACL_URI,
1409                                strlen(OIC_RSRC_ACL_URI) + 1) == 0 ||
1410                        strncmp(acl->resources[i], OIC_RSRC_PSTAT_URI,
1411                                strlen(OIC_RSRC_PSTAT_URI) + 1) == 0)
1412                     {
1413                         matchedRsrc++;
1414                     }
1415                 }
1416
1417                 //If default security resource ACL is detected, delete it.
1418                 if(NUMBER_OF_SEC_PROV_RSCS == matchedRsrc)
1419                 {
1420                     LL_DELETE(gAcl, acl);
1421                     FreeACE(acl);
1422                     isRemoved = true;
1423                 }
1424             }
1425         }
1426
1427         if(isRemoved)
1428         {
1429             /*
1430              * Generate new security resource ACL as follows :
1431              *      subject : "*"
1432              *      resources :  '/oic/sec/doxm', '/oic/sec/pstat'
1433              *      permission : READ
1434              */
1435             OicSecAcl_t *newDefaultAcl = GetSecDefaultACL();
1436             if (newDefaultAcl)
1437             {
1438                 LL_APPEND(gAcl, newDefaultAcl);
1439
1440                 size_t size = 0;
1441                 uint8_t *payload = NULL;
1442                 if (OC_STACK_OK == AclToCBORPayload(gAcl, &payload, &size))
1443                 {
1444                     if (UpdateSecureResourceInPS(OIC_JSON_ACL_NAME, payload, size) == OC_STACK_OK)
1445                     {
1446                         ret = OC_STACK_OK;
1447                     }
1448                     OICFree(payload);
1449                 }
1450             }
1451         }
1452     }
1453
1454     return ret;
1455 }