1 /* *****************************************************************
\r
3 * Copyright 2016 Samsung Electronics All Rights Reserved.
\r
7 * Licensed under the Apache License, Version 2.0 (the "License");
\r
8 * you may not use this file except in compliance with the License.
\r
9 * You may obtain a copy of the License at
\r
11 * http://www.apache.org/licenses/LICENSE-2.0
\r
13 * Unless required by applicable law or agreed to in writing, software
\r
14 * distributed under the License is distributed on an "AS IS" BASIS,
\r
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
16 * See the License for the specific language governing permissions and
\r
17 * limitations under the License.
\r
19 * *****************************************************************/
\r
23 #include "ocstack.h"
\r
25 #include "oic_malloc.h"
\r
26 #include "oic_string.h"
\r
29 #include "ocpayload.h"
\r
30 #include "payload_logging.h"
\r
31 #include "resourcemanager.h"
\r
32 #include "pconfresource.h"
\r
33 #include "psinterface.h"
\r
35 #include "srmresourcestrings.h"
\r
36 #include "doxmresource.h"
\r
37 #include "srmutility.h"
\r
38 #include "ocserverrequest.h"
\r
40 #include "psinterface.h"
\r
41 #include "security_internals.h"
\r
45 #include <strings.h>
\r
48 #define TAG "SRM-PCONF"
\r
50 static const uint64_t CBOR_SIZE = 255;
\r
51 static const uint64_t CBOR_MAX_SIZE = 4400;
\r
52 static const uint8_t PCONF_MAP_SIZE = 4;
\r
54 static OicSecPconf_t *gPconf = NULL;
\r
55 static OCResourceHandle gPconfHandle = NULL;
\r
56 static OicSecPconf_t gDefaultPconf =
\r
58 false, /* bool edp */
\r
59 NULL, /* OicSecPrm *prm */
\r
60 0, /* size_t prmLen */
\r
61 {.val = {0}}, /* OicDpPin_t pin */
\r
62 NULL, /* OicSecPdAcl_t *pdacls */
\r
63 NULL, /* OicUuid_t *pddevs */
\r
64 0, /* size_t pddevLen */
\r
65 {.id = {0}}, /* OicUuid_t deviceID */
\r
66 {.id = {0}}, /* OicUuid_t rowner */
\r
70 * This function frees OicSecPdAcl_t object's fields and object itself.
\r
72 void FreePdAclList(OicSecPdAcl_t* pdacls)
\r
78 //Clean pdacl objecs
\r
79 OicSecPdAcl_t *aclTmp1 = NULL;
\r
80 OicSecPdAcl_t *aclTmp2 = NULL;
\r
81 LL_FOREACH_SAFE(pdacls, aclTmp1, aclTmp2)
\r
83 LL_DELETE(pdacls, aclTmp1);
\r
86 for (i = 0; i < aclTmp1->resourcesLen; i++)
\r
88 OICFree(aclTmp1->resources[i]);
\r
90 OICFree(aclTmp1->resources);
\r
93 if(aclTmp1->periods)
\r
95 for(i = 0; i < aclTmp1->prdRecrLen; i++)
\r
97 OICFree(aclTmp1->periods[i]);
\r
99 OICFree(aclTmp1->periods);
\r
103 if(aclTmp1->recurrences)
\r
105 for(i = 0; i < aclTmp1->prdRecrLen; i++)
\r
107 OICFree(aclTmp1->recurrences[i]);
\r
109 OICFree(aclTmp1->recurrences);
\r
113 //Clean pconf itself
\r
118 void DeletePconfBinData(OicSecPconf_t* pconf)
\r
123 OICFree(pconf->prm);
\r
128 FreePdAclList(pconf->pdacls);
\r
132 OICFree(pconf->pddevs);
\r
134 //Clean pconf itself
\r
139 static size_t OicPdAclSize(const OicSecPdAcl_t *pdAcl)
\r
146 OicSecPdAcl_t *tmp = (OicSecPdAcl_t *)pdAcl;
\r
156 OCStackResult PconfToCBORPayload(const OicSecPconf_t *pconf,uint8_t **payload,size_t *size)
\r
158 if (NULL == pconf || NULL == payload || NULL != *payload || NULL == size)
\r
160 return OC_STACK_INVALID_PARAM;
\r
162 size_t cborLen = *size;
\r
165 cborLen = CBOR_SIZE;
\r
169 OCStackResult ret = OC_STACK_ERROR;
\r
170 CborEncoder encoder = { {.ptr = NULL}, .end = 0};
\r
171 CborEncoder pconfMap = { {.ptr = NULL}, .end = 0};
\r
173 int64_t cborEncoderResult = CborNoError;
\r
174 uint8_t mapSize = PCONF_MAP_SIZE;
\r
176 if (pconf->prmLen > 0)
\r
189 uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
\r
190 VERIFY_NON_NULL(TAG, outPayload, ERROR);
\r
192 cbor_encoder_init(&encoder, outPayload, cborLen, 0);
\r
193 cborEncoderResult = cbor_encoder_create_map(&encoder, &pconfMap, mapSize);
\r
194 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Creating Pconf Map.");
\r
197 cborEncoderResult |= cbor_encode_text_string(&pconfMap, OIC_JSON_EDP_NAME,
\r
198 strlen(OIC_JSON_EDP_NAME));
\r
199 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Encode EDP String.");
\r
200 cborEncoderResult |= cbor_encode_boolean(&pconfMap, pconf->edp);
\r
201 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Convert PconfEDP value");
\r
203 //PRM type -- Not Mandatory
\r
204 if(pconf->prmLen > 0)
\r
206 cborEncoderResult |= cbor_encode_text_string(&pconfMap, OIC_JSON_PRM_NAME,
\r
207 strlen(OIC_JSON_PRM_NAME));
\r
208 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Convert Pconf PRM NAME");
\r
209 CborEncoder prm = { {.ptr = NULL }, .end = 0 };
\r
210 cborEncoderResult |= cbor_encoder_create_array(&pconfMap, &prm, pconf->prmLen);
\r
211 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Convert Pconf PRM value");
\r
213 for (size_t i = 0; i < pconf->prmLen; i++)
\r
215 cborEncoderResult |= cbor_encode_int(&prm, pconf->prm[i]);
\r
216 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Convert Pconf PRM Array");
\r
218 cborEncoderResult |= cbor_encoder_close_container(&pconfMap, &prm);
\r
219 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to close encode array");
\r
223 cborEncoderResult |= cbor_encode_text_string(&pconfMap, OIC_JSON_PIN_NAME,
\r
224 strlen(OIC_JSON_PIN_NAME));
\r
225 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create OIC_JSON_PIN_NAME");
\r
226 cborEncoderResult |= cbor_encode_byte_string(&pconfMap, pconf->pin.val, sizeof(pconf->pin.val));
\r
227 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to convert pin value");
\r
229 //PDACL -- Mandatory
\r
232 cborEncoderResult |= cbor_encode_text_string(&pconfMap, OIC_JSON_PDACL_NAME,
\r
233 strlen(OIC_JSON_PDACL_NAME));
\r
234 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create OIC_JSON_PIN_NAME");
\r
235 OicSecPdAcl_t *pdacl = pconf->pdacls;
\r
236 CborEncoder pdAclArray;
\r
237 cborEncoderResult |= cbor_encoder_create_array(&pconfMap, &pdAclArray,
\r
238 OicPdAclSize(pconf->pdacls));
\r
239 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to creeate _pdacl array");
\r
243 CborEncoder pdAclMap = { {.ptr = NULL }, .end = 0, .added = 0, .flags = 0 };
\r
244 // PDACL Map size - Number of mandatory items
\r
245 uint8_t aclMapSize = 2;
\r
247 if (pdacl->prdRecrLen)
\r
251 if (pdacl->recurrences)
\r
256 cborEncoderResult |= cbor_encoder_create_map(&pdAclArray, &pdAclMap, aclMapSize);
\r
257 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to creeate _pdacl array");
\r
259 // Resources -- Mandatory
\r
260 cborEncoderResult |= cbor_encode_text_string(&pdAclMap, OIC_JSON_RESOURCES_NAME,
\r
261 strlen(OIC_JSON_RESOURCES_NAME));
\r
262 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode resource result");
\r
264 CborEncoder resources = { {.ptr = NULL }, .end = 0, .added = 0, .flags = 0 };
\r
265 cborEncoderResult |= cbor_encoder_create_array(&pdAclMap, &resources,
\r
266 pdacl->resourcesLen);
\r
267 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create resource array");
\r
269 for (size_t i = 0; i < pdacl->resourcesLen; i++)
\r
271 cborEncoderResult |= cbor_encode_text_string(&resources, pdacl->resources[i],
\r
272 strlen(pdacl->resources[i]));
\r
273 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to convert resource array");
\r
275 cborEncoderResult = cbor_encoder_close_container(&pdAclMap, &resources);
\r
276 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to close resource array");
\r
278 // Permissions -- Mandatory
\r
279 cborEncoderResult |= cbor_encode_text_string(&pdAclMap, OIC_JSON_PERMISSION_NAME,
\r
280 strlen(OIC_JSON_PERMISSION_NAME));
\r
281 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create permition string");
\r
282 cborEncoderResult |= cbor_encode_int(&pdAclMap, pdacl->permission);
\r
283 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode permition calue");
\r
285 // Period -- Not Mandatory
\r
286 if (pdacl->periods)
\r
288 CborEncoder period = { {.ptr = NULL }, .end = 0, .added = 0, .flags = 0 };
\r
289 cborEncoderResult |= cbor_encode_text_string(&pdAclMap, OIC_JSON_PERIODS_NAME,
\r
290 strlen(OIC_JSON_PERIODS_NAME));
\r
291 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode period value");
\r
292 cborEncoderResult |= cbor_encoder_create_array(&pdAclMap, &period,
\r
293 pdacl->prdRecrLen);
\r
294 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create array");
\r
296 for (size_t i = 0; i < pdacl->prdRecrLen; i++)
\r
298 cborEncoderResult |= cbor_encode_text_string(&period, pdacl->periods[i],
\r
299 strlen(pdacl->periods[i]));
\r
300 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode period");
\r
302 cborEncoderResult = cbor_encoder_close_container(&pdAclMap, &period);
\r
303 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult,"Failed to close period array");
\r
306 // Period -- Not Mandatory
\r
307 if(0 != pdacl->prdRecrLen && pdacl->recurrences)
\r
309 CborEncoder recurrences = { {.ptr = NULL }, .end = 0, .added = 0, .flags = 0 };
\r
310 cborEncoderResult |= cbor_encode_text_string(&pdAclMap, OIC_JSON_RECURRENCES_NAME,
\r
311 strlen(OIC_JSON_RECURRENCES_NAME));
\r
312 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult,"Failed to encode recurrences");
\r
313 cborEncoderResult |= cbor_encoder_create_array(&pdAclMap, &recurrences,
\r
314 pdacl->prdRecrLen);
\r
315 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create rec array");
\r
317 for (size_t i = 0; i < pdacl->prdRecrLen; i++)
\r
319 cborEncoderResult |= cbor_encode_text_string(&recurrences,
\r
320 pdacl->recurrences[i], strlen(pdacl->recurrences[i]));
\r
321 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode recurrences");
\r
323 cborEncoderResult |= cbor_encoder_close_container(&pdAclMap, &recurrences);
\r
324 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to close rec array");
\r
326 cborEncoderResult |= cbor_encoder_close_container(&pdAclArray, &pdAclMap);
\r
327 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to close acl map");
\r
329 pdacl = pdacl->next;
\r
332 cborEncoderResult |= cbor_encoder_close_container(&pconfMap, &pdAclArray);
\r
333 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to close acl array");
\r
336 //PDDev -- Mandatory
\r
337 //There may not be paired devices if it did not pairing before
\r
338 if (pconf->pddevs && 0 < pconf->pddevLen)
\r
340 cborEncoderResult |= cbor_encode_text_string(&pconfMap, OIC_JSON_PDDEV_LIST_NAME,
\r
341 strlen(OIC_JSON_PDDEV_LIST_NAME));
\r
342 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode pddev");
\r
343 CborEncoder pddev = { {.ptr = NULL }, .end = 0, .added = 0, .flags = 0 };
\r
344 cborEncoderResult |= cbor_encoder_create_array(&pconfMap, &pddev, pconf->pddevLen);
\r
345 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create array");
\r
347 for (size_t i = 0; i < pconf->pddevLen; i++)
\r
349 cborEncoderResult |= cbor_encode_byte_string(&pddev, (uint8_t *)pconf->pddevs[i].id,
\r
350 sizeof(pconf->pddevs[i].id));
\r
351 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode pddev id");
\r
353 cborEncoderResult |= cbor_encoder_close_container(&pconfMap, &pddev);
\r
354 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to close pddev array");
\r
357 //DeviceId -- Mandatory
\r
358 //There may not be devicd id if caller is provisoning tool
\r
359 cborEncoderResult |= cbor_encode_text_string(&pconfMap, OIC_JSON_DEVICE_ID_NAME,
\r
360 strlen(OIC_JSON_DEVICE_ID_NAME));
\r
361 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode device id");
\r
362 cborEncoderResult |= cbor_encode_byte_string(&pconfMap, (uint8_t *)pconf->deviceID.id,
\r
363 sizeof(pconf->deviceID.id));
\r
364 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode deviceID value");
\r
366 //ROwner -- Mandatory
\r
367 cborEncoderResult |= cbor_encode_text_string(&pconfMap, OIC_JSON_ROWNER_NAME,
\r
368 strlen(OIC_JSON_ROWNER_NAME));
\r
369 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode rowner string");
\r
370 cborEncoderResult |= cbor_encode_byte_string(&pconfMap, (uint8_t *)pconf->rowner.id,
\r
371 sizeof(pconf->rowner.id));
\r
372 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode rwoner value");
\r
374 cborEncoderResult |= cbor_encoder_close_container(&encoder, &pconfMap);
\r
375 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to close pconfMap");
\r
377 *size = encoder.ptr - outPayload;
\r
378 *payload = outPayload;
\r
381 if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
\r
383 // reallocate and try again!
\r
384 OICFree(outPayload);
\r
385 // Since the allocated initial memory failed, double the memory.
\r
386 cborLen += encoder.ptr - encoder.end;
\r
387 cborEncoderResult = CborNoError;
\r
388 ret = PconfToCBORPayload(pconf, payload, &cborLen);
\r
391 if ((CborNoError != cborEncoderResult) || (OC_STACK_OK != ret))
\r
393 OICFree(outPayload);
\r
397 ret = OC_STACK_ERROR;
\r
402 OCStackResult CBORPayloadToPconf(const uint8_t *cborPayload, size_t size, OicSecPconf_t **secPconf)
\r
404 if (NULL == cborPayload || NULL == secPconf || NULL != *secPconf || 0 == size)
\r
406 return OC_STACK_INVALID_PARAM;
\r
408 OCStackResult ret = OC_STACK_ERROR;
\r
410 CborValue pconfCbor = { .parser = NULL };
\r
411 CborParser parser = { .end = NULL };
\r
412 CborError cborFindResult = CborNoError;
\r
413 int cborLen = size;
\r
415 cbor_parser_init(cborPayload, cborLen, 0, &parser, &pconfCbor);
\r
416 CborValue pconfMap = { .parser = NULL } ;
\r
417 OicSecPconf_t *pconf = NULL;
\r
418 cborFindResult = cbor_value_enter_container(&pconfCbor, &pconfMap);
\r
419 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to enter map");
\r
420 pconf = (OicSecPconf_t *)OICCalloc(1, sizeof(*pconf));
\r
421 VERIFY_NON_NULL(TAG, pconf, ERROR);
\r
422 while (cbor_value_is_valid(&pconfMap))
\r
426 CborType type = cbor_value_get_type(&pconfMap);
\r
427 if (type == CborTextStringType)
\r
429 cborFindResult = cbor_value_dup_text_string(&pconfMap, &name, &len, NULL);
\r
430 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get value");
\r
431 cborFindResult = cbor_value_advance(&pconfMap);
\r
432 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance value");
\r
438 if(0 == strcmp(OIC_JSON_EDP_NAME, name))
\r
440 cborFindResult = cbor_value_get_boolean(&pconfMap, &pconf->edp);
\r
441 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get value");
\r
443 if (0 == strcmp(OIC_JSON_PRM_NAME, name))
\r
445 CborValue prm = { .parser = NULL };
\r
446 cborFindResult = cbor_value_get_array_length(&pconfMap, &pconf->prmLen);
\r
447 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get length");
\r
448 VERIFY_SUCCESS(TAG, pconf->prmLen != 0, ERROR);
\r
450 pconf->prm = (OicSecPrm_t *)OICCalloc(pconf->prmLen, sizeof(OicSecPrm_t));
\r
451 VERIFY_NON_NULL(TAG, pconf->prm, ERROR);
\r
452 cborFindResult = cbor_value_enter_container(&pconfMap, &prm);
\r
453 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to eneter array");
\r
456 while (cbor_value_is_valid(&prm))
\r
458 cborFindResult = cbor_value_get_int(&prm, (int *)&pconf->prm[i++]);
\r
459 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get value");
\r
460 cborFindResult = cbor_value_advance(&prm);
\r
461 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance value");
\r
465 if (0 == strcmp(OIC_JSON_PIN_NAME, name))
\r
467 uint8_t *pin = NULL;
\r
468 cborFindResult = cbor_value_dup_byte_string(&pconfMap, &pin, &len, NULL);
\r
469 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get value");
\r
470 memcpy(pconf->pin.val, pin, len);
\r
474 //PDACL -- Mandatory
\r
475 if (0 == strcmp(OIC_JSON_PDACL_NAME, name))
\r
477 CborValue pdAclArray = { .parser = NULL};
\r
478 cborFindResult = cbor_value_enter_container(&pconfMap, &pdAclArray);
\r
479 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to enter");
\r
480 OicSecPdAcl_t *headPdacl = NULL;
\r
482 while (cbor_value_is_valid(&pdAclArray))
\r
484 CborValue pdAclMap = { .parser = NULL};
\r
485 cborFindResult = cbor_value_enter_container(&pdAclArray, &pdAclMap);
\r
486 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to enter");
\r
487 OicSecPdAcl_t *pdacl = (OicSecPdAcl_t *) OICCalloc(1, sizeof(OicSecPdAcl_t));
\r
488 VERIFY_NON_NULL(TAG, pdacl, ERROR);
\r
490 while (cbor_value_is_valid(&pdAclMap))
\r
494 CborType type = cbor_value_get_type(&pdAclMap);
\r
495 if (type == CborTextStringType)
\r
497 cborFindResult = cbor_value_dup_text_string(&pdAclMap, &name,
\r
499 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get text");
\r
500 cborFindResult = cbor_value_advance(&pdAclMap);
\r
501 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance value");
\r
505 // Resources -- Mandatory
\r
506 if (strcmp(name, OIC_JSON_RESOURCES_NAME) == 0)
\r
508 CborValue resources = { .parser = NULL };
\r
509 cborFindResult = cbor_value_get_array_length(&pdAclMap,
\r
510 &pdacl->resourcesLen);
\r
511 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get length");
\r
512 cborFindResult = cbor_value_enter_container(&pdAclMap, &resources);
\r
513 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to enter");
\r
514 pdacl->resources = (char **) OICCalloc(pdacl->resourcesLen,
\r
516 VERIFY_NON_NULL(TAG, pdacl->resources, ERROR);
\r
518 while (cbor_value_is_text_string(&resources))
\r
520 cborFindResult = cbor_value_dup_text_string(&resources,
\r
521 &pdacl->resources[i++], &len, NULL);
\r
522 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get text");
\r
523 cborFindResult = cbor_value_advance(&resources);
\r
524 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance");
\r
528 // Permissions -- Mandatory
\r
529 if (strcmp(name, OIC_JSON_PERMISSION_NAME) == 0)
\r
531 cborFindResult = cbor_value_get_uint64(&pdAclMap,
\r
532 (uint64_t *) &pdacl->permission);
\r
533 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get value");
\r
536 // Period -- Not mandatory
\r
537 if (strcmp(name, OIC_JSON_PERIODS_NAME) == 0)
\r
539 CborValue period = { .parser = NULL };
\r
540 cborFindResult = cbor_value_get_array_length(&pdAclMap,
\r
541 &pdacl->prdRecrLen);
\r
542 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get length");
\r
543 cborFindResult = cbor_value_enter_container(&pdAclMap, &period);
\r
544 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to enter");
\r
545 pdacl->periods = (char **) OICCalloc(pdacl->prdRecrLen, sizeof(char*));
\r
546 VERIFY_NON_NULL(TAG, pdacl->periods, ERROR);
\r
548 while (cbor_value_is_text_string(&period))
\r
550 cborFindResult = cbor_value_dup_text_string(&period,
\r
551 &pdacl->periods[i++], &len, NULL);
\r
552 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get text");
\r
553 cborFindResult = cbor_value_advance(&period);
\r
554 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance");
\r
555 pdacl->prdRecrLen++;
\r
559 // Recurrence -- Not mandatory
\r
560 if (strcmp(name, OIC_JSON_RECURRENCES_NAME) == 0)
\r
562 CborValue recurrences = { .parser = NULL };
\r
563 cborFindResult = cbor_value_get_array_length(&pdAclMap, &pdacl->prdRecrLen);
\r
564 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get length");
\r
565 cborFindResult = cbor_value_enter_container(&pdAclMap, &recurrences);
\r
566 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to enter");
\r
567 pdacl->recurrences = (char **) OICCalloc(pdacl->prdRecrLen, sizeof(char*));
\r
568 VERIFY_NON_NULL(TAG, pdacl->recurrences, ERROR);
\r
571 while (cbor_value_is_text_string(&recurrences))
\r
573 cborFindResult = cbor_value_dup_text_string(&recurrences,
\r
574 &pdacl->recurrences[i++], &len, NULL);
\r
575 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get value");
\r
576 cborFindResult = cbor_value_advance(&recurrences);
\r
577 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance");
\r
580 if (type != CborMapType && cbor_value_is_valid(&pdAclMap))
\r
582 cborFindResult = cbor_value_advance(&pdAclMap);
\r
583 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance");
\r
586 if (cbor_value_is_valid(&pdAclArray))
\r
588 cborFindResult = cbor_value_advance(&pdAclArray);
\r
589 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance");
\r
594 pdacl->next = NULL;
\r
595 if (headPdacl == NULL)
\r
601 OicSecPdAcl_t *temp = headPdacl;
\r
606 temp->next = pdacl;
\r
609 pconf->pdacls = headPdacl;
\r
612 //PDDev -- Mandatory
\r
613 if (strcmp(name, OIC_JSON_PDDEV_LIST_NAME) == 0)
\r
615 CborValue pddevs = { .parser = NULL };
\r
616 cborFindResult = cbor_value_get_array_length(&pconfMap, &pconf->pddevLen);
\r
617 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get length");
\r
618 cborFindResult = cbor_value_enter_container(&pconfMap, &pddevs);
\r
619 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to enter");
\r
622 pconf->pddevs = (OicUuid_t *)OICMalloc(pconf->pddevLen * sizeof(OicUuid_t));
\r
623 VERIFY_NON_NULL(TAG, pconf->pddevs, ERROR);
\r
624 while (cbor_value_is_valid(&pddevs))
\r
626 uint8_t *pddev = NULL;
\r
627 cborFindResult = cbor_value_dup_byte_string(&pddevs, &pddev, &len, NULL);
\r
628 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get value");
\r
629 cborFindResult = cbor_value_advance(&pddevs);
\r
630 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance");
\r
631 memcpy(pconf->pddevs[i++].id, pddev, len);
\r
636 //Mandatory - Device Id
\r
637 if (0 == strcmp(OIC_JSON_DEVICE_ID_NAME, name))
\r
639 uint8_t *deviceId = NULL;
\r
640 cborFindResult = cbor_value_dup_byte_string(&pconfMap, &deviceId, &len, NULL);
\r
641 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get deviceID");
\r
642 memcpy(pconf->deviceID.id, deviceId, len);
\r
646 // ROwner -- Mandatory
\r
647 if (0 == strcmp(OIC_JSON_ROWNER_NAME, name))
\r
649 uint8_t *rowner = NULL;
\r
650 cborFindResult = cbor_value_dup_byte_string(&pconfMap, &rowner, &len, NULL);
\r
651 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get rowner");
\r
652 memcpy(pconf->rowner.id, rowner, len);
\r
656 if (CborMapType != type && cbor_value_is_valid(&pconfMap))
\r
658 cborFindResult = cbor_value_advance(&pconfMap);
\r
659 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance");
\r
667 if (CborNoError != cborFindResult)
\r
669 OIC_LOG (ERROR, TAG, "CBORPayloadToPconf failed");
\r
670 DeletePconfBinData(pconf);
\r
672 ret = OC_STACK_ERROR;
\r
677 static bool UpdatePersistentStorage(const OicSecPconf_t * pconf)
\r
681 // Convert PCONF data into Cborpayload for update to persistent storage
\r
682 uint8_t *payload = NULL;
\r
684 if (OC_STACK_OK == PconfToCBORPayload(pconf, &payload, &size) && NULL !=payload)
\r
686 if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_PCONF_NAME, payload, size))
\r
695 static OCEntityHandlerResult HandlePconfGetRequest (const OCEntityHandlerRequest * ehRequest)
\r
697 uint8_t* payload = NULL;
\r
699 OCEntityHandlerResult ehRet = OC_EH_OK;
\r
701 OicSecPconf_t pconf;
\r
702 memset(&pconf, 0, sizeof(OicSecPconf_t));
\r
704 OIC_LOG (DEBUG, TAG, "Pconf EntityHandle processing GET request");
\r
706 if (true == GetDoxmResourceData()->dpc)
\r
708 //Making response elements for Get request
\r
709 if( (true == gPconf->edp) && (gPconf->prm && 0 < gPconf->prmLen) &&
\r
710 (0 < strlen((const char*)gPconf->deviceID.id)) && (0 < strlen((const char*)gPconf->rowner.id)))
\r
713 pconf.prm = gPconf->prm;
\r
714 pconf.prmLen = gPconf->prmLen;
\r
715 memcpy(&pconf.deviceID, &gPconf->deviceID, sizeof(OicUuid_t));
\r
716 memcpy(&pconf.rowner, &gPconf->rowner, sizeof(OicUuid_t));
\r
717 OIC_LOG (DEBUG, TAG, "PCONF - direct pairing enabled");
\r
719 else if (false == gPconf->edp)
\r
722 memcpy(&pconf.rowner, &gPconf->rowner, sizeof(OicUuid_t));
\r
723 OIC_LOG (DEBUG, TAG, "PCONF - direct pairing disable");
\r
727 ehRet= OC_EH_ERROR;
\r
728 OIC_LOG (DEBUG, TAG, "PCONF - error");
\r
733 OIC_LOG (DEBUG, TAG, "DPC == false : Direct-Pairing Disabled");
\r
737 if (OC_STACK_OK != PconfToCBORPayload(gPconf, &payload, &size))
\r
739 ehRet = OC_EH_ERROR;
\r
741 ehRet = (payload ? OC_EH_OK : OC_EH_ERROR);
\r
743 // Send response payload to request originator
\r
744 SendSRMCBORResponse(ehRequest, ehRet, payload, size);
\r
745 OIC_LOG_V(DEBUG, TAG, "%s RetVal %d", __func__, ehRet);
\r
750 static OCEntityHandlerResult HandlePconfPostRequest (const OCEntityHandlerRequest * ehRequest)
\r
752 OCEntityHandlerResult ehRet = OC_EH_OK;
\r
753 OCStackResult res=OC_STACK_OK;
\r
754 OicSecPconf_t* newPconf = NULL;
\r
756 if (true == GetDoxmResourceData()->dpc)
\r
758 // Convert CBOR PCONF data into binary. This will also validate the PCONF data received.
\r
759 uint8_t *payload = ((OCSecurityPayload *) ehRequest->payload)->securityData1;
\r
760 size_t size = ((OCSecurityPayload *) ehRequest->payload)->payloadSize;
\r
763 res = CBORPayloadToPconf(payload, size, &newPconf);
\r
768 OIC_LOG (DEBUG, TAG, "DPC == false : Direct-Pairing Disabled");
\r
769 ehRet = OC_EH_ERROR;
\r
772 if (newPconf && res == OC_STACK_OK)
\r
774 // Check if valid Post request
\r
775 if ((true == newPconf->edp) && (0 < newPconf->prmLen) &&
\r
776 DP_PIN_LENGTH == sizeof((const char*)newPconf->pin.val))
\r
778 OicSecPrm_t *oldPrm = gPconf->prm;
\r
779 OicSecPdAcl_t *oldPdacl = gPconf->pdacls;
\r
781 // Update local PCONF with new PCONF
\r
782 gPconf->edp = true;
\r
783 memcpy(&gPconf->pin, &newPconf->pin, sizeof(OicDpPin_t));
\r
784 gPconf->prm = newPconf->prm;
\r
785 gPconf->prmLen = newPconf->prmLen;
\r
786 gPconf->pdacls = newPconf->pdacls;
\r
787 memcpy(&gPconf->rowner, &newPconf->rowner, sizeof(OicUuid_t));
\r
789 // to delete old value(prm, pdacl)
\r
790 newPconf->prm = oldPrm;
\r
791 newPconf->pdacls = oldPdacl;
\r
793 else if (false == newPconf->edp)
\r
795 gPconf->edp = false;
\r
799 ehRet = OC_EH_ERROR;
\r
803 if(OC_EH_ERROR != ehRet && true == UpdatePersistentStorage(gPconf))
\r
805 ehRet = OC_EH_RESOURCE_CREATED;
\r
808 DeletePconfBinData(newPconf);
\r
812 ehRet = OC_EH_ERROR;
\r
815 // Send payload to request originator
\r
816 SendSRMCBORResponse(ehRequest, ehRet, NULL, 0);
\r
818 OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
\r
823 * This internal method is the entity handler for PCONF resources and
\r
824 * will handle REST request (POST) for them.
\r
826 OCEntityHandlerResult PconfEntityHandler (OCEntityHandlerFlag flag,
\r
827 OCEntityHandlerRequest * ehRequest,
\r
828 void* callbackParameter)
\r
830 OIC_LOG(DEBUG, TAG, "Received request PconfEntityHandler");
\r
831 (void)callbackParameter;
\r
832 OCEntityHandlerResult ehRet = OC_EH_ERROR;
\r
839 if (flag & OC_REQUEST_FLAG)
\r
841 OIC_LOG (DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
\r
842 switch (ehRequest->method)
\r
845 ehRet = HandlePconfGetRequest(ehRequest);
\r
849 ehRet = HandlePconfPostRequest(ehRequest);
\r
852 case OC_REST_DELETE:
\r
856 ehRet = OC_EH_ERROR;
\r
857 SendSRMCBORResponse(ehRequest, ehRet, NULL, 0);
\r
865 * This internal method is used to create '/oic/sec/pconf' resource.
\r
867 OCStackResult CreatePconfResource()
\r
871 ret = OCCreateResource(&gPconfHandle,
\r
872 OIC_RSRC_TYPE_SEC_PCONF,
\r
874 OIC_RSRC_PCONF_URI,
\r
875 PconfEntityHandler,
\r
877 OC_SECURE | OC_EXPLICIT_DISCOVERABLE);
\r
879 if (OC_STACK_OK != ret)
\r
881 OIC_LOG (ERROR, TAG, "Unable to instantiate PCONF resource");
\r
882 DeInitPconfResource();
\r
888 * Get the default value.
\r
889 * @retval the gDefaultPconf pointer;
\r
891 static OicSecPconf_t* GetPconfDefault()
\r
893 OIC_LOG (DEBUG, TAG, "GetPconfDefault");
\r
895 return &gDefaultPconf;
\r
899 * This method is used by SRM to retrieve PCONF resource data..
\r
901 * @retval reference to @ref OicSecPconf_t, binary format of Pconf resource data
\r
903 const OicSecPconf_t* GetPconfResourceData()
\r
909 * Initialize PCONF resource by loading data from persistent storage.
\r
911 * @retval OC_STACK_OK for Success, otherwise some error value
\r
913 OCStackResult InitPconfResource()
\r
915 OCStackResult ret = OC_STACK_ERROR;
\r
917 uint8_t *data = NULL;
\r
920 ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_PCONF_NAME, &data, &size);
\r
921 // If database read failed
\r
922 if (ret != OC_STACK_OK)
\r
924 OIC_LOG(DEBUG, TAG, "ReadSVDataFromPS failed");
\r
928 CBORPayloadToPconf(data, size, &gPconf);
\r
931 if (!data || !gPconf)
\r
933 gPconf = GetPconfDefault();
\r
935 // device id from doxm
\r
936 OicUuid_t deviceId = {.id = {0}};
\r
937 OCStackResult ret = GetDoxmDeviceID( &deviceId);
\r
938 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
\r
939 memcpy(&gPconf->deviceID, &deviceId, sizeof(OicUuid_t));
\r
941 VERIFY_NON_NULL(TAG, gPconf, ERROR);
\r
943 // Instantiate 'oic.sec.pconf'
\r
944 ret = CreatePconfResource();
\r
947 if (OC_STACK_OK != ret)
\r
949 DeInitPconfResource();
\r
956 * Perform cleanup for PCONF resources.
\r
959 * OC_STACK_OK - no error
\r
960 * OC_STACK_ERROR - stack process error
\r
963 OCStackResult DeInitPconfResource()
\r
965 OCStackResult ret = OCDeleteResource(gPconfHandle);
\r
966 if(gPconf!= &gDefaultPconf)
\r
968 DeletePconfBinData(gPconf);
\r
972 if(OC_STACK_OK == ret)
\r
974 return OC_STACK_OK;
\r
978 return OC_STACK_ERROR;
\r
983 * This method might be used to add a paired device id after direct-pairing process complete.
\r
985 * @param pdeviceId ID of the paired device.
\r
987 * @retval OC_STACK_OK for Success, otherwise some error value
\r
989 OCStackResult AddPairedDevice(OicUuid_t *pdeviceId)
\r
991 if (!gPconf || !pdeviceId)
\r
993 return OC_STACK_INVALID_PARAM;
\r
997 OicUuid_t *prevList = gPconf->pddevs;
\r
998 gPconf->pddevs = (OicUuid_t *)OICCalloc(gPconf->pddevLen+1, sizeof(OicUuid_t));
\r
999 if(!gPconf->pddevs)
\r
1001 return OC_STACK_NO_MEMORY;
\r
1003 for (size_t i=0; i<gPconf->pddevLen; i++)
\r
1005 memcpy(&gPconf->pddevs[i], &prevList[i], sizeof(OicUuid_t));
\r
1008 // add new paired device id
\r
1009 memcpy(&gPconf->pddevs[gPconf->pddevLen], pdeviceId, sizeof(OicUuid_t));
\r
1010 gPconf->pddevLen++;
\r
1013 if(true != UpdatePersistentStorage(gPconf))
\r
1015 OIC_LOG (ERROR, TAG, "Fail to update pconf resource");
\r
1016 return OC_STACK_ERROR;
\r
1019 OIC_LOG (ERROR, TAG, "Add paired device success");
\r
1020 return OC_STACK_OK;
\r
1024 * This method might be used by PolicyEngine to retrieve PDACL for a Subject.
\r
1026 * @param subjectId ID of the subject for which PDACL is required.
\r
1027 * @param savePtr is used internally by @ref GetACLResourceData to maintain index between
\r
1028 * successive calls for same subjectId.
\r
1030 * @retval reference to @ref OicSecPdAcl_t if PDACL is found, else NULL
\r
1032 const OicSecPdAcl_t* GetPdAclData(const OicUuid_t* subjectId, OicSecPdAcl_t **savePtr)
\r
1034 OicSecPdAcl_t *pdacl = NULL;
\r
1036 if ( NULL == subjectId)
\r
1042 * savePtr MUST point to NULL if this is the 'first' call to retrieve PDACL for
\r
1045 if (NULL == *savePtr)
\r
1047 pdacl = gPconf->pdacls;
\r
1049 // Find if 'subjectID' is in paired device list.
\r
1050 for(size_t i=0; i<gPconf->pddevLen; i++)
\r
1052 if (memcmp(&(gPconf->pddevs[i]), subjectId, sizeof(OicUuid_t)) == 0)
\r
1061 OicSecPdAcl_t *temp = NULL;
\r
1064 * If this is a 'successive' call, search for location pointed by
\r
1065 * savePtr and assign 'begin' to the next PDACL after it in the linked
\r
1066 * list and start searching from there.
\r
1068 LL_FOREACH(gPconf->pdacls, temp)
\r
1070 if (temp == *savePtr)
\r
1072 pdacl = temp->next;
\r
1079 // Cleanup in case no PDACL is found
\r
1085 * This method return whether device is paired or not.
\r
1087 * @param pdeviceId Target device ID to find in paired list.
\r
1088 * @retval ture if device is already paired, else false
\r
1090 bool IsPairedDevice(const OicUuid_t* pdeviceId)
\r
1092 // Find if 'pdeviceId' is in paired device list.
\r
1093 for(size_t i=0; i<gPconf->pddevLen; i++)
\r
1095 if (memcmp(&(gPconf->pddevs[i]), pdeviceId, sizeof(OicUuid_t)) == 0)
\r