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