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 int64_t 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.");
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.");
168 for (size_t i = 0; i < amacl->ownersLen; i++)
170 cborEncoderResult |= cbor_encode_byte_string(&owners, (uint8_t *)amacl->owners[i].id,
171 sizeof(amacl->owners[i].id));
172 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Owners Array Value.");
174 cborEncoderResult |= cbor_encoder_close_container(&amaclMap, &owners);
175 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Owners Array.");
177 cborEncoderResult |= cbor_encoder_close_container(&amaclArray, &amaclMap);
178 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing AMACL Map.");
182 cborEncoderResult |= cbor_encoder_close_container(&encoder, &amaclArray);
183 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Amacl Array.");
185 if (CborNoError == cborEncoderResult)
187 *cborPayload = outPayload;
188 *cborSize = encoder.ptr - outPayload;
193 if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
195 // reallocate and try again!
198 // Since the allocated initial memory failed, double the memory.
199 cborLen += encoder.ptr - encoder.end;
200 cborEncoderResult = CborNoError;
201 ret = AmaclToCBORPayload(amaclS, cborPayload, &cborLen);
202 if (OC_STACK_OK == ret)
209 if (CborNoError != cborEncoderResult)
215 ret = OC_STACK_ERROR;
221 OCStackResult CBORPayloadToAmacl(const uint8_t *cborPayload, size_t size,
222 OicSecAmacl_t **secAmacl)
224 if (NULL == cborPayload || NULL == secAmacl || NULL != *secAmacl)
226 return OC_STACK_INVALID_PARAM;
231 OCStackResult ret = OC_STACK_ERROR;
233 CborValue amaclCbor = { .parser = NULL };
234 CborParser parser = { .end = NULL };
235 CborError cborFindResult = CborNoError;
241 cbor_parser_init(cborPayload, cborLen, 0, &parser, &amaclCbor);
243 OicSecAmacl_t *headAmacl = NULL;
245 CborValue amaclArray = { .parser = NULL };
246 cborFindResult = cbor_value_enter_container(&amaclCbor, &amaclArray);
247 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering Amacl Array.");
249 while (cbor_value_is_valid(&amaclArray))
251 CborValue amaclMap = { .parser = NULL };
252 cborFindResult = cbor_value_enter_container(&amaclArray, &amaclMap);
253 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering Amacl Map.");
255 OicSecAmacl_t *amacl = (OicSecAmacl_t *) OICCalloc(1, sizeof(*amacl));
256 VERIFY_NON_NULL(TAG, amacl, ERROR);
258 while (cbor_value_is_valid(&amaclMap))
262 cborFindResult = cbor_value_dup_text_string(&amaclMap, &name, &len, NULL);
263 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering Amacl Name.");
264 cborFindResult = cbor_value_advance(&amaclMap);
265 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering Amacl Advance.");
267 CborType type = cbor_value_get_type(&amaclMap);
269 // Resources -- Mandatory
270 if (0 == strcmp(OIC_JSON_RESOURCES_NAME, name))
272 CborValue resources = { .parser = NULL };
273 cborFindResult = cbor_value_get_array_length(&amaclMap, &amacl->resourcesLen);
274 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Resource Name Array Len.");
276 cborFindResult = cbor_value_enter_container(&amaclMap, &resources);
277 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering Amacl Array.");
279 amacl->resources = (char **) OICCalloc(amacl->resourcesLen, sizeof(*amacl->resources));
280 VERIFY_NON_NULL(TAG, amacl->resources, ERROR);
282 while (cbor_value_is_text_string(&resources))
284 cborFindResult = cbor_value_dup_text_string(&resources, &amacl->resources[i++],
286 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Resource Name Value.");
287 cborFindResult = cbor_value_advance(&resources);
288 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Resource Name.");
293 if (0 == strcmp(OIC_JSON_AMSS_NAME, name))
295 CborValue amss = { .parser = NULL };
296 cborFindResult = cbor_value_get_array_length(&amaclMap, &amacl->amssLen);
297 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering AMSS Name Array Len.");
298 cborFindResult = cbor_value_enter_container(&amaclMap, &amss);
299 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering AMSS Name Container.");
301 amacl->amss = (OicUuid_t *)OICCalloc(amacl->amssLen, sizeof(*amacl->amss));
302 VERIFY_NON_NULL(TAG, amacl->amss, ERROR);
303 while (cbor_value_is_valid(&amss))
305 uint8_t *amssId = NULL;
306 cborFindResult = cbor_value_dup_byte_string(&amss, &amssId, &len, NULL);
307 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Adding AMSS Id.");
308 cborFindResult = cbor_value_advance(&amss);
309 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing AMSS.");
310 memcpy(amacl->amss[i++].id, amssId, len);
315 // Owners -- Mandatory
316 if (0 == strcmp(OIC_JSON_OWNERS_NAME, name))
318 CborValue owners = { .parser = NULL };
319 cborFindResult = cbor_value_get_array_length(&amaclMap, &amacl->ownersLen);
320 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Adding Owner Name Len.");
321 cborFindResult = cbor_value_enter_container(&amaclMap, &owners);
322 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Container Owner Array.");
324 amacl->owners = (OicUuid_t *)OICCalloc(amacl->ownersLen, sizeof(*amacl->owners));
325 VERIFY_NON_NULL(TAG, amacl->owners, ERROR);
326 while (cbor_value_is_valid(&owners))
328 uint8_t *owner = NULL;
329 cborFindResult = cbor_value_dup_byte_string(&owners, &owner, &len, NULL);
330 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Adding Owners Array Value.");
331 cborFindResult = cbor_value_advance(&owners);
332 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Owners Array");
333 memcpy(amacl->owners[i++].id, owner, len);
337 if (CborMapType != type && cbor_value_is_valid(&amaclMap))
339 cborFindResult = cbor_value_advance(&amaclMap);
340 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Amacl Map.");
346 if (NULL == headAmacl)
352 OicSecAmacl_t *temp = headAmacl;
359 if (cbor_value_is_valid(&amaclArray))
361 cborFindResult = cbor_value_advance(&amaclArray);
362 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing AMACL Array.");
365 *secAmacl = headAmacl;
369 if (CborNoError != cborFindResult)
371 DeleteAmaclList(headAmacl);
373 ret = OC_STACK_ERROR;
378 static OCEntityHandlerResult HandleAmaclGetRequest (const OCEntityHandlerRequest * ehRequest)
380 // Convert Amacl data into JSON for transmission
382 uint8_t *cborPayload = NULL;
383 OCStackResult res = AmaclToCBORPayload(gAmacl, &cborPayload, &size);
385 OCEntityHandlerResult ehRet = (res == OC_STACK_OK) ? OC_EH_OK : OC_EH_ERROR;
387 // Send response payload to request originator
388 SendSRMCBORResponse(ehRequest, ehRet, cborPayload, size);
390 OICFree(cborPayload);
392 OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
396 static OCEntityHandlerResult HandleAmaclPostRequest (const OCEntityHandlerRequest * ehRequest)
398 OCEntityHandlerResult ehRet = OC_EH_ERROR;
400 // Convert CBOR Amacl data into binary. This will also validate the Amacl data received.
401 uint8_t *payload = ((OCSecurityPayload *) ehRequest->payload)->securityData1;
402 size_t size = ((OCSecurityPayload *) ehRequest->payload)->payloadSize;
405 OicSecAmacl_t *newAmacl = NULL;
406 OCStackResult res = CBORPayloadToAmacl(payload, size, &newAmacl);
407 if (newAmacl && OC_STACK_OK == res)
409 // Append the new Amacl to existing Amacl
410 LL_APPEND(gAmacl, newAmacl);
412 // Convert Amacl data into JSON for update to persistent storage.
413 uint8_t *cborPayload = NULL;
414 res = AmaclToCBORPayload(gAmacl, &cborPayload, &size);
415 if (cborPayload && (OC_STACK_OK == res) &&
416 (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_AMACL_NAME, cborPayload, size)))
418 ehRet = OC_EH_RESOURCE_CREATED;
420 OICFree(cborPayload);
425 // Send payload to request originator
426 SendSRMCBORResponse(ehRequest, ehRet, NULL, 0);
428 OIC_LOG_V(DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
433 * This internal method is the entity handler for Amacl resources and
434 * will handle REST request (GET/PUT/POST/DEL) for them.
436 static OCEntityHandlerResult AmaclEntityHandler (OCEntityHandlerFlag flag,
437 OCEntityHandlerRequest * ehRequest,
438 void* callbackParameter)
440 (void) callbackParameter;
441 OCEntityHandlerResult ehRet = OC_EH_ERROR;
448 if (flag & OC_REQUEST_FLAG)
450 OIC_LOG (DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
451 switch (ehRequest->method)
454 ehRet = HandleAmaclGetRequest(ehRequest);
458 ehRet = HandleAmaclPostRequest(ehRequest);
463 SendSRMCBORResponse(ehRequest, ehRet, NULL, 0);
471 * This internal method is used to create '/oic/sec/amacl' resource.
473 static OCStackResult CreateAmaclResource()
475 OCStackResult ret = OCCreateResource(&gAmaclHandle,
476 OIC_RSRC_TYPE_SEC_AMACL,
483 if (OC_STACK_OK != ret)
485 OIC_LOG (FATAL, TAG, "Unable to instantiate Amacl resource");
486 DeInitAmaclResource();
491 OCStackResult InitAmaclResource()
493 OCStackResult ret = OC_STACK_ERROR;
495 uint8_t *data = NULL;
497 ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_AMACL_NAME, &data, &size);
499 // If database read failed
500 if (OC_STACK_OK != ret)
502 OIC_LOG(DEBUG, TAG, "ReadSVDataFromPS failed");
506 // Read AMACL resource from PS
507 ret = CBORPayloadToAmacl(data, size, &gAmacl);
508 if (OC_STACK_OK != ret)
510 OIC_LOG(DEBUG, TAG, "ReadAMACLresourcefromPS failed");
515 // Instantiate 'oic/sec/amacl' resource
516 ret = CreateAmaclResource();
518 if (OC_STACK_OK != ret)
520 DeInitAmaclResource();
525 void DeInitAmaclResource()
527 OCDeleteResource(gAmaclHandle);
530 DeleteAmaclList(gAmacl);
534 OCStackResult AmaclGetAmsDeviceId(const char *resource, OicUuid_t *amsDeviceId)
536 OicSecAmacl_t *amacl = NULL;
538 VERIFY_NON_NULL(TAG, resource, ERROR);
539 VERIFY_NON_NULL(TAG, amsDeviceId, ERROR);
541 LL_FOREACH(gAmacl, amacl)
543 for(size_t i = 0; i < amacl->resourcesLen; i++)
545 if (0 == strncmp((amacl->resources[i]), resource, strlen(amacl->resources[i])))
547 //Returning the ID of the first AMS service for the resource
548 memcpy(amsDeviceId, &amacl->amss[0], sizeof(*amsDeviceId));
555 return OC_STACK_ERROR;