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 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
23 #include "oic_malloc.h"
24 #include "ocpayload.h"
25 #include "payload_logging.h"
26 #include "psinterface.h"
27 #include "resourcemanager.h"
29 #include "srmresourcestrings.h"
30 #include "srmutility.h"
31 #include "amaclresource.h"
33 #define TAG "SRM-AMACL"
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 uint8_t CBOR_SIZE = 255;
39 /* Max cbor size payload. */
40 static const uint16_t CBOR_MAX_SIZE = 4400;
42 /** AMACL Map size - Number of mandatory items. */
43 static const uint8_t AMACL_MAP_SIZE = 3;
45 static OicSecAmacl_t *gAmacl = NULL;
46 static OCResourceHandle gAmaclHandle = NULL;
48 void DeleteAmaclList(OicSecAmacl_t* amacl)
52 OicSecAmacl_t *amaclTmp1 = NULL, *amaclTmp2 = NULL;
53 LL_FOREACH_SAFE(amacl, amaclTmp1, amaclTmp2)
55 LL_DELETE(amacl, amaclTmp1);
58 for (size_t i = 0; i < amaclTmp1->resourcesLen; i++)
60 OICFree(amaclTmp1->resources[i]);
62 OICFree(amaclTmp1->resources);
65 OICFree(amaclTmp1->amss);
68 OICFree(amaclTmp1->owners);
70 // Clean Amacl node itself
76 static size_t OicSecAmaclCount(const OicSecAmacl_t *secAmacl)
79 for (const OicSecAmacl_t *amacl = secAmacl; amacl; amacl = amacl->next)
86 OCStackResult AmaclToCBORPayload(const OicSecAmacl_t *amaclS, uint8_t **cborPayload,
89 if (NULL == amaclS || NULL == cborPayload || NULL != *cborPayload || NULL == cborSize)
91 return OC_STACK_INVALID_PARAM;
94 OCStackResult ret = OC_STACK_ERROR;
95 size_t cborLen = *cborSize;
104 CborEncoder encoder = { {.ptr = NULL }, .end = 0 };
105 CborEncoder amaclArray = { {.ptr = NULL }, .end = 0 };
106 CborError cborEncoderResult = CborNoError;
108 const OicSecAmacl_t *amacl = amaclS;
109 uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
110 VERIFY_NON_NULL(TAG, outPayload, ERROR);
111 cbor_encoder_init(&encoder, outPayload, cborLen, 0);
113 // Create AMACL Array
114 cborEncoderResult = cbor_encoder_create_array(&encoder, &amaclArray, OicSecAmaclCount(amacl));
115 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding AMACL Array.");
119 CborEncoder amaclMap = { {.ptr = NULL }, .end = 0 };
120 cborEncoderResult = cbor_encoder_create_map(&amaclArray, &amaclMap, AMACL_MAP_SIZE);
121 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding AMACL MAP.");
123 // Resources -- Mandatory
125 CborEncoder resources = { {.ptr = NULL }, .end = 0};
126 cborEncoderResult = cbor_encode_text_string(&amaclMap, OIC_JSON_RESOURCES_NAME,
127 strlen(OIC_JSON_RESOURCES_NAME));
128 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Resource Name Tag.");
129 cborEncoderResult = cbor_encoder_create_array(&amaclMap, &resources, amacl->resourcesLen);
130 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Resource Name Array.");
131 for (size_t i = 0; i < amacl->resourcesLen; i++)
133 cborEncoderResult = cbor_encode_text_string(&resources, amacl->resources[i],
134 strlen(amacl->resources[i]));
135 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Resource Name Value in Array.");
138 cborEncoderResult = cbor_encoder_close_container(&amaclMap, &resources);
139 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Resource Name ");
143 CborEncoder amss = { {.ptr = NULL }, .end = 0 };
144 cborEncoderResult = cbor_encode_text_string(&amaclMap, OIC_JSON_AMSS_NAME,
145 strlen(OIC_JSON_AMSS_NAME));
146 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding AMSS Name Tag.");
147 cborEncoderResult = cbor_encoder_create_array(&amaclMap, &amss, amacl->amssLen);
148 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding AMSS Name Array.");
149 for (size_t i = 0; i < amacl->amssLen; i++)
151 cborEncoderResult = cbor_encode_byte_string(&amss, amacl->amss[i].id,
152 sizeof(amacl->amss[i].id));
153 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding AMSS Name Value.");
155 cborEncoderResult = cbor_encoder_close_container(&amaclMap, &amss);
156 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing AMSS Array.");
158 // Owners -- Mandatory
160 cborEncoderResult = cbor_encode_text_string(&amaclMap, OIC_JSON_OWNERS_NAME,
161 strlen(OIC_JSON_OWNERS_NAME));
162 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Owners Array Tag.");
163 CborEncoder owners = { {.ptr = NULL }, .end = 0};
164 cborEncoderResult = cbor_encoder_create_array(&amaclMap, &owners, amacl->ownersLen);
165 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Owners Array.");
166 for (size_t i = 0; i < amacl->ownersLen; i++)
168 cborEncoderResult = cbor_encode_byte_string(&owners, (uint8_t *)amacl->owners[i].id,
169 sizeof(amacl->owners[i].id));
170 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Owners Array Value.");
172 cborEncoderResult = cbor_encoder_close_container(&amaclMap, &owners);
173 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Owners Array.");
175 cborEncoderResult = cbor_encoder_close_container(&amaclArray, &amaclMap);
176 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing AMACL Map.");
180 cborEncoderResult = cbor_encoder_close_container(&encoder, &amaclArray);
181 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Amacl Array.");
183 if (CborNoError == cborEncoderResult)
185 *cborPayload = outPayload;
186 *cborSize = encoder.ptr - outPayload;
191 if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
193 // reallocate and try again!
196 // Since the allocated initial memory failed, double the memory.
197 cborLen += encoder.ptr - encoder.end;
198 cborEncoderResult = CborNoError;
199 ret = AmaclToCBORPayload(amaclS, cborPayload, &cborLen);
200 if (OC_STACK_OK == ret)
207 if (CborNoError != cborEncoderResult)
213 ret = OC_STACK_ERROR;
219 OCStackResult CBORPayloadToAmacl(const uint8_t *cborPayload, size_t size,
220 OicSecAmacl_t **secAmacl)
222 if (NULL == cborPayload || NULL == secAmacl || NULL != *secAmacl)
224 return OC_STACK_INVALID_PARAM;
229 OCStackResult ret = OC_STACK_ERROR;
231 CborValue amaclCbor = { .parser = NULL };
232 CborParser parser = { .end = NULL };
233 CborError cborFindResult = CborNoError;
239 cbor_parser_init(cborPayload, cborLen, 0, &parser, &amaclCbor);
241 OicSecAmacl_t *headAmacl = NULL;
243 CborValue amaclArray = { .parser = NULL };
244 cborFindResult = cbor_value_enter_container(&amaclCbor, &amaclArray);
245 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
247 while (cbor_value_is_valid(&amaclArray))
249 CborValue amaclMap = { .parser = NULL };
250 cborFindResult = cbor_value_enter_container(&amaclArray, &amaclMap);
251 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
253 OicSecAmacl_t *amacl = (OicSecAmacl_t *) OICCalloc(1, sizeof(*amacl));
254 VERIFY_NON_NULL(TAG, amacl, ERROR);
256 while (cbor_value_is_valid(&amaclMap))
260 cborFindResult = cbor_value_dup_text_string(&amaclMap, &name, &len, NULL);
261 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
262 cborFindResult = cbor_value_advance(&amaclMap);
263 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
265 CborType type = cbor_value_get_type(&amaclMap);
267 // Resources -- Mandatory
268 if (0 == strcmp(OIC_JSON_RESOURCES_NAME, name))
270 CborValue resources = { .parser = NULL };
271 cborFindResult = cbor_value_get_array_length(&amaclMap, &amacl->resourcesLen);
272 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
274 cborFindResult = cbor_value_enter_container(&amaclMap, &resources);
275 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
277 amacl->resources = (char **) OICMalloc(amacl->resourcesLen * sizeof(*amacl->resources));
278 VERIFY_NON_NULL(TAG, amacl->resources, ERROR);
280 while (cbor_value_is_text_string(&resources))
282 cborFindResult = cbor_value_dup_text_string(&resources, &amacl->resources[i++],
284 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
285 cborFindResult = cbor_value_advance(&resources);
286 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
291 if (0 == strcmp(OIC_JSON_AMSS_NAME, name))
293 CborValue amss = { .parser = NULL };
294 cborFindResult = cbor_value_get_array_length(&amaclMap, &amacl->amssLen);
295 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
296 cborFindResult = cbor_value_enter_container(&amaclMap, &amss);
297 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
299 amacl->amss = (OicUuid_t *)OICCalloc(amacl->amssLen, sizeof(*amacl->amss));
300 VERIFY_NON_NULL(TAG, amacl->amss, ERROR);
301 while (cbor_value_is_valid(&amss))
303 uint8_t *amssId = NULL;
304 cborFindResult = cbor_value_dup_byte_string(&amss, &amssId, &len, NULL);
305 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
306 cborFindResult = cbor_value_advance(&amss);
307 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
308 memcpy(amacl->amss[i].id, amssId, len);
313 // Owners -- Mandatory
314 if (0 == strcmp(OIC_JSON_OWNERS_NAME, name))
316 CborValue owners = { .parser = NULL };
317 cborFindResult = cbor_value_get_array_length(&amaclMap, &amacl->ownersLen);
318 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
319 cborFindResult = cbor_value_enter_container(&amaclMap, &owners);
320 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
322 amacl->owners = (OicUuid_t *)OICCalloc(amacl->ownersLen, sizeof(*amacl->owners));
323 VERIFY_NON_NULL(TAG, amacl->owners, ERROR);
324 while (cbor_value_is_valid(&owners))
326 uint8_t *owner = NULL;
327 cborFindResult = cbor_value_dup_byte_string(&owners, &owner, &len, NULL);
328 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
329 cborFindResult = cbor_value_advance(&owners);
330 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
331 memcpy(amacl->owners[i].id, owner, len);
335 if (CborMapType != type && cbor_value_is_valid(&amaclMap))
337 cborFindResult = cbor_value_advance(&amaclMap);
338 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
344 if (NULL == headAmacl)
350 OicSecAmacl_t *temp = headAmacl;
357 if (cbor_value_is_valid(&amaclArray))
359 cborFindResult = cbor_value_advance(&amaclArray);
360 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
363 *secAmacl = headAmacl;
366 if (CborNoError != cborFindResult)
368 DeleteAmaclList(headAmacl);
370 ret = OC_STACK_ERROR;
375 static OCEntityHandlerResult HandleAmaclGetRequest (const OCEntityHandlerRequest * ehRequest)
377 // Convert Amacl data into JSON for transmission
379 uint8_t *cborPayload = NULL;
380 OCStackResult res = AmaclToCBORPayload(gAmacl, &cborPayload, &size);
382 OCEntityHandlerResult ehRet = (res == OC_STACK_OK) ? OC_EH_OK : OC_EH_ERROR;
384 // Send response payload to request originator
385 SendSRMCBORResponse(ehRequest, ehRet, cborPayload);
387 OICFree(cborPayload);
389 OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
393 static OCEntityHandlerResult HandleAmaclPostRequest (const OCEntityHandlerRequest * ehRequest)
395 OCEntityHandlerResult ehRet = OC_EH_ERROR;
397 // Convert CBOR Amacl data into binary. This will also validate the Amacl data received.
398 uint8_t *payload = ((OCSecurityPayload *) ehRequest->payload)->securityData1;;
401 OicSecAmacl_t *newAmacl = NULL;
402 OCStackResult res = CBORPayloadToAmacl(payload, CBOR_SIZE, &newAmacl);
403 if (newAmacl && OC_STACK_OK == res)
405 // Append the new Amacl to existing Amacl
406 LL_APPEND(gAmacl, newAmacl);
408 // Convert Amacl data into JSON for update to persistent storage.
409 uint8_t *cborPayload = NULL;
410 res = AmaclToCBORPayload(gAmacl, &cborPayload, &size);
411 if (cborPayload && (OC_STACK_OK == res) &&
412 (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_AMACL_NAME, cborPayload, size)))
414 ehRet = OC_EH_RESOURCE_CREATED;
416 OICFree(cborPayload);
421 // Send payload to request originator
422 SendSRMCBORResponse(ehRequest, ehRet, NULL);
424 OIC_LOG_V(DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
429 * This internal method is the entity handler for Amacl resources and
430 * will handle REST request (GET/PUT/POST/DEL) for them.
432 static OCEntityHandlerResult AmaclEntityHandler (OCEntityHandlerFlag flag,
433 OCEntityHandlerRequest * ehRequest,
434 void* callbackParameter)
436 (void) callbackParameter;
437 OCEntityHandlerResult ehRet = OC_EH_ERROR;
444 if (flag & OC_REQUEST_FLAG)
446 OIC_LOG (DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
447 switch (ehRequest->method)
450 ehRet = HandleAmaclGetRequest(ehRequest);
454 ehRet = HandleAmaclPostRequest(ehRequest);
459 SendSRMResponse(ehRequest, ehRet, NULL);
467 * This internal method is used to create '/oic/sec/amacl' resource.
469 static OCStackResult CreateAmaclResource()
471 OCStackResult ret = OCCreateResource(&gAmaclHandle,
472 OIC_RSRC_TYPE_SEC_AMACL,
479 if (OC_STACK_OK != ret)
481 OIC_LOG (FATAL, TAG, "Unable to instantiate Amacl resource");
482 DeInitAmaclResource();
487 OCStackResult InitAmaclResource()
489 OCStackResult ret = OC_STACK_ERROR;
491 uint8_t *data = NULL;
493 ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_AMACL_NAME, &data, &size);
495 // If database read failed
496 if (OC_STACK_OK != ret)
498 OIC_LOG(DEBUG, TAG, "ReadSVDataFromPS failed");
502 // Read AMACL resource from PS
503 ret = CBORPayloadToAmacl(data, size, &gAmacl);
507 // Instantiate 'oic/sec/amacl' resource
508 ret = CreateAmaclResource();
510 if (OC_STACK_OK != ret)
512 DeInitAmaclResource();
517 void DeInitAmaclResource()
519 OCDeleteResource(gAmaclHandle);
522 DeleteAmaclList(gAmacl);
526 OCStackResult AmaclGetAmsDeviceId(const char *resource, OicUuid_t *amsDeviceId)
528 OicSecAmacl_t *amacl = NULL;
530 VERIFY_NON_NULL(TAG, resource, ERROR);
531 VERIFY_NON_NULL(TAG, amsDeviceId, ERROR);
533 LL_FOREACH(gAmacl, amacl)
535 for(size_t i = 0; i < amacl->resourcesLen; i++)
537 if (0 == strncmp((amacl->resources[i]), resource, strlen(amacl->resources[i])))
539 //Returning the ID of the first AMS service for the resource
540 memcpy(amsDeviceId, &amacl->amss[0], sizeof(*amsDeviceId));
547 return OC_STACK_ERROR;