1 //******************************************************************
3 // Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
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
11 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
24 #include "oic_malloc.h"
25 #include "ocpayload.h"
26 #include "payload_logging.h"
27 #include "psinterface.h"
28 #include "resourcemanager.h"
30 #include "srmresourcestrings.h"
31 #include "srmutility.h"
32 #include "amaclresource.h"
34 #define TAG "SRM-AMACL"
36 /** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
37 * The value of payload size is increased until reaching belox max cbor size. */
38 static const uint8_t CBOR_SIZE = 255;
40 /* Max cbor size payload. */
41 static const uint16_t CBOR_MAX_SIZE = 4400;
43 /** AMACL Map size - Number of mandatory items. */
44 static const uint8_t AMACL_MAP_SIZE = 3;
46 static OicSecAmacl_t *gAmacl = NULL;
47 static OCResourceHandle gAmaclHandle = NULL;
49 void DeleteAmaclList(OicSecAmacl_t* amacl)
53 OicSecAmacl_t *amaclTmp1 = NULL, *amaclTmp2 = NULL;
54 LL_FOREACH_SAFE(amacl, amaclTmp1, amaclTmp2)
56 LL_DELETE(amacl, amaclTmp1);
59 for (size_t i = 0; i < amaclTmp1->resourcesLen; i++)
61 OICFree(amaclTmp1->resources[i]);
63 OICFree(amaclTmp1->resources);
66 OICFree(amaclTmp1->amss);
69 OICFree(amaclTmp1->owners);
71 // Clean Amacl node itself
77 static size_t OicSecAmaclCount(const OicSecAmacl_t *secAmacl)
80 for (const OicSecAmacl_t *amacl = secAmacl; amacl; amacl = amacl->next)
87 OCStackResult AmaclToCBORPayload(const OicSecAmacl_t *amaclS, uint8_t **cborPayload,
90 if (NULL == amaclS || NULL == cborPayload || NULL != *cborPayload || NULL == cborSize)
92 return OC_STACK_INVALID_PARAM;
95 OCStackResult ret = OC_STACK_ERROR;
96 size_t cborLen = *cborSize;
105 CborEncoder encoder = { {.ptr = NULL }, .end = 0 };
106 CborEncoder amaclArray = { {.ptr = NULL }, .end = 0 };
107 CborError cborEncoderResult = CborNoError;
109 const OicSecAmacl_t *amacl = amaclS;
110 uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
111 VERIFY_NON_NULL(TAG, outPayload, ERROR);
112 cbor_encoder_init(&encoder, outPayload, cborLen, 0);
114 // Create AMACL Array
115 cborEncoderResult = cbor_encoder_create_array(&encoder, &amaclArray, OicSecAmaclCount(amacl));
116 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding AMACL Array.");
120 CborEncoder amaclMap = { {.ptr = NULL }, .end = 0 };
121 cborEncoderResult = cbor_encoder_create_map(&amaclArray, &amaclMap, AMACL_MAP_SIZE);
122 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding AMACL MAP.");
124 // Resources -- Mandatory
126 CborEncoder resources = { {.ptr = NULL }, .end = 0};
127 cborEncoderResult = cbor_encode_text_string(&amaclMap, OIC_JSON_RESOURCES_NAME,
128 strlen(OIC_JSON_RESOURCES_NAME));
129 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Resource Name Tag.");
130 cborEncoderResult = cbor_encoder_create_array(&amaclMap, &resources, amacl->resourcesLen);
131 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Resource Name Array.");
132 for (size_t i = 0; i < amacl->resourcesLen; i++)
134 cborEncoderResult = cbor_encode_text_string(&resources, amacl->resources[i],
135 strlen(amacl->resources[i]));
136 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Resource Name Value in Array.");
139 cborEncoderResult = cbor_encoder_close_container(&amaclMap, &resources);
140 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Resource Name ");
144 CborEncoder amss = { {.ptr = NULL }, .end = 0 };
145 cborEncoderResult = cbor_encode_text_string(&amaclMap, OIC_JSON_AMSS_NAME,
146 strlen(OIC_JSON_AMSS_NAME));
147 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding AMSS Name Tag.");
148 cborEncoderResult = cbor_encoder_create_array(&amaclMap, &amss, amacl->amssLen);
149 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding AMSS Name Array.");
150 for (size_t i = 0; i < amacl->amssLen; i++)
152 cborEncoderResult = cbor_encode_byte_string(&amss, amacl->amss[i].id,
153 sizeof(amacl->amss[i].id));
154 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding AMSS Name Value.");
156 cborEncoderResult = cbor_encoder_close_container(&amaclMap, &amss);
157 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing AMSS Array.");
159 // Owners -- Mandatory
161 cborEncoderResult = cbor_encode_text_string(&amaclMap, OIC_JSON_OWNERS_NAME,
162 strlen(OIC_JSON_OWNERS_NAME));
163 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Owners Array Tag.");
164 CborEncoder owners = { {.ptr = NULL }, .end = 0};
165 cborEncoderResult = cbor_encoder_create_array(&amaclMap, &owners, amacl->ownersLen);
166 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Owners Array.");
167 for (size_t i = 0; i < amacl->ownersLen; i++)
169 cborEncoderResult = cbor_encode_byte_string(&owners, (uint8_t *)amacl->owners[i].id,
170 sizeof(amacl->owners[i].id));
171 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Owners Array Value.");
173 cborEncoderResult = cbor_encoder_close_container(&amaclMap, &owners);
174 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Owners Array.");
176 cborEncoderResult = cbor_encoder_close_container(&amaclArray, &amaclMap);
177 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing AMACL Map.");
181 cborEncoderResult = cbor_encoder_close_container(&encoder, &amaclArray);
182 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Amacl Array.");
184 if (CborNoError == cborEncoderResult)
186 *cborPayload = outPayload;
187 *cborSize = encoder.ptr - outPayload;
192 if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
194 // reallocate and try again!
197 // Since the allocated initial memory failed, double the memory.
198 cborLen += encoder.ptr - encoder.end;
199 cborEncoderResult = CborNoError;
200 ret = AmaclToCBORPayload(amaclS, cborPayload, &cborLen);
201 if (OC_STACK_OK == ret)
208 if (CborNoError != cborEncoderResult)
214 ret = OC_STACK_ERROR;
220 OCStackResult CBORPayloadToAmacl(const uint8_t *cborPayload, size_t size,
221 OicSecAmacl_t **secAmacl)
223 if (NULL == cborPayload || NULL == secAmacl || NULL != *secAmacl)
225 return OC_STACK_INVALID_PARAM;
230 OCStackResult ret = OC_STACK_ERROR;
232 CborValue amaclCbor = { .parser = NULL };
233 CborParser parser = { .end = NULL };
234 CborError cborFindResult = CborNoError;
240 cbor_parser_init(cborPayload, cborLen, 0, &parser, &amaclCbor);
242 OicSecAmacl_t *headAmacl = NULL;
244 CborValue amaclArray = { .parser = NULL };
245 cborFindResult = cbor_value_enter_container(&amaclCbor, &amaclArray);
246 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
248 while (cbor_value_is_valid(&amaclArray))
250 CborValue amaclMap = { .parser = NULL };
251 cborFindResult = cbor_value_enter_container(&amaclArray, &amaclMap);
252 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
254 OicSecAmacl_t *amacl = (OicSecAmacl_t *) OICCalloc(1, sizeof(*amacl));
255 VERIFY_NON_NULL(TAG, amacl, ERROR);
257 while (cbor_value_is_valid(&amaclMap))
261 cborFindResult = cbor_value_dup_text_string(&amaclMap, &name, &len, NULL);
262 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
263 cborFindResult = cbor_value_advance(&amaclMap);
264 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
266 CborType type = cbor_value_get_type(&amaclMap);
268 // Resources -- Mandatory
269 if (0 == strcmp(OIC_JSON_RESOURCES_NAME, name))
271 CborValue resources = { .parser = NULL };
272 cborFindResult = cbor_value_get_array_length(&amaclMap, &amacl->resourcesLen);
273 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
275 cborFindResult = cbor_value_enter_container(&amaclMap, &resources);
276 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
278 amacl->resources = (char **) OICMalloc(amacl->resourcesLen * sizeof(*amacl->resources));
279 VERIFY_NON_NULL(TAG, amacl->resources, ERROR);
281 while (cbor_value_is_text_string(&resources))
283 cborFindResult = cbor_value_dup_text_string(&resources, &amacl->resources[i++],
285 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
286 cborFindResult = cbor_value_advance(&resources);
287 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
292 if (0 == strcmp(OIC_JSON_AMSS_NAME, name))
294 CborValue amss = { .parser = NULL };
295 cborFindResult = cbor_value_get_array_length(&amaclMap, &amacl->amssLen);
296 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
297 cborFindResult = cbor_value_enter_container(&amaclMap, &amss);
298 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
300 amacl->amss = (OicUuid_t *)OICCalloc(amacl->amssLen, sizeof(*amacl->amss));
301 VERIFY_NON_NULL(TAG, amacl->amss, ERROR);
302 while (cbor_value_is_valid(&amss))
304 uint8_t *amssId = NULL;
305 cborFindResult = cbor_value_dup_byte_string(&amss, &amssId, &len, NULL);
306 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
307 cborFindResult = cbor_value_advance(&amss);
308 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
309 memcpy(amacl->amss[i].id, amssId, len);
314 // Owners -- Mandatory
315 if (0 == strcmp(OIC_JSON_OWNERS_NAME, name))
317 CborValue owners = { .parser = NULL };
318 cborFindResult = cbor_value_get_array_length(&amaclMap, &amacl->ownersLen);
319 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
320 cborFindResult = cbor_value_enter_container(&amaclMap, &owners);
321 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
323 amacl->owners = (OicUuid_t *)OICCalloc(amacl->ownersLen, sizeof(*amacl->owners));
324 VERIFY_NON_NULL(TAG, amacl->owners, ERROR);
325 while (cbor_value_is_valid(&owners))
327 uint8_t *owner = NULL;
328 cborFindResult = cbor_value_dup_byte_string(&owners, &owner, &len, NULL);
329 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
330 cborFindResult = cbor_value_advance(&owners);
331 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
332 memcpy(amacl->owners[i].id, owner, len);
336 if (CborMapType != type && cbor_value_is_valid(&amaclMap))
338 cborFindResult = cbor_value_advance(&amaclMap);
339 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
345 if (NULL == headAmacl)
351 OicSecAmacl_t *temp = headAmacl;
358 if (cbor_value_is_valid(&amaclArray))
360 cborFindResult = cbor_value_advance(&amaclArray);
361 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
364 *secAmacl = headAmacl;
367 if (CborNoError != cborFindResult)
369 DeleteAmaclList(headAmacl);
371 ret = OC_STACK_ERROR;
376 static OCEntityHandlerResult HandleAmaclGetRequest (const OCEntityHandlerRequest * ehRequest)
378 // Convert Amacl data into JSON for transmission
380 uint8_t *cborPayload = NULL;
381 OCStackResult res = AmaclToCBORPayload(gAmacl, &cborPayload, &size);
383 OCEntityHandlerResult ehRet = (res == OC_STACK_OK) ? OC_EH_OK : OC_EH_ERROR;
385 // Send response payload to request originator
386 SendSRMCBORResponse(ehRequest, ehRet, cborPayload);
388 OICFree(cborPayload);
390 OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
394 static OCEntityHandlerResult HandleAmaclPostRequest (const OCEntityHandlerRequest * ehRequest)
396 OCEntityHandlerResult ehRet = OC_EH_ERROR;
398 // Convert CBOR Amacl data into binary. This will also validate the Amacl data received.
399 uint8_t *payload = ((OCSecurityPayload *) ehRequest->payload)->securityData1;;
402 OicSecAmacl_t *newAmacl = NULL;
403 OCStackResult res = CBORPayloadToAmacl(payload, CBOR_SIZE, &newAmacl);
404 if (newAmacl && OC_STACK_OK == res)
406 // Append the new Amacl to existing Amacl
407 LL_APPEND(gAmacl, newAmacl);
409 // Convert Amacl data into JSON for update to persistent storage.
410 uint8_t *cborPayload = NULL;
411 res = AmaclToCBORPayload(gAmacl, &cborPayload, &size);
412 if (cborPayload && (OC_STACK_OK == res) &&
413 (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_AMACL_NAME, cborPayload, size)))
415 ehRet = OC_EH_RESOURCE_CREATED;
417 OICFree(cborPayload);
422 // Send payload to request originator
423 SendSRMCBORResponse(ehRequest, ehRet, NULL);
425 OIC_LOG_V(DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
430 * This internal method is the entity handler for Amacl resources and
431 * will handle REST request (GET/PUT/POST/DEL) for them.
433 OCEntityHandlerResult AmaclEntityHandler (OCEntityHandlerFlag flag,
434 OCEntityHandlerRequest * ehRequest,
435 void* callbackParameter)
437 (void) callbackParameter;
438 OCEntityHandlerResult ehRet = OC_EH_ERROR;
445 if (flag & OC_REQUEST_FLAG)
447 OIC_LOG (DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
448 switch (ehRequest->method)
451 ehRet = HandleAmaclGetRequest(ehRequest);
455 ehRet = HandleAmaclPostRequest(ehRequest);
460 SendSRMResponse(ehRequest, ehRet, NULL);
468 * This internal method is used to create '/oic/sec/amacl' resource.
470 OCStackResult CreateAmaclResource()
472 OCStackResult ret = OCCreateResource(&gAmaclHandle,
473 OIC_RSRC_TYPE_SEC_AMACL,
480 if (OC_STACK_OK != ret)
482 OIC_LOG (FATAL, TAG, "Unable to instantiate Amacl resource");
483 DeInitAmaclResource();
489 * Initialize Amacl resource by loading data from persistent storage.
491 * @retval OC_STACK_OK for Success, otherwise some error value
493 OCStackResult InitAmaclResource()
495 OCStackResult ret = OC_STACK_ERROR;
497 uint8_t *data = NULL;
499 ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_AMACL_NAME, &data, &size);
501 // If database read failed
502 if (OC_STACK_OK != ret)
504 OIC_LOG(DEBUG, TAG, "ReadSVDataFromPS failed");
508 // Read AMACL resource from PS
509 ret = CBORPayloadToAmacl(data, size, &gAmacl);
513 // Instantiate 'oic/sec/amacl' resource
514 ret = CreateAmaclResource();
516 if (OC_STACK_OK != ret)
518 DeInitAmaclResource();
524 * Perform cleanup for Amacl resources.
528 void DeInitAmaclResource()
530 OCDeleteResource(gAmaclHandle);
533 DeleteAmaclList(gAmacl);
538 OCStackResult AmaclGetAmsDeviceId(const char *resource, OicUuid_t *amsDeviceId)
540 OicSecAmacl_t *amacl = NULL;
542 VERIFY_NON_NULL(TAG, resource, ERROR);
543 VERIFY_NON_NULL(TAG, amsDeviceId, ERROR);
545 LL_FOREACH(gAmacl, amacl)
547 for(size_t i = 0; i < amacl->resourcesLen; i++)
549 if (0 == strncmp((amacl->resources[i]), resource, strlen(amacl->resources[i])))
551 //Returning the ID of the first AMS service for the resource
552 memcpy(amsDeviceId, &amacl->amss[0], sizeof(*amsDeviceId));
559 return OC_STACK_ERROR;