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