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