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