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