RAML v1.1 sync-up in SVR DB
[platform/upstream/iotivity.git] / resource / csdk / security / src / amaclresource.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 #include <stdlib.h>
22 #include <string.h>
23 #include "oic_malloc.h"
24 #include "ocpayload.h"
25 #include "payload_logging.h"
26 #include "psinterface.h"
27 #include "resourcemanager.h"
28 #include "utlist.h"
29 #include "srmresourcestrings.h"
30 #include "srmutility.h"
31 #include "amaclresource.h"
32
33 #define TAG  "SRM-AMACL"
34
35 /** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
36  * The value of payload size is increased until reaching belox max cbor size. */
37 static const uint16_t CBOR_SIZE = 1024;
38
39 /* Max cbor size payload. */
40 static const uint16_t CBOR_MAX_SIZE = 4400;
41
42 /** AMACL Map size - Number of mandatory items. */
43 static const uint8_t AMACL_MAP_SIZE = 3;
44 static const uint8_t AMACL_RSRC_MAP_SIZE = 1;
45 static const uint8_t AMACL_RLIST_MAP_SIZE = 3;
46
47 static OicSecAmacl_t *gAmacl = NULL;
48 static OCResourceHandle gAmaclHandle = NULL;
49
50 void DeleteAmaclList(OicSecAmacl_t* amacl)
51 {
52     if (amacl)
53     {
54         OicSecAmacl_t *amaclTmp1 = NULL, *amaclTmp2 = NULL;
55         LL_FOREACH_SAFE(amacl, amaclTmp1, amaclTmp2)
56         {
57             LL_DELETE(amacl, amaclTmp1);
58
59             // Clean Resources
60             for (size_t i = 0; i < amaclTmp1->resourcesLen; i++)
61             {
62                 OICFree(amaclTmp1->resources[i]);
63             }
64             OICFree(amaclTmp1->resources);
65
66             // Clean Amss
67             OICFree(amaclTmp1->amss);
68
69             // Clean Owners
70             OICFree(amaclTmp1->owners);
71
72             // Clean Amacl node itself
73             OICFree(amaclTmp1);
74         }
75     }
76 }
77
78 static size_t OicSecAmaclCount(const OicSecAmacl_t *secAmacl)
79 {
80     size_t size = 0;
81     for (const OicSecAmacl_t *amacl = secAmacl; amacl; amacl = amacl->next)
82     {
83         size++;
84     }
85     return size;
86 }
87
88 OCStackResult AmaclToCBORPayload(const OicSecAmacl_t *amaclS, uint8_t **cborPayload,
89                                  size_t *cborSize)
90 {
91     if (NULL == amaclS || NULL == cborPayload || NULL != *cborPayload || NULL == cborSize)
92     {
93         return OC_STACK_INVALID_PARAM;
94     }
95
96     OCStackResult ret = OC_STACK_ERROR;
97     size_t cborLen = *cborSize;
98     if (0 == cborLen)
99     {
100         cborLen = CBOR_SIZE;
101     }
102
103     *cborSize = 0;
104     *cborPayload = NULL;
105
106     CborEncoder encoder = { {.ptr = NULL }, .end = 0 };
107     CborEncoder amaclMap = { {.ptr = NULL }, .end = 0 };
108     int64_t cborEncoderResult = CborNoError;
109     CborEncoder rsrcMap = { {.ptr = NULL }, .end = 0 };
110     CborEncoder rlistArray = { {.ptr = NULL }, .end = 0 };
111     CborEncoder amss = { {.ptr = NULL }, .end = 0 };
112     char *stRowner = NULL;
113
114     const OicSecAmacl_t *amacl = amaclS;
115     uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
116     VERIFY_NON_NULL(TAG, outPayload, ERROR);
117     cbor_encoder_init(&encoder, outPayload, cborLen, 0);
118
119     // Create AMACL Map
120     cborEncoderResult = cbor_encoder_create_map(&encoder, &amaclMap, AMACL_MAP_SIZE);
121     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding AMACL Map.");
122
123     // resources -- Mandatory
124     cborEncoderResult = cbor_encode_text_string(&amaclMap, OIC_JSON_RESOURCES_NAME,
125                 strlen(OIC_JSON_RESOURCES_NAME));
126     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Resource Name Tag.");
127
128     cborEncoderResult = cbor_encoder_create_map(&amaclMap, &rsrcMap, AMACL_RSRC_MAP_SIZE);
129     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Resource Map.");
130
131
132     cborEncoderResult = cbor_encode_text_string(&rsrcMap, OIC_JSON_RLIST_NAME,
133                 strlen(OIC_JSON_RLIST_NAME));
134     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RLIST Name Tag.");
135
136     // TODO : Need to input array length by OicSecAmacl_t->resources->rlistLen based on spec.
137     cborEncoderResult = cbor_encoder_create_array(&rsrcMap, &rlistArray, amacl->resourcesLen);
138     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RLIST Array.");
139
140     // TODO : Need to add OicSecAmacl_t->rlist as array rMap based on RAML spec.
141     for (size_t i = 0; i < amacl->resourcesLen; i++)
142     {
143         // TODO : Need to create rMap structure based on RAML spec.
144         CborEncoder rMap = { {.ptr = NULL }, .end = 0 };
145         cborEncoderResult = cbor_encoder_create_map(&rlistArray, &rMap, AMACL_RLIST_MAP_SIZE);
146         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RLIST Map.");
147
148         cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_HREF_NAME,
149                 strlen(OIC_JSON_HREF_NAME));
150         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding HREF Name Tag.");
151         cborEncoderResult = cbor_encode_text_string(&rMap, amacl->resources[i],
152                 strlen(amacl->resources[i]));
153         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding HREF Value in Map.");
154
155         cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_RT_NAME,
156                 strlen(OIC_JSON_RT_NAME));
157         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Name Tag.");
158
159         // TODO : Need to assign real value of RT
160         cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_EMPTY_STRING,
161                 strlen(OIC_JSON_EMPTY_STRING));
162         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Value.");
163
164         cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_IF_NAME,
165                 strlen(OIC_JSON_IF_NAME));
166         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Name Tag.");
167
168         // TODO : Need to assign real value of IF
169         cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_EMPTY_STRING,
170                 strlen(OIC_JSON_EMPTY_STRING));
171         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Value.");
172
173         cborEncoderResult = cbor_encoder_close_container(&rlistArray, &rMap);
174         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing RLIST Array.");
175     }
176
177     cborEncoderResult = cbor_encoder_close_container(&rsrcMap, &rlistArray);
178     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing RLIST Array.");
179
180
181     cborEncoderResult = cbor_encoder_close_container(&amaclMap, &rsrcMap);
182     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Resource Map.");
183
184     // TODO : Need to modify type of OicSecAmacl_t->amss based on RAML spec.
185     // ams -- Mandatory
186     cborEncoderResult = cbor_encode_text_string(&amaclMap, OIC_JSON_AMS_NAME,
187                 strlen(OIC_JSON_AMS_NAME));
188     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding AMSS Name Tag.");
189
190     cborEncoderResult = cbor_encoder_create_array(&amaclMap, &amss, amacl->amssLen);
191     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding AMS Name Array.");
192     for (size_t i = 0; i < amacl->amssLen; i++)
193     {
194         cborEncoderResult = cbor_encode_text_string(&amss, (const char *)amacl->amss[i].id,
195             sizeof(amacl->amss[i].id));
196         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding AMS Name Value.");
197     }
198     cborEncoderResult = cbor_encoder_close_container(&amaclMap, &amss);
199     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing AMSS Array.");
200
201     // TODO : Need to check owner property in the RAML spec.
202     // rowner
203     cborEncoderResult = cbor_encode_text_string(&amaclMap, OIC_JSON_ROWNERID_NAME,
204                 strlen(OIC_JSON_ROWNERID_NAME));
205     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding ROwnerID Name Tag.");
206
207     // TODO : Need to modify amacl->owners[0] to amacl->rownerid based on RAML spec.
208     ret = ConvertUuidToStr(&amacl->owners[0], &stRowner);
209     VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
210     cborEncoderResult = cbor_encode_text_string(&amaclMap, stRowner, strlen(stRowner));
211     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding ROwner Value.");
212     OICFree(stRowner);
213
214     cborEncoderResult = cbor_encoder_close_container(&encoder, &amaclMap);
215     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Amacl Map.");
216
217     if (CborNoError == cborEncoderResult)
218     {
219         *cborPayload = outPayload;
220         *cborSize = encoder.ptr - outPayload;
221         ret = OC_STACK_OK;
222     }
223
224 exit:
225     if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
226     {
227        // reallocate and try again!
228        OICFree(outPayload);
229        outPayload = NULL;
230        // Since the allocated initial memory failed, double the memory.
231        cborLen += encoder.ptr - encoder.end;
232        cborEncoderResult = CborNoError;
233        ret = AmaclToCBORPayload(amaclS, cborPayload, &cborLen);
234        if (OC_STACK_OK == ret)
235        {
236            *cborSize = cborLen;
237            ret = OC_STACK_OK;
238        }
239     }
240
241     if (CborNoError != cborEncoderResult || ret != OC_STACK_OK)
242     {
243        OICFree(outPayload);
244        outPayload = NULL;
245        *cborSize = 0;
246        *cborPayload = NULL;
247        ret = OC_STACK_ERROR;
248     }
249
250     return ret;
251 }
252
253 OCStackResult CBORPayloadToAmacl(const uint8_t *cborPayload, size_t size,
254                                  OicSecAmacl_t **secAmacl)
255 {
256     if (NULL == cborPayload || NULL == secAmacl || NULL != *secAmacl)
257     {
258         return OC_STACK_INVALID_PARAM;
259     }
260
261     *secAmacl = NULL;
262
263     OCStackResult ret = OC_STACK_ERROR;
264
265     CborValue amaclCbor = { .parser = NULL };
266     CborParser parser = { .end = NULL };
267     CborError cborFindResult = CborNoError;
268     int cborLen = size;
269     if (0 == size)
270     {
271         cborLen = CBOR_SIZE;
272     }
273     cbor_parser_init(cborPayload, cborLen, 0, &parser, &amaclCbor);
274
275     OicSecAmacl_t *headAmacl = (OicSecAmacl_t *)OICCalloc(1, sizeof(OicSecAmacl_t));
276
277     CborValue amaclMap = { .parser = NULL };
278     cborFindResult = cbor_value_enter_container(&amaclCbor, &amaclMap);
279     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering Amacl Map.");
280
281     while(cbor_value_is_valid(&amaclMap))
282     {
283         char *name = NULL;
284         size_t len = 0;
285         cborFindResult = cbor_value_dup_text_string(&amaclMap, &name, &len, NULL);
286         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Amacl Data Name Tag.");
287         cborFindResult = cbor_value_advance(&amaclMap);
288         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Amacl Data Value.");
289
290         //CborType type = cbor_value_get_type(&amaclMap);
291
292         // Resources -- Mandatory
293         if (0 == strcmp(OIC_JSON_RESOURCES_NAME, name))
294         {
295             // resource map
296             CborValue rsrcMap = { .parser = NULL  };
297             cborFindResult = cbor_value_enter_container(&amaclMap, &rsrcMap);
298             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering Resource Map");
299
300             while(cbor_value_is_valid(&rsrcMap))
301             {
302                 // resource name
303                 char *rsrcName = NULL;
304                 size_t rsrcNameLen = 0;
305                 cborFindResult = cbor_value_dup_text_string(&rsrcMap, &rsrcName, &rsrcNameLen, NULL);
306                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Resource Data Name Tag.");
307                 cborFindResult = cbor_value_advance(&rsrcMap);
308                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Resource Data Value.");
309
310                 // rlist
311                 if (0 == strcmp(OIC_JSON_RLIST_NAME, rsrcName))
312                 {
313                     int i = 0;
314                     // TODO : Need to assign array length to OicSecAmacl_t->resources->rlistLen based of RAML spec.
315                     cborFindResult = cbor_value_get_array_length(&rsrcMap, &headAmacl->resourcesLen);
316                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Rlist Array Len.");
317
318                     CborValue rsrcArray = { .parser = NULL  };
319
320                     // rlist array
321                     cborFindResult = cbor_value_enter_container(&rsrcMap, &rsrcArray);
322                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering Rlist Array");
323
324                     // TODO : Need to check data structure of OicSecAmacl_t based on RAML spec.
325                     headAmacl->resources = (char **) OICCalloc(headAmacl->resourcesLen, sizeof(*headAmacl->resources));
326                     VERIFY_NON_NULL(TAG, headAmacl->resources, ERROR);
327
328                     while (cbor_value_is_valid(&rsrcArray))
329                     {
330                         // rMap
331                         CborValue rMap = { .parser = NULL  };
332                         cborFindResult = cbor_value_enter_container(&rsrcArray, &rMap);
333                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering Rlist Map");
334
335                         while(cbor_value_is_valid(&rMap))
336                         {
337                             char *rMapName = NULL;
338                             size_t rMapNameLen = 0;
339                             cborFindResult = cbor_value_dup_text_string(&rMap, &rMapName, &rMapNameLen, NULL);
340                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding RMap Data Name Tag.");
341                             cborFindResult = cbor_value_advance(&rMap);
342                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding RMap Data Value.");
343
344                             // "href"
345                             if (0 == strcmp(OIC_JSON_HREF_NAME, rMapName))
346                             {
347                                 // TODO : Need to check data structure of OicSecAmacl_t based on RAML spec.
348                                 cborFindResult = cbor_value_dup_text_string(&rMap, &headAmacl->resources[i++], &len, NULL);
349                                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Href Value.");
350                             }
351
352                             // "rt"
353                             if (0 == strcmp(OIC_JSON_RT_NAME, rMapName))
354                             {
355                                 // TODO : Need to check data structure of OicSecAmacl_t and assign based on RAML spec.
356                                 char *rtData = NULL;
357                                 cborFindResult = cbor_value_dup_text_string(&rMap, &rtData, &len, NULL);
358                                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding RT Value.");
359                                 OICFree(rtData);
360                             }
361
362                             // "if"
363                             if (0 == strcmp(OIC_JSON_IF_NAME, rMapName))
364                             {
365                                 // TODO : Need to check data structure of OicSecAmacl_t and assign based on RAML spec.
366                                 char *ifData = NULL;
367                                 cborFindResult = cbor_value_dup_text_string(&rMap, &ifData, &len, NULL);
368                                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding IF Value.");
369                                 OICFree(ifData);
370                             }
371
372                             if (cbor_value_is_valid(&rMap))
373                             {
374                                 cborFindResult = cbor_value_advance(&rMap);
375                                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Rlist Map.");
376                             }
377                             OICFree(rMapName);
378                         }
379
380                         if (cbor_value_is_valid(&rsrcArray))
381                         {
382                             cborFindResult = cbor_value_advance(&rsrcArray);
383                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Resource Array.");
384                         }
385                     }
386                 }
387
388                 if (cbor_value_is_valid(&rsrcMap))
389                 {
390                     cborFindResult = cbor_value_advance(&rsrcMap);
391                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Resource Map.");
392                 }
393                 OICFree(rsrcName);
394             }
395
396         }
397
398         // TODO : Need to modify type of OicSecAmacl_t->amss based on RAML spec.
399          // Ams -- Mandatory
400         if (0 == strcmp(OIC_JSON_AMS_NAME, name))
401         {
402             int i = 0;
403             CborValue amsArray = { .parser = NULL };
404             cborFindResult = cbor_value_get_array_length(&amaclMap, &headAmacl->amssLen);
405             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding AMS Array Len.");
406             cborFindResult = cbor_value_enter_container(&amaclMap, &amsArray);
407             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering AMS Array Container.");
408             headAmacl->amss = (OicUuid_t *)OICCalloc(headAmacl->amssLen, sizeof(*headAmacl->amss));
409             VERIFY_NON_NULL(TAG, headAmacl->amss, ERROR);
410             while (cbor_value_is_valid(&amsArray))
411             {
412                 char *amssId = NULL;
413                 cborFindResult = cbor_value_dup_text_string(&amsArray, &amssId, &len, NULL);
414                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding AMS Id.");
415                 cborFindResult = cbor_value_advance(&amsArray);
416                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing AMS.");
417                 memcpy(headAmacl->amss[i++].id, (OicUuid_t *)amssId, len);
418                 OICFree(amssId);
419             }
420         }
421
422         // TODO : Need to modify headAmacl->owners[0].id to headAmacl->rowner based on RAML spec.
423         // Rowner -- Mandatory
424         if (0 == strcmp(OIC_JSON_ROWNERID_NAME, name))
425         {
426             char *stRowner = NULL;
427             cborFindResult = cbor_value_dup_text_string(&amaclMap, &stRowner, &len, NULL);
428             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding ROwner Value.");
429             headAmacl->ownersLen = 1;
430             headAmacl->owners = (OicUuid_t *)OICCalloc(headAmacl->ownersLen, sizeof(*headAmacl->owners));
431             VERIFY_NON_NULL(TAG, headAmacl->owners, ERROR);
432             ret = ConvertStrToUuid(stRowner, &headAmacl->owners[0]);
433             VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
434             OICFree(stRowner);
435         }
436
437         //if (CborMapType != type && cbor_value_is_valid(&amaclMap))
438         if (cbor_value_is_valid(&amaclMap))
439         {
440             cborFindResult = cbor_value_advance(&amaclMap);
441             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Amacl Map.");
442         }
443         OICFree(name);
444     }
445
446     *secAmacl = headAmacl;
447     ret = OC_STACK_OK;
448
449 exit:
450     if (CborNoError != cborFindResult)
451     {
452         DeleteAmaclList(headAmacl);
453         headAmacl = NULL;
454         *secAmacl = NULL;
455         ret = OC_STACK_ERROR;
456     }
457     return ret;
458 }
459
460 static OCEntityHandlerResult HandleAmaclGetRequest (const OCEntityHandlerRequest * ehRequest)
461 {
462     // Convert Amacl data into JSON for transmission
463     size_t size = 0;
464     uint8_t *cborPayload = NULL;
465     OCStackResult res = AmaclToCBORPayload(gAmacl, &cborPayload, &size);
466
467     OCEntityHandlerResult ehRet = (res == OC_STACK_OK) ? OC_EH_OK : OC_EH_ERROR;
468
469     // Send response payload to request originator
470     SendSRMCBORResponse(ehRequest, ehRet, cborPayload, size);
471
472     OICFree(cborPayload);
473
474     OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
475     return ehRet;
476 }
477
478 static OCEntityHandlerResult HandleAmaclPostRequest (const OCEntityHandlerRequest * ehRequest)
479 {
480     OCEntityHandlerResult ehRet = OC_EH_ERROR;
481
482     // Convert CBOR Amacl data into binary. This will also validate the Amacl data received.
483     uint8_t *payload = ((OCSecurityPayload *) ehRequest->payload)->securityData1;
484     size_t size = ((OCSecurityPayload *) ehRequest->payload)->payloadSize;
485     if (payload)
486     {
487         OicSecAmacl_t *newAmacl = NULL;
488         OCStackResult res = CBORPayloadToAmacl(payload, size, &newAmacl);
489         if (newAmacl && OC_STACK_OK == res)
490         {
491             // Append the new Amacl to existing Amacl
492             LL_APPEND(gAmacl, newAmacl);
493             size_t size = 0;
494             // Convert Amacl data into JSON for update to persistent storage.
495             uint8_t *cborPayload = NULL;
496             res = AmaclToCBORPayload(gAmacl, &cborPayload, &size);
497             if (cborPayload && (OC_STACK_OK == res) &&
498                 (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_AMACL_NAME, cborPayload, size)))
499             {
500                 ehRet = OC_EH_RESOURCE_CREATED;
501             }
502             OICFree(cborPayload);
503         }
504         OICFree(payload);
505     }
506
507     // Send payload to request originator
508     SendSRMCBORResponse(ehRequest, ehRet, NULL, 0);
509
510     OIC_LOG_V(DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
511     return ehRet;
512 }
513
514 /**
515  * This internal method is the entity handler for Amacl resources and
516  * will handle REST request (GET/PUT/POST/DEL) for them.
517  */
518 static OCEntityHandlerResult AmaclEntityHandler (OCEntityHandlerFlag flag,
519                                                  OCEntityHandlerRequest * ehRequest,
520                                                  void* callbackParameter)
521 {
522     (void) callbackParameter;
523     OCEntityHandlerResult ehRet = OC_EH_ERROR;
524
525     if (!ehRequest)
526     {
527         return ehRet;
528     }
529
530     if (flag & OC_REQUEST_FLAG)
531     {
532         OIC_LOG (DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
533         switch (ehRequest->method)
534         {
535             case OC_REST_GET:
536                 ehRet = HandleAmaclGetRequest(ehRequest);
537                 break;
538
539             case OC_REST_POST:
540                 ehRet = HandleAmaclPostRequest(ehRequest);
541                 break;
542
543             default:
544                 ehRet = OC_EH_ERROR;
545                 SendSRMCBORResponse(ehRequest, ehRet, NULL, 0);
546         }
547     }
548
549     return ehRet;
550 }
551
552 /**
553  * This internal method is used to create '/oic/sec/amacl' resource.
554  */
555 static OCStackResult CreateAmaclResource()
556 {
557     OCStackResult ret = OCCreateResource(&gAmaclHandle,
558                                          OIC_RSRC_TYPE_SEC_AMACL,
559                                          OIC_MI_DEF,
560                                          OIC_RSRC_AMACL_URI,
561                                          AmaclEntityHandler,
562                                          NULL,
563                                          OC_OBSERVABLE);
564
565     if (OC_STACK_OK != ret)
566     {
567         OIC_LOG (FATAL, TAG, "Unable to instantiate Amacl resource");
568         DeInitAmaclResource();
569     }
570     return ret;
571 }
572
573 OCStackResult InitAmaclResource()
574 {
575     OCStackResult ret = OC_STACK_ERROR;
576
577     uint8_t *data = NULL;
578     size_t size = 0;
579     ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_AMACL_NAME, &data, &size);
580
581     // If database read failed
582     if (OC_STACK_OK != ret)
583     {
584         OIC_LOG(DEBUG, TAG, "ReadSVDataFromPS failed");
585     }
586     if (data)
587     {
588         // Read AMACL resource from PS
589         ret = CBORPayloadToAmacl(data, size, &gAmacl);
590         if (OC_STACK_OK != ret)
591         {
592             OIC_LOG(DEBUG, TAG, "ReadAMACLresourcefromPS failed");
593         }
594         OICFree(data);
595     }
596
597     // Instantiate 'oic/sec/amacl' resource
598     ret = CreateAmaclResource();
599
600     if (OC_STACK_OK != ret)
601     {
602         DeInitAmaclResource();
603     }
604     return ret;
605 }
606
607 void DeInitAmaclResource()
608 {
609     OCDeleteResource(gAmaclHandle);
610     gAmaclHandle = NULL;
611
612     DeleteAmaclList(gAmacl);
613     gAmacl = NULL;
614 }
615
616 OCStackResult AmaclGetAmsDeviceId(const char *resource, OicUuid_t *amsDeviceId)
617 {
618     OicSecAmacl_t *amacl = NULL;
619
620     VERIFY_NON_NULL(TAG, resource, ERROR);
621     VERIFY_NON_NULL(TAG, amsDeviceId, ERROR);
622
623     LL_FOREACH(gAmacl, amacl)
624     {
625         for(size_t i = 0; i < amacl->resourcesLen; i++)
626         {
627             if (0 == strncmp((amacl->resources[i]), resource, strlen(amacl->resources[i])))
628             {
629                 //Returning the ID of the first AMS service for the resource
630                 memcpy(amsDeviceId, &amacl->amss[0], sizeof(*amsDeviceId));
631                 return OC_STACK_OK;
632             }
633         }
634     }
635
636 exit:
637     return OC_STACK_ERROR;
638 }