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 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
29 #include "ocserverrequest.h"
30 #include "oic_malloc.h"
31 #include "oic_string.h"
33 #include "ocpayload.h"
35 #include "payload_logging.h"
36 #include "srmresourcestrings.h"
37 #include "aclresource.h"
38 #include "doxmresource.h"
39 #include "resourcemanager.h"
40 #include "srmutility.h"
41 #include "psinterface.h"
43 #include "security_internals.h"
46 #define NUMBER_OF_SEC_PROV_RSCS 4
47 #define NUMBER_OF_DEFAULT_SEC_RSCS 2
49 // CborSize is the default cbor payload size being used.
50 static uint64_t CborSize = 255;
52 static OicSecAcl_t *gAcl = NULL;
53 static OCResourceHandle gAclHandle = NULL;
56 * This function frees OicSecAcl_t object's fields and object itself.
58 static void FreeACE(OicSecAcl_t *ace)
63 OIC_LOG(ERROR, TAG, "Invalid Parameter");
68 for (i = 0; i < ace->resourcesLen; i++)
70 OICFree(ace->resources[i]);
72 OICFree(ace->resources);
77 for (i = 0; i < ace->prdRecrLen; i++)
79 OICFree(ace->periods[i]);
81 OICFree(ace->periods);
87 for (i = 0; i < ace->prdRecrLen; i++)
89 OICFree(ace->recurrences[i]);
91 OICFree(ace->recurrences);
97 // Clean ACL node itself
101 void DeleteACLList(OicSecAcl_t* acl)
105 OicSecAcl_t *aclTmp1 = NULL;
106 OicSecAcl_t *aclTmp2 = NULL;
107 LL_FOREACH_SAFE(acl, aclTmp1, aclTmp2)
109 LL_DELETE(acl, aclTmp1);
115 static size_t OicSecAclSize(const OicSecAcl_t *secAcl)
121 OicSecAcl_t *acl = (OicSecAcl_t *)secAcl;
131 OCStackResult AclToCBORPayload(const OicSecAcl_t *secAcl, uint8_t **payload, size_t *size)
133 OCStackResult ret = OC_STACK_INVALID_PARAM;
134 int64_t cborEncoderResult = CborNoError;
135 uint8_t *outPayload = NULL;
136 size_t cborLen = *size;
137 OicSecAcl_t *acl = (OicSecAcl_t *)secAcl;
138 VERIFY_NON_NULL(TAG, secAcl, ERROR);
141 CborEncoder oicSecAclArray;
149 // Please note: This has been initialized prior to use because of VERIFY macro
151 outPayload = (uint8_t *)OICCalloc(1, cborLen);
152 VERIFY_NON_NULL(TAG, outPayload, ERROR);
153 cbor_encoder_init(&encoder, outPayload, cborLen, 0);
156 cborEncoderResult |= cbor_encoder_create_array(&encoder, &oicSecAclArray, OicSecAclSize(secAcl));
157 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Creating ACL Array.");
161 CborEncoder oicSecAclMap = { {.ptr = NULL }, .end = 0, .added = 0, .flags = 0 };
162 // ACL Map size - Number of mandatory items
163 uint8_t aclMapSize = 4;
169 if (acl->recurrences)
173 cborEncoderResult |= cbor_encoder_create_map(&oicSecAclArray, &oicSecAclMap, aclMapSize);
174 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Creating ACL Map");
176 // Subject -- Mandatory
177 cborEncoderResult |= cbor_encode_text_string(&oicSecAclMap, OIC_JSON_SUBJECT_NAME,
178 sizeof(OIC_JSON_SUBJECT_NAME) - 1);
179 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Subject Name Tag.");
181 if (memcmp(&(acl->subject), &WILDCARD_SUBJECT_ID, sizeof(OicUuid_t)) == 0)
183 inLen = WILDCARD_SUBJECT_ID_LEN;
187 inLen = sizeof(OicUuid_t);
189 cborEncoderResult |= cbor_encode_byte_string(&oicSecAclMap, (uint8_t *)acl->subject.id, inLen);
190 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Subject Id Value.");
193 CborEncoder resources = { {.ptr = NULL }, .end = 0, .added = 0, .flags = 0 };
194 cborEncoderResult |= cbor_encode_text_string(&oicSecAclMap, OIC_JSON_RESOURCES_NAME,
195 sizeof(OIC_JSON_RESOURCES_NAME) -1);
196 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Resource Name Tag.");
197 cborEncoderResult |= cbor_encoder_create_array(&oicSecAclMap, &resources, acl->resourcesLen);
198 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Resource Name Array.");
199 for (size_t i = 0; i < acl->resourcesLen; i++)
201 cborEncoderResult |= cbor_encode_text_string(&resources, acl->resources[i],
202 strlen(acl->resources[i]));
203 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Resource Name Array Value.");
206 cborEncoderResult |= cbor_encoder_close_container(&oicSecAclMap, &resources);
207 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Resource Name Array.");
209 // Permissions -- Mandatory
210 cborEncoderResult |= cbor_encode_text_string(&oicSecAclMap, OIC_JSON_PERMISSION_NAME,
211 sizeof(OIC_JSON_PERMISSION_NAME) -1);
212 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Permission Name Tag.");
213 cborEncoderResult |= cbor_encode_int(&oicSecAclMap, acl->permission);
214 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Permission Name Value.");
216 // Period -- Not Mandatory
219 CborEncoder period = { {.ptr = NULL }, .end = 0, .added = 0, .flags = 0 };
220 cborEncoderResult |= cbor_encode_text_string(&oicSecAclMap, OIC_JSON_PERIODS_NAME,
221 sizeof(OIC_JSON_PERIODS_NAME) -1);
222 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Period Tag.");
223 cborEncoderResult |= cbor_encoder_create_array(&oicSecAclMap, &period, acl->prdRecrLen);
224 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Period Array.");
225 for (size_t i = 0; i < acl->prdRecrLen; i++)
227 cborEncoderResult |= cbor_encode_text_string(&period, acl->periods[i],
228 strlen(acl->periods[i]));
229 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Period Value in Array.");
232 cborEncoderResult |= cbor_encoder_close_container(&oicSecAclMap, &period);
233 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Period Array.");
236 // Recurrence -- Not Mandatory
237 if (acl->recurrences)
239 CborEncoder recurrences = { {.ptr = NULL }, .end = 0, .added = 0, .flags = 0 };
240 cborEncoderResult |= cbor_encode_text_string(&oicSecAclMap, OIC_JSON_RECURRENCES_NAME,
241 sizeof(OIC_JSON_RECURRENCES_NAME) -1);
242 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Recurrence Tag.");
243 cborEncoderResult |= cbor_encoder_create_array(&oicSecAclMap, &recurrences, acl->prdRecrLen);
244 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Recurrence Array.");
245 for (size_t i = 0; i < acl->prdRecrLen; i++)
247 cborEncoderResult |= cbor_encode_text_string(&recurrences, acl->recurrences[i],
248 strlen(acl->recurrences[i]));
249 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Recurrence Array Value.");
251 cborEncoderResult |= cbor_encoder_close_container(&oicSecAclMap, &recurrences);
252 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Recurrence Array");
255 cborEncoderResult |= cbor_encode_text_string(&oicSecAclMap, OIC_JSON_OWNERS_NAME,
256 sizeof(OIC_JSON_OWNERS_NAME) - 1);
257 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owner Name.");
258 CborEncoder owners = { {.ptr = NULL }, .end = 0, .added = 0, .flags = 0 };
259 cborEncoderResult |= cbor_encoder_create_array(&oicSecAclMap, &owners, acl->ownersLen);
260 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owner Array.");
261 for (size_t i = 0; i < acl->ownersLen; i++)
263 cborEncoderResult = cbor_encode_byte_string(&owners, (uint8_t *)acl->owners[i].id,
264 sizeof(acl->owners[i].id));
265 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owner Array Value.");
268 cborEncoderResult |= cbor_encoder_close_container(&oicSecAclMap, &owners);
269 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Owner Array.");
271 cborEncoderResult |= cbor_encoder_close_container(&oicSecAclArray, &oicSecAclMap);
272 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing ACL Map.");
276 cborEncoderResult |= cbor_encoder_close_container(&encoder, &oicSecAclArray);
277 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing ACL Array.");
279 if (CborNoError == cborEncoderResult)
281 *size = encoder.ptr - outPayload;
282 *payload = outPayload;
286 if (CborErrorOutOfMemory == cborEncoderResult)
288 // reallocate and try again!
290 // Since the allocated initial memory failed, double the memory.
291 cborLen += encoder.ptr - encoder.end;
292 cborEncoderResult = CborNoError;
293 if (OC_STACK_OK == AclToCBORPayload(secAcl, &outPayload, &cborLen))
296 *payload = outPayload;
301 if (cborEncoderResult != CborNoError)
306 ret = OC_STACK_ERROR;
312 // This function converts CBOR format to ACL data.
313 // Caller needs to invoke 'free' when done using
314 // note: This function is used in unit test hence not declared static,
315 OicSecAcl_t* CBORPayloadToAcl(const uint8_t *cborPayload, const size_t size)
317 if (NULL == cborPayload)
322 CborValue aclCbor = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
323 CborParser parser = { .end = NULL, .flags = 0 };
324 CborError cborFindResult = CborNoError;
325 cbor_parser_init(cborPayload, size, 0, &parser, &aclCbor);
327 OicSecAcl_t *headAcl = NULL;
329 CborValue aclArray = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
330 cborFindResult = cbor_value_enter_container(&aclCbor, &aclArray);
331 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering ACL Array.");
333 while (cbor_value_is_valid(&aclArray))
335 CborValue aclMap = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
336 cborFindResult = cbor_value_enter_container(&aclArray, &aclMap);
337 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering ACL Map.");
339 OicSecAcl_t *acl = (OicSecAcl_t *) OICCalloc(1, sizeof(OicSecAcl_t));
340 VERIFY_NON_NULL(TAG, acl, ERROR);
342 while (cbor_value_is_valid(&aclMap))
346 CborType type = cbor_value_get_type(&aclMap);
347 if (type == CborTextStringType)
349 cborFindResult = cbor_value_dup_text_string(&aclMap, &name, &len, NULL);
350 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Name in ACL Map.");
351 cborFindResult = cbor_value_advance(&aclMap);
352 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Value in ACL Map.");
356 // Subject -- Mandatory
357 if (strcmp(name, OIC_JSON_SUBJECT_NAME) == 0)
359 uint8_t *subjectId = NULL;
360 cborFindResult = cbor_value_dup_byte_string(&aclMap, &subjectId, &len, NULL);
361 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a Subject Name Value.");
362 memcpy(acl->subject.id, subjectId, len);
366 // Resources -- Mandatory
367 if (strcmp(name, OIC_JSON_RESOURCES_NAME) == 0)
369 CborValue resources = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
370 cborFindResult = cbor_value_get_array_length(&aclMap, &acl->resourcesLen);
371 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a Rec Array Len Value.");
373 cborFindResult = cbor_value_enter_container(&aclMap, &resources);
374 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering a Rec Array.");
376 acl->resources = (char **) OICMalloc(acl->resourcesLen * sizeof(char*));
377 VERIFY_NON_NULL(TAG, acl->resources, ERROR);
379 while (cbor_value_is_text_string(&resources))
381 cborFindResult = cbor_value_dup_text_string(&resources, &acl->resources[i++],
383 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a Rec Array Value.");
384 cborFindResult = cbor_value_advance(&resources);
385 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a Rec Array Advance.");
389 // Permissions -- Mandatory
390 if (strcmp(name, OIC_JSON_PERMISSION_NAME) == 0)
392 cborFindResult = cbor_value_get_uint64(&aclMap, (uint64_t *) &acl->permission);
393 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a PERM Value.");
396 // Period -- Not mandatory
397 if (strcmp(name, OIC_JSON_PERIODS_NAME) == 0)
399 CborValue period = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
400 cborFindResult = cbor_value_get_array_length(&aclMap, &acl->prdRecrLen);
401 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a Period Array Len.");
402 cborFindResult = cbor_value_enter_container(&aclMap, &period);
403 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a Period Array Map.");
405 while (cbor_value_is_text_string(&period))
407 cborFindResult = cbor_value_dup_text_string(&period, &acl->periods[i++],
409 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a Period Array Value.");
410 cborFindResult = cbor_value_advance(&period);
411 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing a Period Array.");
415 // Recurrence -- Not mandatory
416 if (strcmp(name, OIC_JSON_RECURRENCES_NAME) == 0)
418 CborValue recurrences = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
419 cborFindResult = cbor_value_enter_container(&aclMap, &recurrences);
420 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Adding Recurrence Array.");
422 while (cbor_value_is_text_string(&recurrences))
424 cborFindResult = cbor_value_dup_text_string(&recurrences,
425 &acl->recurrences[i++], &len, NULL);
426 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Adding Recurrence Array Value.");
427 cborFindResult = cbor_value_advance(&recurrences);
428 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Closing Recurrence Array.");
432 // Owners -- Mandatory
433 if (strcmp(name, OIC_JSON_OWNERS_NAME) == 0)
435 CborValue owners = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
436 cborFindResult = cbor_value_get_array_length(&aclMap, &acl->ownersLen);
437 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Getting Owner Array Len.");
438 cborFindResult = cbor_value_enter_container(&aclMap, &owners);
439 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering Owner Array.");
441 acl->owners = (OicUuid_t *)OICMalloc(acl->ownersLen * sizeof(OicUuid_t));
442 VERIFY_NON_NULL(TAG, acl->owners, ERROR);
443 while (cbor_value_is_valid(&owners))
445 uint8_t *owner = NULL;
446 cborFindResult = cbor_value_dup_byte_string(&owners, &owner, &len, NULL);
447 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Adding Owner Array Value.");
448 cborFindResult = cbor_value_advance(&owners);
449 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Owners Array.");
450 memcpy(acl->owners[i].id, owner, len);
455 if (type != CborMapType && cbor_value_is_valid(&aclMap))
457 cborFindResult = cbor_value_advance(&aclMap);
458 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing the Array.");
469 OicSecAcl_t *temp = headAcl;
476 if (cbor_value_is_valid(&aclArray))
478 cborFindResult = cbor_value_advance(&aclArray);
479 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing ACL Array.");
484 if (cborFindResult != CborNoError)
486 DeleteACLList(headAcl);
493 * This method removes ACE for the subject and resource from the ACL
495 * @param subject of the ACE
496 * @param resource of the ACE
499 * ::OC_STACK_RESOURCE_DELETED on success
500 * ::OC_STACK_NO_RESOURCE on failure to find the appropriate ACE
501 * ::OC_STACK_INVALID_PARAM on invalid parameter
503 static OCStackResult RemoveACE(const OicUuid_t * subject, const char * resource)
505 OIC_LOG(DEBUG, TAG, "IN RemoveACE");
507 OicSecAcl_t *acl = NULL;
508 OicSecAcl_t *tempAcl = NULL;
509 bool deleteFlag = false;
510 OCStackResult ret = OC_STACK_NO_RESOURCE;
512 if (memcmp(subject->id, &WILDCARD_SUBJECT_ID, sizeof(subject->id)) == 0)
514 OIC_LOG_V(ERROR, TAG, "%s received invalid parameter", __func__ );
515 return OC_STACK_INVALID_PARAM;
518 //If resource is NULL then delete all the ACE for the subject.
519 if (NULL == resource || resource[0] == '\0')
521 LL_FOREACH_SAFE(gAcl, acl, tempAcl)
523 if (memcmp(acl->subject.id, subject->id, sizeof(subject->id)) == 0)
525 LL_DELETE(gAcl, acl);
533 //Looping through ACL to find the right ACE to delete. If the required resource is the only
534 //resource in the ACE for the subject then delete the whole ACE. If there are more resources
535 //than the required resource in the ACE, for the subject then just delete the resource from
537 LL_FOREACH_SAFE(gAcl, acl, tempAcl)
539 if (memcmp(acl->subject.id, subject->id, sizeof(subject->id)) == 0)
541 if (1 == acl->resourcesLen && strcmp(acl->resources[0], resource) == 0)
543 LL_DELETE(gAcl, acl);
552 for (i = 0; i < acl->resourcesLen; i++)
554 if (strcmp(acl->resources[i], resource) == 0)
560 if (0 <= (int) resPos)
562 OICFree(acl->resources[resPos]);
563 acl->resources[resPos] = NULL;
564 acl->resourcesLen -= 1;
565 for (i = resPos; i < acl->resourcesLen; i++)
567 acl->resources[i] = acl->resources[i + 1];
579 // In case of unit test do not update persistant storage.
580 if (memcmp(subject->id, &WILDCARD_SUBJECT_B64_ID, sizeof(subject->id)) == 0)
582 ret = OC_STACK_RESOURCE_DELETED;
586 uint8_t *payload = NULL;
588 if (OC_STACK_OK == AclToCBORPayload(gAcl, &payload, &size))
590 if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_ACL_NAME, payload, size))
592 ret = OC_STACK_RESOURCE_DELETED;
602 * This method parses the query string received for REST requests and
603 * retrieves the 'subject' field.
605 * @param query querystring passed in REST request
606 * @param subject subject UUID parsed from query string
608 * @return true if query parsed successfully and found 'subject', else false.
610 static bool GetSubjectFromQueryString(const char *query, OicUuid_t *subject)
612 OicParseQueryIter_t parseIter = { .attrPos = NULL };
614 ParseQueryIterInit((unsigned char *) query, &parseIter);
616 while (GetNextQuery (&parseIter))
618 if (strncasecmp((char *) parseIter.attrPos, OIC_JSON_SUBJECT_NAME, parseIter.attrLen) == 0)
620 VERIFY_SUCCESS(TAG, 0 != parseIter.valLen, ERROR);
621 memcpy(subject->id, parseIter.valPos, parseIter.valLen);
631 * This method parses the query string received for REST requests and
632 * retrieves the 'resource' field.
634 * @param query querystring passed in REST request
635 * @param resource resource parsed from query string
636 * @param resourceSize size of the memory pointed to resource
638 * @return true if query parsed successfully and found 'resource', else false.
640 static bool GetResourceFromQueryString(const char *query, char *resource, size_t resourceSize)
642 OicParseQueryIter_t parseIter = { .attrPos = NULL };
644 ParseQueryIterInit((unsigned char *) query, &parseIter);
646 while (GetNextQuery (&parseIter))
648 if (strncasecmp((char *) parseIter.attrPos, OIC_JSON_RESOURCES_NAME, parseIter.attrLen)
651 VERIFY_SUCCESS(TAG, 0 != parseIter.valLen, ERROR);
652 OICStrcpy(resource, resourceSize, (char *) parseIter.valPos);
662 static OCEntityHandlerResult HandleACLGetRequest(const OCEntityHandlerRequest *ehRequest)
664 OIC_LOG(INFO, TAG, "HandleACLGetRequest processing the request");
665 uint8_t* payload = NULL;
667 OCEntityHandlerResult ehRet;
669 // Process the REST querystring parameters
670 if (ehRequest->query)
672 OIC_LOG(DEBUG, TAG, "HandleACLGetRequest processing query");
674 OicUuid_t subject = {.id= { 0 } };
675 char resource[MAX_URI_LENGTH] = { 0 };
677 OicSecAcl_t *savePtr = NULL;
678 const OicSecAcl_t *currentAce = NULL;
680 // 'Subject' field is MUST for processing a querystring in REST request.
681 VERIFY_SUCCESS(TAG, true == GetSubjectFromQueryString(ehRequest->query, &subject), ERROR);
683 GetResourceFromQueryString(ehRequest->query, resource, sizeof(resource));
686 * TODO : Currently, this code only provides one ACE for a Subject.
687 * Below code needs to be updated for scenarios when Subject have
688 * multiple ACE's in ACL resource.
690 while ((currentAce = GetACLResourceData(&subject, &savePtr)))
693 * If REST querystring contains a specific resource, we need
694 * to search for that resource in ACE.
696 if (resource[0] != '\0')
698 for (size_t n = 0; n < currentAce->resourcesLen; n++)
700 if ((currentAce->resources[n])
701 && (0 == strcmp(resource, currentAce->resources[n])
702 || 0 == strcmp(WILDCARD_RESOURCE_URI, currentAce->resources[n])))
704 // Convert ACL data into CBOR format for transmission
705 if (OC_STACK_OK != AclToCBORPayload(currentAce, &payload, &size))
715 // Convert ACL data into CBOR format for transmission
716 if (OC_STACK_OK != AclToCBORPayload(currentAce, &payload, &size))
726 // Convert ACL data into CBOR format for transmission.
727 if (OC_STACK_OK != AclToCBORPayload(gAcl, &payload, &size))
733 // A device should always have a default acl. Therefore, payload should never be NULL.
734 ehRet = (payload ? OC_EH_OK : OC_EH_ERROR);
736 // Send response payload to request originator
737 SendSRMCBORResponse(ehRequest, ehRet, payload);
739 OIC_LOG_V(DEBUG, TAG, "%s RetVal %d", __func__, ehRet);
743 static OCEntityHandlerResult HandleACLPostRequest(const OCEntityHandlerRequest *ehRequest)
745 OIC_LOG(INFO, TAG, "HandleACLPostRequest processing the request");
746 OCEntityHandlerResult ehRet = OC_EH_ERROR;
748 // Convert CBOR into ACL data and update to SVR buffers. This will also validate the ACL data received.
749 uint8_t *payload = ((OCSecurityPayload *) ehRequest->payload)->securityData1;;
752 OicSecAcl_t *newAcl = CBORPayloadToAcl(payload, CborSize);
755 // Append the new ACL to existing ACL
756 LL_APPEND(gAcl, newAcl);
758 // In case of unit test do not update persistant storage.
759 if (memcmp(newAcl->subject.id, &WILDCARD_SUBJECT_ID, sizeof(newAcl->subject.id)) == 0
760 || memcmp(newAcl->subject.id, &WILDCARD_SUBJECT_B64_ID, sizeof(newAcl->subject.id)) == 0)
762 ehRet = OC_EH_RESOURCE_CREATED;
766 uint8_t *cborPayload = NULL;
767 if (OC_STACK_OK == AclToCBORPayload(gAcl, &cborPayload, &size))
769 if (UpdateSecureResourceInPS(OIC_JSON_ACL_NAME, cborPayload, size) == OC_STACK_OK)
771 ehRet = OC_EH_RESOURCE_CREATED;
778 // Send payload to request originator
779 SendSRMCBORResponse(ehRequest, ehRet, NULL);
781 OIC_LOG_V(DEBUG, TAG, "%s RetVal %d", __func__, ehRet);
785 static OCEntityHandlerResult HandleACLDeleteRequest(const OCEntityHandlerRequest *ehRequest)
787 OIC_LOG(DEBUG, TAG, "Processing ACLDeleteRequest");
788 OCEntityHandlerResult ehRet = OC_EH_ERROR;
789 OicUuid_t subject = { .id= { 0 } };
790 char resource[MAX_URI_LENGTH] = { 0 };
792 VERIFY_NON_NULL(TAG, ehRequest->query, ERROR);
794 // 'Subject' field is MUST for processing a querystring in REST request.
795 VERIFY_SUCCESS(TAG, true == GetSubjectFromQueryString(ehRequest->query, &subject), ERROR);
797 GetResourceFromQueryString(ehRequest->query, resource, sizeof(resource));
799 if (OC_STACK_RESOURCE_DELETED == RemoveACE(&subject, resource))
801 ehRet = OC_EH_RESOURCE_DELETED;
805 // Send payload to request originator
806 SendSRMCBORResponse(ehRequest, ehRet, NULL);
811 OCEntityHandlerResult ACLEntityHandler(OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehRequest,
812 void* callbackParameter)
814 OIC_LOG(DEBUG, TAG, "Received request ACLEntityHandler");
815 (void)callbackParameter;
816 OCEntityHandlerResult ehRet = OC_EH_ERROR;
823 if (flag & OC_REQUEST_FLAG)
825 // TODO : Handle PUT method
826 OIC_LOG(DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
827 switch (ehRequest->method)
830 ehRet = HandleACLGetRequest(ehRequest);
834 ehRet = HandleACLPostRequest(ehRequest);
838 ehRet = HandleACLDeleteRequest(ehRequest);
843 SendSRMCBORResponse(ehRequest, ehRet, NULL);
851 * This internal method is used to create '/oic/sec/acl' resource.
853 static OCStackResult CreateACLResource()
857 ret = OCCreateResource(&gAclHandle,
858 OIC_RSRC_TYPE_SEC_ACL,
863 OC_OBSERVABLE | OC_SECURE | OC_EXPLICIT_DISCOVERABLE);
865 if (OC_STACK_OK != ret)
867 OIC_LOG(FATAL, TAG, "Unable to instantiate ACL resource");
873 // This function sets the default ACL and is defined for the unit test only.
874 OCStackResult SetDefaultACL(OicSecAcl_t *acl)
880 OCStackResult GetDefaultACL(OicSecAcl_t** defaultAcl)
882 OCStackResult ret = OC_STACK_ERROR;
884 OicUuid_t ownerId = { .id = { 0 } };
887 * TODO In future, when new virtual resources will be added in OIC
888 * specification, Iotivity stack should be able to add them in
889 * existing SVR database. To support this, we need to add 'versioning'
890 * mechanism in SVR database.
893 const char *rsrcs[] = {
894 OC_RSRVD_WELL_KNOWN_URI,
896 OC_RSRVD_PLATFORM_URI,
897 OC_RSRVD_RESOURCE_TYPES_URI,
899 OC_RSRVD_PRESENCE_URI,
900 #endif //WITH_PRESENCE
908 return OC_STACK_INVALID_PARAM;
911 OicSecAcl_t *acl = (OicSecAcl_t *) OICCalloc(1, sizeof(OicSecAcl_t));
912 VERIFY_NON_NULL(TAG, acl, ERROR);
914 // Subject -- Mandatory
915 memcpy(&(acl->subject), &WILDCARD_SUBJECT_ID, sizeof(acl->subject));
917 // Resources -- Mandatory
918 acl->resourcesLen = sizeof(rsrcs) / sizeof(rsrcs[0]);
920 acl->resources = (char**) OICCalloc(acl->resourcesLen, sizeof(char*));
921 VERIFY_NON_NULL(TAG, (acl->resources), ERROR);
923 for (size_t i = 0; i < acl->resourcesLen; i++)
925 size_t len = strlen(rsrcs[i]) + 1;
926 acl->resources[i] = (char*) OICMalloc(len * sizeof(char));
927 VERIFY_NON_NULL(TAG, (acl->resources[i]), ERROR);
928 OICStrcpy(acl->resources[i], len, rsrcs[i]);
931 acl->permission = PERMISSION_READ;
934 acl->recurrences = NULL;
936 // Device ID is the owner of this default ACL
937 if (GetDoxmResourceData() != NULL)
939 ret = GetDoxmDeviceID(&ownerId);
940 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, FATAL);
944 OCRandomUuidResult rdm = OCGenerateUuid(ownerId.id);
945 VERIFY_SUCCESS(TAG, RAND_UUID_OK == rdm, FATAL);
948 acl->owners = (OicUuid_t*) OICMalloc(sizeof(OicUuid_t));
949 VERIFY_NON_NULL(TAG, (acl->owners), ERROR);
950 memcpy(acl->owners, &ownerId, sizeof(OicUuid_t));
959 if (ret != OC_STACK_OK)
968 OCStackResult InitACLResource()
970 OCStackResult ret = OC_STACK_ERROR;
972 uint8_t *data = NULL;
974 ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_ACL_NAME, &data, &size);
975 // If database read failed
976 if (ret != OC_STACK_OK)
978 OIC_LOG(DEBUG, TAG, "ReadSVDataFromPS failed");
982 // Read ACL resource from PS
983 gAcl = CBORPayloadToAcl(data, size);
986 * If SVR database in persistent storage got corrupted or
987 * is not available for some reason, a default ACL is created
988 * which allows user to initiate ACL provisioning again.
992 GetDefaultACL(&gAcl);
993 // TODO Needs to update persistent storage
995 VERIFY_NON_NULL(TAG, gAcl, FATAL);
997 // Instantiate 'oic.sec.acl'
998 ret = CreateACLResource();
1001 if (OC_STACK_OK != ret)
1003 DeInitACLResource();
1008 OCStackResult DeInitACLResource()
1010 OCStackResult ret = OCDeleteResource(gAclHandle);
1015 DeleteACLList(gAcl);
1021 const OicSecAcl_t* GetACLResourceData(const OicUuid_t* subjectId, OicSecAcl_t **savePtr)
1023 OicSecAcl_t *acl = NULL;
1024 OicSecAcl_t *begin = NULL;
1026 if (NULL == subjectId)
1032 * savePtr MUST point to NULL if this is the 'first' call to retrieve ACL for
1035 if (NULL == *savePtr)
1042 * If this is a 'successive' call, search for location pointed by
1043 * savePtr and assign 'begin' to the next ACL after it in the linked
1044 * list and start searching from there.
1046 LL_FOREACH(gAcl, acl)
1048 if (acl == *savePtr)
1055 // Find the next ACL corresponding to the 'subjectID' and return it.
1056 LL_FOREACH(begin, acl)
1058 if (memcmp(&(acl->subject), subjectId, sizeof(OicUuid_t)) == 0)
1065 // Cleanup in case no ACL is found
1070 OCStackResult InstallNewACL(const uint8_t *cborPayload, const size_t size)
1072 OCStackResult ret = OC_STACK_ERROR;
1074 // Convert CBOR format to ACL data. This will also validate the ACL data received.
1075 OicSecAcl_t* newAcl = CBORPayloadToAcl(cborPayload, size);
1079 // Append the new ACL to existing ACL
1080 LL_APPEND(gAcl, newAcl);
1082 // Update persistent storage only if it is not WILDCARD_SUBJECT_ID
1083 if (memcmp(newAcl->subject.id, &WILDCARD_SUBJECT_ID, sizeof(newAcl->subject.id)) == 0
1084 || memcmp(newAcl->subject.id, &WILDCARD_SUBJECT_B64_ID, sizeof(newAcl->subject.id)) == 0)
1091 uint8_t *payload = NULL;
1092 if (OC_STACK_OK == AclToCBORPayload(gAcl, &payload, &size))
1094 if (UpdateSecureResourceInPS(OIC_JSON_ACL_NAME, payload, size) == OC_STACK_OK)
1107 * This function generates default ACL for security resource in case of owned status.
1109 * @return Default ACL for security resource.
1111 static OicSecAcl_t* GetSecDefaultACL()
1113 const char *sec_rsrcs[] = {
1117 OicUuid_t ownerId = {.id = {0}};
1118 OCStackResult res = OC_STACK_ERROR;
1119 OicSecAcl_t* newDefaultAcl = (OicSecAcl_t*)OICCalloc(1, sizeof(OicSecAcl_t));
1120 VERIFY_NON_NULL(TAG, newDefaultAcl, ERROR);
1122 // Subject -- Mandatory
1123 memcpy(&(newDefaultAcl->subject), &WILDCARD_SUBJECT_ID, WILDCARD_SUBJECT_ID_LEN);
1125 // Resources -- Mandatory
1126 newDefaultAcl->resourcesLen = NUMBER_OF_DEFAULT_SEC_RSCS;
1127 newDefaultAcl->resources = (char**)OICCalloc(NUMBER_OF_DEFAULT_SEC_RSCS, sizeof(char*));
1128 VERIFY_NON_NULL(TAG, (newDefaultAcl->resources), ERROR);
1130 for (size_t i = 0; i < NUMBER_OF_DEFAULT_SEC_RSCS; i++)
1132 size_t len = strlen(sec_rsrcs[i]) + 1;
1133 newDefaultAcl->resources[i] = (char*)OICMalloc(len * sizeof(char));
1134 VERIFY_NON_NULL(TAG, (newDefaultAcl->resources[i]), ERROR);
1135 OICStrcpy(newDefaultAcl->resources[i], len, sec_rsrcs[i]);
1138 // Permissions -- Mandatory
1139 newDefaultAcl->permission = PERMISSION_READ;
1141 //Period -- Not Mandatory
1142 newDefaultAcl->prdRecrLen = 0;
1143 newDefaultAcl->periods = NULL;
1145 //Recurrence -- Not Mandatory
1146 newDefaultAcl->recurrences = NULL;
1148 // Device ID is the owner of this default ACL
1149 res = GetDoxmDeviceID(&ownerId);
1150 VERIFY_SUCCESS(TAG, OC_STACK_OK == res, FATAL);
1152 // Owners -- Mandatory
1153 newDefaultAcl->ownersLen = 1;
1154 newDefaultAcl->owners = (OicUuid_t*)OICMalloc(sizeof(OicUuid_t));
1155 VERIFY_NON_NULL(TAG, (newDefaultAcl->owners), ERROR);
1156 memcpy(newDefaultAcl->owners, &ownerId, sizeof(OicUuid_t));
1158 return newDefaultAcl;
1160 DeleteACLList(newDefaultAcl);
1165 OCStackResult UpdateDefaultSecProvACL()
1167 OCStackResult ret = OC_STACK_OK;
1168 OicSecAcl_t *acl = NULL;
1169 OicSecAcl_t *tmp = NULL;
1173 int matchedRsrc = 0;
1174 bool isRemoved = false;
1176 LL_FOREACH_SAFE(gAcl, acl, tmp)
1178 //Find default security resource ACL
1179 if(memcmp(&acl->subject, &WILDCARD_SUBJECT_ID, sizeof(OicUuid_t)) == 0 &&
1180 ((PERMISSION_READ | PERMISSION_WRITE) == acl->permission))
1184 for(size_t i = 0; i < acl->resourcesLen; i++)
1186 if(strncmp(acl->resources[i], OIC_RSRC_DOXM_URI,
1187 strlen(OIC_RSRC_DOXM_URI) + 1) == 0 ||
1188 strncmp(acl->resources[i], OIC_RSRC_CRED_URI,
1189 strlen(OIC_RSRC_CRED_URI) + 1) == 0 ||
1190 strncmp(acl->resources[i], OIC_RSRC_ACL_URI,
1191 strlen(OIC_RSRC_ACL_URI) + 1) == 0 ||
1192 strncmp(acl->resources[i], OIC_RSRC_PSTAT_URI,
1193 strlen(OIC_RSRC_PSTAT_URI) + 1) == 0)
1199 //If default security resource ACL is detected, delete it.
1200 if(NUMBER_OF_SEC_PROV_RSCS == matchedRsrc)
1202 LL_DELETE(gAcl, acl);
1212 * Generate new security resource ACL as follows :
1214 * resources : '/oic/sec/doxm', '/oic/sec/pstat'
1217 OicSecAcl_t *newDefaultAcl = GetSecDefaultACL();
1220 LL_APPEND(gAcl, newDefaultAcl);
1223 uint8_t *payload = NULL;
1224 if (OC_STACK_OK == AclToCBORPayload(gAcl, &payload, &size))
1226 if (UpdateSecureResourceInPS(OIC_JSON_ACL_NAME, payload, size) == OC_STACK_OK)