Security CBOR cleanup
[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 = 4;
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 ACL node itself
101     OICFree(ace);
102 }
103
104 void DeleteACLList(OicSecAcl_t* acl)
105 {
106     if (acl)
107     {
108         OicSecAcl_t *aclTmp1 = NULL;
109         OicSecAcl_t *aclTmp2 = NULL;
110         LL_FOREACH_SAFE(acl, aclTmp1, aclTmp2)
111         {
112             LL_DELETE(acl, aclTmp1);
113             FreeACE(aclTmp1);
114         }
115     }
116 }
117
118 static size_t OicSecAclSize(const OicSecAcl_t *secAcl)
119 {
120     if (!secAcl)
121     {
122         return 0;
123     }
124     OicSecAcl_t *acl = (OicSecAcl_t *)secAcl;
125     size_t size = 0;
126     while (acl)
127     {
128        size++;
129        acl = acl->next;
130     }
131     return size;
132 }
133
134 OCStackResult AclToCBORPayload(const OicSecAcl_t *secAcl, uint8_t **payload, size_t *size)
135 {
136      if (NULL == secAcl || NULL == payload || NULL != *payload || NULL == size)
137     {
138         return OC_STACK_INVALID_PARAM;
139     }
140
141     OCStackResult ret = OC_STACK_ERROR;
142     CborError cborEncoderResult = CborNoError;
143     OicSecAcl_t *acl = (OicSecAcl_t *)secAcl;
144     CborEncoder encoder;
145     CborEncoder aclMap;
146     CborEncoder aclListMap;
147     CborEncoder acesArray;
148     uint8_t *outPayload = NULL;
149     size_t cborLen = *size;
150     *size = 0;
151     *payload = NULL;
152
153     if (cborLen == 0)
154     {
155         cborLen = CBOR_SIZE;
156     }
157
158     outPayload = (uint8_t *)OICCalloc(1, cborLen);
159     VERIFY_NON_NULL(TAG, outPayload, ERROR);
160     cbor_encoder_init(&encoder, outPayload, cborLen, 0);
161
162     // Create ACL Map (aclist, rownerid)
163     cborEncoderResult = cbor_encoder_create_map(&encoder, &aclMap, ACL_MAP_SIZE);
164     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Creating ACL Map.");
165
166     cborEncoderResult = cbor_encode_text_string(&aclMap, OIC_JSON_ACLIST_NAME,
167         strlen(OIC_JSON_ACLIST_NAME));
168     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding aclist Name Tag.");
169
170     // Create ACLIST Map (aces)
171     cborEncoderResult = cbor_encoder_create_map(&aclMap, &aclListMap, ACL_ACLIST_MAP_SIZE);
172     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Creating ACLIST Map.");
173
174     cborEncoderResult = cbor_encode_text_string(&aclListMap, OIC_JSON_ACES_NAME,
175         strlen(OIC_JSON_ACES_NAME));
176     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ACES Name Tag.");
177
178     // Create ACES Array
179     cborEncoderResult = cbor_encoder_create_array(&aclListMap, &acesArray, OicSecAclSize(secAcl));
180     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Creating ACES Array.");
181
182     while (acl)
183     {
184         CborEncoder oicSecAclMap;
185         // ACL Map size - Number of mandatory items
186         uint8_t aclMapSize = ACL_ACES_MAP_SIZE;
187         size_t inLen = 0;
188
189         // Create ACL Map
190         if (acl->periods)
191         {
192             ++aclMapSize;
193         }
194         if (acl->recurrences)
195         {
196             ++aclMapSize;
197         }
198
199         cborEncoderResult = cbor_encoder_create_map(&acesArray, &oicSecAclMap, aclMapSize);
200         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Creating ACES Map");
201
202         // Subject -- Mandatory
203         cborEncoderResult = cbor_encode_text_string(&oicSecAclMap, OIC_JSON_SUBJECTID_NAME,
204             strlen(OIC_JSON_SUBJECTID_NAME));
205         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Subject Name Tag.");
206         inLen = (memcmp(&(acl->subject), &WILDCARD_SUBJECT_ID, sizeof(OicUuid_t)) == 0) ?
207             WILDCARD_SUBJECT_ID_LEN : sizeof(OicUuid_t);
208         if(inLen == WILDCARD_SUBJECT_ID_LEN)
209         {
210             cborEncoderResult = cbor_encode_text_string(&oicSecAclMap, WILDCARD_RESOURCE_URI,
211                 strlen(WILDCARD_RESOURCE_URI));
212             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Subject Id wildcard Value.");
213         }
214         else
215         {
216             char *subject = NULL;
217             ret = ConvertUuidToStr(&acl->subject, &subject);
218             VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
219             cborEncoderResult = cbor_encode_text_string(&oicSecAclMap, subject, strlen(subject));
220             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Subject Id Value.");
221             OICFree(subject);
222         }
223
224         // Resources
225         {
226             CborEncoder resources;
227             cborEncoderResult = cbor_encode_text_string(&oicSecAclMap, OIC_JSON_RESOURCES_NAME,
228                 strlen(OIC_JSON_RESOURCES_NAME));
229             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Resource Name Tag.");
230
231             cborEncoderResult = cbor_encoder_create_array(&oicSecAclMap, &resources, acl->resourcesLen);
232             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Resource Name Array.");
233
234             for (size_t i = 0; i < acl->resourcesLen; i++)
235             {
236
237                 CborEncoder rMap;
238                 cborEncoderResult = cbor_encoder_create_map(&resources, &rMap, ACL_RESOURCE_MAP_SIZE);
239                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Resource Map.");
240
241                 cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_HREF_NAME,
242                         strlen(OIC_JSON_HREF_NAME));
243                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding HREF Name Tag.");
244                 cborEncoderResult = cbor_encode_text_string(&rMap, acl->resources[i],
245                         strlen(acl->resources[i]));
246                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding HREF Value in Map.");
247
248                 cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_REL_NAME,
249                         strlen(OIC_JSON_REL_NAME));
250                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding REL Name Tag.");
251
252                 // TODO : Need to assign real value of REL
253                 cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_EMPTY_STRING,
254                         strlen(OIC_JSON_EMPTY_STRING));
255                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding REL Value.");
256
257                 cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_RT_NAME,
258                         strlen(OIC_JSON_RT_NAME));
259                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Name Tag.");
260
261                 // TODO : Need to assign real value of RT
262                 cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_EMPTY_STRING,
263                         strlen(OIC_JSON_EMPTY_STRING));
264                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Value.");
265
266                 cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_IF_NAME,
267                         strlen(OIC_JSON_IF_NAME));
268                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Name Tag.");
269
270                 // TODO : Need to assign real value of IF
271                 cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_EMPTY_STRING,
272                         strlen(OIC_JSON_EMPTY_STRING));
273                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Value.");
274
275
276                 cborEncoderResult = cbor_encoder_close_container(&resources, &rMap);
277                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Resource Map.");
278
279             }
280             cborEncoderResult = cbor_encoder_close_container(&oicSecAclMap, &resources);
281             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Resource Name Array.");
282         }
283
284
285         // Permissions -- Mandatory
286         cborEncoderResult = cbor_encode_text_string(&oicSecAclMap, OIC_JSON_PERMISSION_NAME,
287             strlen(OIC_JSON_PERMISSION_NAME));
288         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Permission Name Tag.");
289         cborEncoderResult = cbor_encode_int(&oicSecAclMap, acl->permission);
290         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Permission Name Value.");
291
292         // Period -- Not Mandatory
293         if (acl->periods)
294         {
295
296             CborEncoder period;
297             cborEncoderResult = cbor_encode_text_string(&oicSecAclMap, OIC_JSON_PERIOD_NAME,
298                 strlen(OIC_JSON_PERIOD_NAME));
299             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Period Tag.");
300             cborEncoderResult = cbor_encoder_create_array(&oicSecAclMap, &period, acl->prdRecrLen);
301             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Period Array.");
302             for (size_t i = 0; i < acl->prdRecrLen; i++)
303             {
304                 cborEncoderResult = cbor_encode_text_string(&period, acl->periods[i],
305                     strlen(acl->periods[i]));
306                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Period Value in Array.");
307             }
308             cborEncoderResult = cbor_encoder_close_container(&oicSecAclMap, &period);
309             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Period Array.");
310         }
311
312         // Recurrence -- Not Mandatory
313         if (acl->recurrences)
314         {
315             CborEncoder recurrences;
316             cborEncoderResult = cbor_encode_text_string(&oicSecAclMap, OIC_JSON_RECURRENCES_NAME,
317                 strlen(OIC_JSON_RECURRENCES_NAME));
318             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Recurrence Tag.");
319             cborEncoderResult = cbor_encoder_create_array(&oicSecAclMap, &recurrences, acl->prdRecrLen);
320             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Recurrence Array.");
321
322             for (size_t i = 0; i < acl->prdRecrLen; i++)
323             {
324                 cborEncoderResult = cbor_encode_text_string(&recurrences, acl->recurrences[i],
325                     strlen(acl->recurrences[i]));
326                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Recurrence Array Value.");
327             }
328             cborEncoderResult = cbor_encoder_close_container(&oicSecAclMap, &recurrences);
329             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Recurrence Array");
330
331         }
332
333
334         cborEncoderResult = cbor_encoder_close_container(&acesArray, &oicSecAclMap);
335         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing ACES Map.");
336         acl = acl->next;
337     }
338
339     // Close ACES Array
340     cborEncoderResult = cbor_encoder_close_container(&aclListMap, &acesArray);
341     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing ACES Array.");
342
343     // Close ACLIST Map
344     cborEncoderResult = cbor_encoder_close_container(&aclMap, &aclListMap);
345     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing ACLIST Map.");
346
347     // Rownerid
348     {
349         char *rowner = NULL;
350         cborEncoderResult = cbor_encode_text_string(&aclMap, OIC_JSON_ROWNERID_NAME,
351             strlen(OIC_JSON_ROWNERID_NAME));
352         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding rownerid Name.");
353         ret = ConvertUuidToStr(&secAcl->rownerID, &rowner);
354         VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
355         cborEncoderResult = cbor_encode_text_string(&aclMap, rowner, strlen(rowner));
356         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding rownerid Value.");
357         OICFree(rowner);
358     }
359
360     // Close ACL Map
361     cborEncoderResult = cbor_encoder_close_container(&encoder, &aclMap);
362     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing ACL Map.");
363
364     if (CborNoError == cborEncoderResult)
365     {
366         OIC_LOG(DEBUG, TAG, "AclToCBORPayload Successed");
367         *size = encoder.ptr - outPayload;
368         *payload = outPayload;
369         ret = OC_STACK_OK;
370     }
371 exit:
372     if (CborErrorOutOfMemory == cborEncoderResult)
373     {
374         OIC_LOG(DEBUG, TAG, "AclToCBORPayload:CborErrorOutOfMemory : retry with more memory");
375
376         // reallocate and try again!
377         OICFree(outPayload);
378         // Since the allocated initial memory failed, double the memory.
379         cborLen += encoder.ptr - encoder.end;
380         cborEncoderResult = CborNoError;
381         ret = AclToCBORPayload(secAcl, payload, &cborLen);
382         *size = cborLen;
383     }
384     else if (cborEncoderResult != CborNoError)
385     {
386         OIC_LOG(ERROR, TAG, "Failed to AclToCBORPayload");
387         OICFree(outPayload);
388         outPayload = NULL;
389         *size = 0;
390         *payload = NULL;
391         ret = OC_STACK_ERROR;
392     }
393
394     return ret;
395 }
396
397 // This function converts CBOR format to ACL data.
398 // Caller needs to invoke 'free' when done using
399 // note: This function is used in unit test hence not declared static,
400 OicSecAcl_t* CBORPayloadToAcl(const uint8_t *cborPayload, const size_t size)
401 {
402     if (NULL == cborPayload || 0 == size)
403     {
404         return NULL;
405     }
406     OCStackResult ret = OC_STACK_ERROR;
407     CborValue aclCbor = { .parser = NULL };
408     CborParser parser = { .end = NULL };
409     CborError cborFindResult = CborNoError;
410     cbor_parser_init(cborPayload, size, 0, &parser, &aclCbor);
411
412     OicSecAcl_t *headAcl = (OicSecAcl_t *) OICCalloc(1, sizeof(OicSecAcl_t));
413
414     // Enter ACL Map
415     CborValue aclMap = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
416     cborFindResult = cbor_value_enter_container(&aclCbor, &aclMap);
417     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering ACL Map.");
418
419     while (cbor_value_is_valid(&aclMap))
420     {
421         char* tagName = NULL;
422         size_t len = 0;
423         CborType type = cbor_value_get_type(&aclMap);
424         if (type == CborTextStringType)
425         {
426             cborFindResult = cbor_value_dup_text_string(&aclMap, &tagName, &len, NULL);
427             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Name in ACL Map.");
428             cborFindResult = cbor_value_advance(&aclMap);
429             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Value in ACL Map.");
430         }
431         if(tagName)
432         {
433             if (strcmp(tagName, OIC_JSON_ACLIST_NAME)  == 0)
434             {
435                 // Enter ACLIST Map
436                 CborValue aclistMap = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
437                 cborFindResult = cbor_value_enter_container(&aclMap, &aclistMap);
438                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering ACLIST Map.");
439
440
441                 while (cbor_value_is_valid(&aclistMap))
442                 {
443                     char* acName = NULL;
444                     size_t acLen = 0;
445                     CborType acType = cbor_value_get_type(&aclistMap);
446                     if (acType == CborTextStringType)
447                     {
448                         cborFindResult = cbor_value_dup_text_string(&aclistMap, &acName, &acLen, NULL);
449                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Name in ACLIST Map.");
450                         cborFindResult = cbor_value_advance(&aclistMap);
451                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Value in ACLIST Map.");
452                     }
453                     if(acName)
454                     {
455                         if (strcmp(acName, OIC_JSON_ACES_NAME)  == 0)
456                         {
457
458                             // Enter ACES Array
459                             CborValue aclArray = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
460                             cborFindResult = cbor_value_enter_container(&aclistMap, &aclArray);
461                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering ACL Array.");
462
463                             int acesCount = 0;
464                             while (cbor_value_is_valid(&aclArray))
465                             {
466                                 acesCount++;
467
468                                 CborValue aclMap = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
469                                 cborFindResult = cbor_value_enter_container(&aclArray, &aclMap);
470                                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering ACL Map.");
471                                 OicSecAcl_t *acl = NULL;
472
473                                 if(acesCount == 1)
474                                 {
475                                     acl = headAcl;
476                                 }
477                                 else
478                                 {
479                                     acl = (OicSecAcl_t *) OICCalloc(1, sizeof(OicSecAcl_t));
480                                     OicSecAcl_t *temp = headAcl;
481                                     while (temp->next)
482                                     {
483                                         temp = temp->next;
484                                     }
485                                     temp->next = acl;
486                                 }
487                                 VERIFY_NON_NULL(TAG, acl, ERROR);
488
489                                 while (cbor_value_is_valid(&aclMap))
490                                 {
491                                     char* name = NULL;
492                                     size_t len = 0;
493                                     CborType type = cbor_value_get_type(&aclMap);
494                                     if (type == CborTextStringType)
495                                     {
496                                         cborFindResult = cbor_value_dup_text_string(&aclMap, &name, &len, NULL);
497                                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Name in ACL Map.");
498                                         cborFindResult = cbor_value_advance(&aclMap);
499                                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Value in ACL Map.");
500                                     }
501                                     if (name)
502                                     {
503                                         // Subject -- Mandatory
504                                         if (strcmp(name, OIC_JSON_SUBJECTID_NAME)  == 0)
505                                         {
506                                             char *subject = NULL;
507                                             cborFindResult = cbor_value_dup_text_string(&aclMap, &subject, &len, NULL);
508                                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding subject Value.");
509                                             if(strcmp(subject, WILDCARD_RESOURCE_URI) == 0)
510                                             {
511                                                 acl->subject.id[0] = '*';
512                                             }
513                                             else
514                                             {
515                                                 ret = ConvertStrToUuid(subject, &acl->subject);
516                                                 VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
517                                             }
518                                             OICFree(subject);
519                                         }
520
521                                         // Resources -- Mandatory
522                                         if (strcmp(name, OIC_JSON_RESOURCES_NAME) == 0)
523                                         {
524                                             CborValue resources = { .parser = NULL };
525                                             cborFindResult = cbor_value_get_array_length(&aclMap, &acl->resourcesLen);
526                                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a Resource Array Len Value.");
527                                             cborFindResult = cbor_value_enter_container(&aclMap, &resources);
528                                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering a Resource Array.");
529
530                                             acl->resources = (char **) OICMalloc(acl->resourcesLen * sizeof(char*));
531                                             VERIFY_NON_NULL(TAG, acl->resources, ERROR);
532                                             int i = 0;
533                                             while (cbor_value_is_valid(&resources))
534                                             {
535                                                 // rMap
536                                                 CborValue rMap = { .parser = NULL  };
537                                                 cborFindResult = cbor_value_enter_container(&resources, &rMap);
538                                                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering Resource Map");
539
540
541                                                 while(cbor_value_is_valid(&rMap))
542                                                 {
543                                                     char *rMapName = NULL;
544                                                     size_t rMapNameLen = 0;
545                                                     cborFindResult = cbor_value_dup_text_string(&rMap, &rMapName, &rMapNameLen, NULL);
546                                                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding RMap Data Name Tag.");
547                                                     cborFindResult = cbor_value_advance(&rMap);
548                                                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding RMap Data Value.");
549
550                                                     // "href"
551                                                     if (0 == strcmp(OIC_JSON_HREF_NAME, rMapName))
552                                                     {
553                                                         // TODO : Need to check data structure of OicSecAcl_t based on RAML spec.
554                                                         cborFindResult = cbor_value_dup_text_string(&rMap, &acl->resources[i++], &len, NULL);
555                                                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Href Value.");
556                                                     }
557                                                     // "rel"
558                                                     if (0 == strcmp(OIC_JSON_REL_NAME, rMapName))
559                                                     {
560                                                         // TODO : Need to check data structure of OicSecAcl_t based on RAML spec.
561                                                         char *relData = NULL;
562                                                         cborFindResult = cbor_value_dup_text_string(&rMap, &relData, &len, NULL);
563                                                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding REL Value.");
564                                                         OICFree(relData);
565                                                     }
566                                                     // "rt"
567                                                     if (0 == strcmp(OIC_JSON_RT_NAME, rMapName))
568                                                     {
569                                                         // TODO : Need to check data structure of OicSecAcl_t and assign based on RAML spec.
570                                                         char *rtData = NULL;
571                                                         cborFindResult = cbor_value_dup_text_string(&rMap, &rtData, &len, NULL);
572                                                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding RT Value.");
573                                                         OICFree(rtData);
574                                                     }
575
576                                                     // "if"
577                                                     if (0 == strcmp(OIC_JSON_IF_NAME, rMapName))
578                                                     {
579                                                         // TODO : Need to check data structure of OicSecAcl_t and assign based on RAML spec.
580                                                         char *ifData = NULL;
581                                                         cborFindResult = cbor_value_dup_text_string(&rMap, &ifData, &len, NULL);
582                                                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding IF Value.");
583                                                         OICFree(ifData);
584                                                     }
585
586                                                     if (cbor_value_is_valid(&rMap))
587                                                     {
588                                                         cborFindResult = cbor_value_advance(&rMap);
589                                                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Rlist Map.");
590                                                     }
591                                                     OICFree(rMapName);
592                                                 }
593
594                                                 if (cbor_value_is_valid(&resources))
595                                                 {
596                                                     cborFindResult = cbor_value_advance(&resources);
597                                                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Resource Array.");
598                                                 }
599                                             }
600                                         }
601
602                                         // Permissions -- Mandatory
603                                         if (strcmp(name, OIC_JSON_PERMISSION_NAME) == 0)
604                                         {
605                                             cborFindResult = cbor_value_get_uint64(&aclMap, (uint64_t *) &acl->permission);
606                                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a PERM Value.");
607                                         }
608
609                                         // Period -- Not mandatory
610                                         if (strcmp(name, OIC_JSON_PERIOD_NAME) == 0)
611                                         {
612                                             CborValue period = { .parser = NULL };
613                                             cborFindResult = cbor_value_get_array_length(&aclMap, &acl->prdRecrLen);
614                                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a Period Array Len.");
615                                             cborFindResult = cbor_value_enter_container(&aclMap, &period);
616                                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a Period Array Map.");
617                                             acl->periods = (char**)OICCalloc(acl->prdRecrLen, sizeof(char*));
618                                             VERIFY_NON_NULL(TAG, acl->periods, ERROR);
619                                             int i = 0;
620                                             while (cbor_value_is_text_string(&period))
621                                             {
622                                                 cborFindResult = cbor_value_dup_text_string(&period, &acl->periods[i++],
623                                                     &len, NULL);
624                                                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a Period Array Value.");
625                                                 cborFindResult = cbor_value_advance(&period);
626                                                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing a Period Array.");
627                                             }
628                                         }
629
630                                         // Recurrence -- Not mandatory
631                                         if (strcmp(name, OIC_JSON_RECURRENCES_NAME) == 0)
632                                         {
633                                             CborValue recurrences = { .parser = NULL };
634                                             cborFindResult = cbor_value_enter_container(&aclMap, &recurrences);
635                                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Adding Recurrence Array.");
636                                             acl->recurrences = (char**)OICCalloc(acl->prdRecrLen, sizeof(char*));
637                                             VERIFY_NON_NULL(TAG, acl->recurrences, ERROR);
638                                             int i = 0;
639                                             while (cbor_value_is_text_string(&recurrences))
640                                             {
641                                                 cborFindResult = cbor_value_dup_text_string(&recurrences,
642                                                     &acl->recurrences[i++], &len, NULL);
643                                                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Adding Recurrence Array Value.");
644                                                 cborFindResult = cbor_value_advance(&recurrences);
645                                                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Closing Recurrence Array.");
646                                             }
647                                         }
648
649                                         OICFree(name);
650                                     }
651
652                                     if (type != CborMapType && cbor_value_is_valid(&aclMap))
653                                     {
654                                         cborFindResult = cbor_value_advance(&aclMap);
655                                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing the Array.");
656                                     }
657                                 }
658
659                                 acl->next = NULL;
660
661                                 if (cbor_value_is_valid(&aclArray))
662                                 {
663                                     cborFindResult = cbor_value_advance(&aclArray);
664                                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing ACL Array.");
665                                 }
666                             }
667                         }
668                         OICFree(acName);
669                     }
670
671                     if (cbor_value_is_valid(&aclistMap))
672                     {
673                         cborFindResult = cbor_value_advance(&aclistMap);
674                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing ACLIST Map.");
675                     }
676                 }
677             }
678
679             // TODO : Need to modify headAcl->owners[0].id to headAcl->rowner based on RAML spec.
680             if (strcmp(tagName, OIC_JSON_ROWNERID_NAME)  == 0)
681             {
682                 char *stRowner = NULL;
683                 cborFindResult = cbor_value_dup_text_string(&aclMap, &stRowner, &len, NULL);
684                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Rownerid Value.");
685                 ret = ConvertStrToUuid(stRowner, &headAcl->rownerID);
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_SUBJECTID_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     if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, payload, size))
954     {
955         ehRet = OC_EH_ERROR;
956         OIC_LOG(ERROR, TAG, "SendSRMResponse failed for HandleACLGetRequest");
957     }
958     OICFree(payload);
959
960     OIC_LOG_V(DEBUG, TAG, "%s RetVal %d", __func__, ehRet);
961     return ehRet;
962 }
963
964 static OCEntityHandlerResult HandleACLPostRequest(const OCEntityHandlerRequest *ehRequest)
965 {
966     OIC_LOG(INFO, TAG, "HandleACLPostRequest processing the request");
967     OCEntityHandlerResult ehRet = OC_EH_ERROR;
968
969     // Convert CBOR into ACL data and update to SVR buffers. This will also validate the ACL data received.
970     uint8_t *payload = ((OCSecurityPayload *) ehRequest->payload)->securityData;
971     size_t size = ((OCSecurityPayload *) ehRequest->payload)->payloadSize;
972     if (payload)
973     {
974         OicSecAcl_t *newAcl = CBORPayloadToAcl(payload, size);
975         if (newAcl)
976         {
977             // Append the new ACL to existing ACL
978             LL_APPEND(gAcl, newAcl);
979             size_t size = 0;
980             // In case of unit test do not update persistant storage.
981             if (memcmp(newAcl->subject.id, &WILDCARD_SUBJECT_ID, sizeof(newAcl->subject.id)) == 0
982                 || memcmp(newAcl->subject.id, &WILDCARD_SUBJECT_B64_ID, sizeof(newAcl->subject.id)) == 0)
983             {
984                 ehRet = OC_EH_RESOURCE_CREATED;
985             }
986             else
987             {
988                 uint8_t *cborPayload = NULL;
989                 if (OC_STACK_OK == AclToCBORPayload(gAcl, &cborPayload, &size))
990                 {
991                     if (UpdateSecureResourceInPS(OIC_JSON_ACL_NAME, cborPayload, size) == OC_STACK_OK)
992                     {
993                         ehRet = OC_EH_RESOURCE_CREATED;
994                     }
995                     OICFree(cborPayload);
996                 }
997             }
998         }
999     }
1000
1001     // Send payload to request originator
1002     if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL, 0))
1003     {
1004         ehRet = OC_EH_ERROR;
1005         OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandleACLPostRequest");
1006     }
1007
1008     OIC_LOG_V(DEBUG, TAG, "%s RetVal %d", __func__, ehRet);
1009     return ehRet;
1010 }
1011
1012 static OCEntityHandlerResult HandleACLDeleteRequest(const OCEntityHandlerRequest *ehRequest)
1013 {
1014     OIC_LOG(DEBUG, TAG, "Processing ACLDeleteRequest");
1015     OCEntityHandlerResult ehRet = OC_EH_ERROR;
1016     OicUuid_t subject = { .id= { 0 } };
1017     char resource[MAX_URI_LENGTH] = { 0 };
1018
1019     VERIFY_NON_NULL(TAG, ehRequest->query, ERROR);
1020
1021     // 'Subject' field is MUST for processing a querystring in REST request.
1022     VERIFY_SUCCESS(TAG, true == GetSubjectFromQueryString(ehRequest->query, &subject), ERROR);
1023
1024     GetResourceFromQueryString(ehRequest->query, resource, sizeof(resource));
1025
1026     if (OC_STACK_RESOURCE_DELETED == RemoveACE(&subject, resource))
1027     {
1028         ehRet = OC_EH_RESOURCE_DELETED;
1029     }
1030
1031 exit:
1032     // Send payload to request originator
1033     if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL, 0))
1034     {
1035         ehRet = OC_EH_ERROR;
1036         OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandleACLDeleteRequest");
1037     }
1038
1039     return ehRet;
1040 }
1041
1042 OCEntityHandlerResult ACLEntityHandler(OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehRequest,
1043         void* callbackParameter)
1044 {
1045     OIC_LOG(DEBUG, TAG, "Received request ACLEntityHandler");
1046     (void)callbackParameter;
1047     OCEntityHandlerResult ehRet = OC_EH_ERROR;
1048
1049     if (!ehRequest)
1050     {
1051         return ehRet;
1052     }
1053
1054     if (flag & OC_REQUEST_FLAG)
1055     {
1056         // TODO :  Handle PUT method
1057         OIC_LOG(DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
1058         switch (ehRequest->method)
1059         {
1060             case OC_REST_GET:
1061                 ehRet = HandleACLGetRequest(ehRequest);
1062                 break;
1063
1064             case OC_REST_POST:
1065                 ehRet = HandleACLPostRequest(ehRequest);
1066                 break;
1067
1068             case OC_REST_DELETE:
1069                 ehRet = HandleACLDeleteRequest(ehRequest);
1070                 break;
1071
1072             default:
1073                 ehRet = OC_EH_ERROR;
1074                 SendSRMResponse(ehRequest, ehRet, NULL, 0);
1075         }
1076     }
1077
1078     return ehRet;
1079 }
1080
1081 /**
1082  * This internal method is used to create '/oic/sec/acl' resource.
1083  */
1084 static OCStackResult CreateACLResource()
1085 {
1086     OCStackResult ret;
1087
1088     ret = OCCreateResource(&gAclHandle,
1089                            OIC_RSRC_TYPE_SEC_ACL,
1090                            OIC_MI_DEF,
1091                            OIC_RSRC_ACL_URI,
1092                            ACLEntityHandler,
1093                            NULL,
1094                            OC_OBSERVABLE | OC_SECURE | OC_EXPLICIT_DISCOVERABLE);
1095
1096     if (OC_STACK_OK != ret)
1097     {
1098         OIC_LOG(FATAL, TAG, "Unable to instantiate ACL resource");
1099         DeInitACLResource();
1100     }
1101     return ret;
1102 }
1103
1104 // This function sets the default ACL and is defined for the unit test only.
1105 OCStackResult SetDefaultACL(OicSecAcl_t *acl)
1106 {
1107     gAcl = acl;
1108     return OC_STACK_OK;
1109 }
1110
1111 OCStackResult GetDefaultACL(OicSecAcl_t** defaultAcl)
1112 {
1113     OCStackResult ret = OC_STACK_ERROR;
1114
1115     OicUuid_t ownerId = { .id = { 0 } };
1116
1117     /*
1118      * TODO In future, when new virtual resources will be added in OIC
1119      * specification, Iotivity stack should be able to add them in
1120      * existing SVR database. To support this, we need to add 'versioning'
1121      * mechanism in SVR database.
1122      */
1123
1124     const char *rsrcs[] = {
1125         OC_RSRVD_WELL_KNOWN_URI,
1126         OC_RSRVD_DEVICE_URI,
1127         OC_RSRVD_PLATFORM_URI,
1128         OC_RSRVD_RESOURCE_TYPES_URI,
1129 #ifdef WITH_PRESENCE
1130         OC_RSRVD_PRESENCE_URI,
1131 #endif //WITH_PRESENCE
1132         OIC_RSRC_ACL_URI,
1133         OIC_RSRC_DOXM_URI,
1134         OIC_RSRC_PSTAT_URI,
1135     };
1136
1137     if (!defaultAcl)
1138     {
1139         return OC_STACK_INVALID_PARAM;
1140     }
1141
1142     OicSecAcl_t *acl = (OicSecAcl_t *) OICCalloc(1, sizeof(OicSecAcl_t));
1143     VERIFY_NON_NULL(TAG, acl, ERROR);
1144
1145     // Subject -- Mandatory
1146     memcpy(&(acl->subject), &WILDCARD_SUBJECT_ID, sizeof(acl->subject));
1147
1148     // Resources -- Mandatory
1149     acl->resourcesLen = sizeof(rsrcs) / sizeof(rsrcs[0]);
1150
1151     acl->resources = (char**) OICCalloc(acl->resourcesLen, sizeof(char*));
1152     VERIFY_NON_NULL(TAG, (acl->resources), ERROR);
1153
1154     for (size_t i = 0; i < acl->resourcesLen; i++)
1155     {
1156         size_t len = strlen(rsrcs[i]) + 1;
1157         acl->resources[i] = (char*) OICMalloc(len * sizeof(char));
1158         VERIFY_NON_NULL(TAG, (acl->resources[i]), ERROR);
1159         OICStrcpy(acl->resources[i], len, rsrcs[i]);
1160     }
1161
1162     acl->permission = PERMISSION_READ;
1163     acl->prdRecrLen = 0;
1164     acl->periods = NULL;
1165     acl->recurrences = NULL;
1166
1167     // Device ID is the owner of this default ACL
1168     if (GetDoxmResourceData() != NULL)
1169     {
1170         ret = GetDoxmDeviceID(&ownerId);
1171         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, FATAL);
1172     }
1173     else
1174     {
1175         OCRandomUuidResult rdm = OCGenerateUuid(ownerId.id);
1176         VERIFY_SUCCESS(TAG, RAND_UUID_OK == rdm, FATAL);
1177     }
1178
1179     memcpy(&acl->rownerID, &ownerId, sizeof(OicUuid_t));
1180
1181     acl->next = NULL;
1182
1183     *defaultAcl = acl;
1184     ret = OC_STACK_OK;
1185
1186 exit:
1187
1188     if (ret != OC_STACK_OK)
1189     {
1190         DeleteACLList(acl);
1191         acl = NULL;
1192     }
1193
1194     return ret;
1195 }
1196
1197 OCStackResult InitACLResource()
1198 {
1199     OCStackResult ret = OC_STACK_ERROR;
1200
1201     uint8_t *data = NULL;
1202     size_t size = 0;
1203     ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_ACL_NAME, &data, &size);
1204     // If database read failed
1205     if (ret != OC_STACK_OK)
1206     {
1207         OIC_LOG(DEBUG, TAG, "ReadSVDataFromPS failed");
1208     }
1209     if (data)
1210     {
1211         // Read ACL resource from PS
1212         gAcl = CBORPayloadToAcl(data, size);
1213     }
1214     /*
1215      * If SVR database in persistent storage got corrupted or
1216      * is not available for some reason, a default ACL is created
1217      * which allows user to initiate ACL provisioning again.
1218      */
1219     if (!gAcl)
1220     {
1221         GetDefaultACL(&gAcl);
1222         // TODO Needs to update persistent storage
1223     }
1224     VERIFY_NON_NULL(TAG, gAcl, FATAL);
1225
1226     // Instantiate 'oic.sec.acl'
1227     ret = CreateACLResource();
1228
1229 exit:
1230     if (OC_STACK_OK != ret)
1231     {
1232         DeInitACLResource();
1233     }
1234     return ret;
1235 }
1236
1237 OCStackResult DeInitACLResource()
1238 {
1239     OCStackResult ret =  OCDeleteResource(gAclHandle);
1240     gAclHandle = NULL;
1241
1242     if (gAcl)
1243     {
1244         DeleteACLList(gAcl);
1245         gAcl = NULL;
1246     }
1247     return ret;
1248 }
1249
1250 const OicSecAcl_t* GetACLResourceData(const OicUuid_t* subjectId, OicSecAcl_t **savePtr)
1251 {
1252     OicSecAcl_t *acl = NULL;
1253     OicSecAcl_t *begin = NULL;
1254
1255     if (NULL == subjectId)
1256     {
1257         return NULL;
1258     }
1259
1260     /*
1261      * savePtr MUST point to NULL if this is the 'first' call to retrieve ACL for
1262      * subjectID.
1263      */
1264     if (NULL == *savePtr)
1265     {
1266         begin = gAcl;
1267     }
1268     else
1269     {
1270         /*
1271          * If this is a 'successive' call, search for location pointed by
1272          * savePtr and assign 'begin' to the next ACL after it in the linked
1273          * list and start searching from there.
1274          */
1275         LL_FOREACH(gAcl, acl)
1276         {
1277             if (acl == *savePtr)
1278             {
1279                 begin = acl->next;
1280             }
1281         }
1282     }
1283
1284     // Find the next ACL corresponding to the 'subjectID' and return it.
1285     LL_FOREACH(begin, acl)
1286     {
1287         if (memcmp(&(acl->subject), subjectId, sizeof(OicUuid_t)) == 0)
1288         {
1289             *savePtr = acl;
1290             return acl;
1291         }
1292     }
1293
1294     // Cleanup in case no ACL is found
1295     *savePtr = NULL;
1296     return NULL;
1297 }
1298
1299 OCStackResult InstallNewACL(const uint8_t *cborPayload, const size_t size)
1300 {
1301     OCStackResult ret = OC_STACK_ERROR;
1302
1303     // Convert CBOR format to ACL data. This will also validate the ACL data received.
1304     OicSecAcl_t* newAcl = CBORPayloadToAcl(cborPayload, size);
1305
1306     if (newAcl)
1307     {
1308         // Append the new ACL to existing ACL
1309         LL_APPEND(gAcl, newAcl);
1310
1311         // Update persistent storage only if it is not WILDCARD_SUBJECT_ID
1312         if (memcmp(newAcl->subject.id, &WILDCARD_SUBJECT_ID, sizeof(newAcl->subject.id)) == 0
1313             || memcmp(newAcl->subject.id, &WILDCARD_SUBJECT_B64_ID, sizeof(newAcl->subject.id)) == 0)
1314         {
1315             ret = OC_STACK_OK;
1316         }
1317         else
1318         {
1319             size_t size = 0;
1320             uint8_t *payload = NULL;
1321             if (OC_STACK_OK == AclToCBORPayload(gAcl, &payload, &size))
1322             {
1323                 if (UpdateSecureResourceInPS(OIC_JSON_ACL_NAME, payload, size) == OC_STACK_OK)
1324                 {
1325                     ret = OC_STACK_OK;
1326                 }
1327                 OICFree(payload);
1328             }
1329         }
1330     }
1331
1332     return ret;
1333 }
1334
1335 /**
1336  * This function generates default ACL for security resource in case of owned status.
1337  *
1338  * @return Default ACL for security resource.
1339  */
1340 static OicSecAcl_t* GetSecDefaultACL()
1341 {
1342     const char *sec_rsrcs[] = {
1343         OIC_RSRC_DOXM_URI,
1344         OIC_RSRC_PSTAT_URI
1345     };
1346     OicUuid_t ownerId = {.id = {0}};
1347     OCStackResult res = OC_STACK_ERROR;
1348     OicSecAcl_t* newDefaultAcl = (OicSecAcl_t*)OICCalloc(1, sizeof(OicSecAcl_t));
1349     VERIFY_NON_NULL(TAG, newDefaultAcl, ERROR);
1350
1351     // Subject -- Mandatory
1352     memcpy(&(newDefaultAcl->subject), &WILDCARD_SUBJECT_ID, WILDCARD_SUBJECT_ID_LEN);
1353
1354     // Resources -- Mandatory
1355     newDefaultAcl->resourcesLen = NUMBER_OF_DEFAULT_SEC_RSCS;
1356     newDefaultAcl->resources = (char**)OICCalloc(NUMBER_OF_DEFAULT_SEC_RSCS, sizeof(char*));
1357     VERIFY_NON_NULL(TAG, (newDefaultAcl->resources), ERROR);
1358
1359     for (size_t i = 0; i <  NUMBER_OF_DEFAULT_SEC_RSCS; i++)
1360     {
1361         size_t len = strlen(sec_rsrcs[i]) + 1;
1362         newDefaultAcl->resources[i] = (char*)OICMalloc(len * sizeof(char));
1363         VERIFY_NON_NULL(TAG, (newDefaultAcl->resources[i]), ERROR);
1364         OICStrcpy(newDefaultAcl->resources[i], len, sec_rsrcs[i]);
1365     }
1366
1367     // Permissions -- Mandatory
1368     newDefaultAcl->permission = PERMISSION_READ;
1369
1370     //Period -- Not Mandatory
1371     newDefaultAcl->prdRecrLen = 0;
1372     newDefaultAcl->periods = NULL;
1373
1374     //Recurrence -- Not Mandatory
1375     newDefaultAcl->recurrences = NULL;
1376
1377     // Device ID is the owner of this default ACL
1378     res = GetDoxmDeviceID(&ownerId);
1379     VERIFY_SUCCESS(TAG, OC_STACK_OK == res, FATAL);
1380
1381     // Owners -- Mandatory
1382     memcpy(&newDefaultAcl->rownerID, &ownerId, sizeof(OicUuid_t));
1383
1384     return newDefaultAcl;
1385 exit:
1386     DeleteACLList(newDefaultAcl);
1387     return NULL;
1388
1389 }
1390
1391 OCStackResult UpdateDefaultSecProvACL()
1392 {
1393     OCStackResult ret = OC_STACK_OK;
1394     OicSecAcl_t *acl = NULL;
1395     OicSecAcl_t *tmp = NULL;
1396
1397     if(gAcl)
1398     {
1399         int matchedRsrc = 0;
1400         bool isRemoved = false;
1401
1402         LL_FOREACH_SAFE(gAcl, acl, tmp)
1403         {
1404             //Find default security resource ACL
1405             if(memcmp(&acl->subject, &WILDCARD_SUBJECT_ID, sizeof(OicUuid_t)) == 0 &&
1406                 ((PERMISSION_READ | PERMISSION_WRITE) == acl->permission))
1407             {
1408                 matchedRsrc = 0;
1409
1410                 for(size_t i = 0; i < acl->resourcesLen; i++)
1411                 {
1412                     if(strncmp(acl->resources[i], OIC_RSRC_DOXM_URI,
1413                                strlen(OIC_RSRC_DOXM_URI) + 1) == 0 ||
1414                        strncmp(acl->resources[i], OIC_RSRC_CRED_URI,
1415                                strlen(OIC_RSRC_CRED_URI) + 1) == 0 ||
1416                        strncmp(acl->resources[i], OIC_RSRC_ACL_URI,
1417                                strlen(OIC_RSRC_ACL_URI) + 1) == 0 ||
1418                        strncmp(acl->resources[i], OIC_RSRC_PSTAT_URI,
1419                                strlen(OIC_RSRC_PSTAT_URI) + 1) == 0)
1420                     {
1421                         matchedRsrc++;
1422                     }
1423                 }
1424
1425                 //If default security resource ACL is detected, delete it.
1426                 if(NUMBER_OF_SEC_PROV_RSCS == matchedRsrc)
1427                 {
1428                     LL_DELETE(gAcl, acl);
1429                     FreeACE(acl);
1430                     isRemoved = true;
1431                 }
1432             }
1433         }
1434
1435         if(isRemoved)
1436         {
1437             /*
1438              * Generate new security resource ACL as follows :
1439              *      subject : "*"
1440              *      resources :  '/oic/sec/doxm', '/oic/sec/pstat'
1441              *      permission : READ
1442              */
1443             OicSecAcl_t *newDefaultAcl = GetSecDefaultACL();
1444             if (newDefaultAcl)
1445             {
1446                 LL_APPEND(gAcl, newDefaultAcl);
1447
1448                 size_t size = 0;
1449                 uint8_t *payload = NULL;
1450                 if (OC_STACK_OK == AclToCBORPayload(gAcl, &payload, &size))
1451                 {
1452                     if (UpdateSecureResourceInPS(OIC_JSON_ACL_NAME, payload, size) == OC_STACK_OK)
1453                     {
1454                         ret = OC_STACK_OK;
1455                     }
1456                     OICFree(payload);
1457                 }
1458             }
1459         }
1460     }
1461
1462     return ret;
1463 }
1464
1465 OCStackResult SetAclRownerId(const OicUuid_t* newROwner)
1466 {
1467     OCStackResult ret = OC_STACK_ERROR;
1468     uint8_t *cborPayload = NULL;
1469     size_t size = 0;
1470     OicUuid_t prevId = {.id={0}};
1471
1472     if(NULL == newROwner)
1473     {
1474         ret = OC_STACK_INVALID_PARAM;
1475     }
1476     if(NULL == gAcl)
1477     {
1478         ret = OC_STACK_NO_RESOURCE;
1479     }
1480
1481     if(newROwner && gAcl)
1482     {
1483         memcpy(prevId.id, gAcl->rownerID.id, sizeof(prevId.id));
1484         memcpy(gAcl->rownerID.id, newROwner->id, sizeof(newROwner->id));
1485
1486         ret = AclToCBORPayload(gAcl, &cborPayload, &size);
1487         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
1488
1489         ret = UpdateSecureResourceInPS(OIC_JSON_ACL_NAME, cborPayload, size);
1490         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
1491
1492         OICFree(cborPayload);
1493     }
1494
1495     return ret;
1496
1497 exit:
1498     OICFree(cborPayload);
1499     memcpy(gAcl->rownerID.id, prevId.id, sizeof(prevId.id));
1500     return ret;
1501 }
1502
1503 OCStackResult GetAclRownerId(OicUuid_t *rowneruuid)
1504 {
1505     OCStackResult retVal = OC_STACK_ERROR;
1506     if (gAcl)
1507     {
1508         *rowneruuid = gAcl->rownerID;
1509         retVal = OC_STACK_OK;
1510     }
1511     return retVal;
1512 }