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 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
25 #include "oic_malloc.h"
26 #include "oic_string.h"
29 #include "resourcemanager.h"
30 #include "aclresource.h"
31 #include "psinterface.h"
33 #include "srmresourcestrings.h"
34 #include "doxmresource.h"
35 #include "srmutility.h"
36 #include "ocserverrequest.h"
46 OicSecAcl_t *gAcl = NULL;
47 static OCResourceHandle gAclHandle = NULL;
50 * This function frees OicSecAcl_t object's fields and object itself.
52 static void FreeACE(OicSecAcl_t *ace)
57 OC_LOG (ERROR, TAG, "Invalid Parameter");
62 for (i = 0; i < ace->resourcesLen; i++)
64 OICFree(ace->resources[i]);
66 OICFree(ace->resources);
71 for(i = 0; i < ace->prdRecrLen; i++)
73 OICFree(ace->periods[i]);
75 OICFree(ace->periods);
81 for(i = 0; i < ace->prdRecrLen; i++)
83 OICFree(ace->recurrences[i]);
85 OICFree(ace->recurrences);
91 // Clean ACL node itself
95 void DeleteACLList(OicSecAcl_t* acl)
99 OicSecAcl_t *aclTmp1 = NULL;
100 OicSecAcl_t *aclTmp2 = NULL;
101 LL_FOREACH_SAFE(acl, aclTmp1, aclTmp2)
103 LL_DELETE(acl, aclTmp1);
110 * This internal method converts ACL data into JSON format.
112 * Note: Caller needs to invoke 'free' when finished done using
115 char * BinToAclJSON(const OicSecAcl_t * acl, const bool isIncResName)
117 cJSON *jsonRoot = NULL;
118 char *jsonStr = NULL;
122 cJSON *jsonAclArray = NULL;
125 jsonRoot = cJSON_CreateObject();
126 VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
127 cJSON_AddItemToObject (jsonRoot, OIC_JSON_ACL_NAME, jsonAclArray=cJSON_CreateArray());
131 jsonAclArray = cJSON_CreateArray();
132 jsonRoot = jsonAclArray;
134 VERIFY_NON_NULL(TAG, jsonAclArray, ERROR);
138 char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {};
141 B64Result b64Ret = B64_OK;
143 cJSON *jsonAcl = cJSON_CreateObject();
145 // Subject -- Mandatory
147 if (memcmp(&(acl->subject), &WILDCARD_SUBJECT_ID, sizeof(OicUuid_t)) == 0)
149 inLen = WILDCARD_SUBJECT_ID_LEN;
153 inLen = sizeof(OicUuid_t);
155 b64Ret = b64Encode(acl->subject.id, inLen, base64Buff,
156 sizeof(base64Buff), &outLen);
157 VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
158 cJSON_AddStringToObject(jsonAcl, OIC_JSON_SUBJECT_NAME, base64Buff );
160 // Resources -- Mandatory
161 cJSON *jsonRsrcArray = NULL;
162 cJSON_AddItemToObject (jsonAcl, OIC_JSON_RESOURCES_NAME, jsonRsrcArray = cJSON_CreateArray());
163 VERIFY_NON_NULL(TAG, jsonRsrcArray, ERROR);
164 for (size_t i = 0; i < acl->resourcesLen; i++)
166 cJSON_AddItemToArray (jsonRsrcArray, cJSON_CreateString(acl->resources[i]));
169 // Permissions -- Mandatory
170 cJSON_AddNumberToObject (jsonAcl, OIC_JSON_PERMISSION_NAME, acl->permission);
172 //Period & Recurrence -- Not Mandatory
173 if(0 != acl->prdRecrLen)
175 cJSON *jsonPeriodArray = NULL;
176 cJSON_AddItemToObject (jsonAcl, OIC_JSON_PERIODS_NAME,
177 jsonPeriodArray = cJSON_CreateArray());
178 VERIFY_NON_NULL(TAG, jsonPeriodArray, ERROR);
179 for (size_t i = 0; i < acl->prdRecrLen; i++)
181 cJSON_AddItemToArray (jsonPeriodArray,
182 cJSON_CreateString(acl->periods[i]));
186 //Recurrence -- Not Mandatory
187 if(0 != acl->prdRecrLen && acl->recurrences)
189 cJSON *jsonRecurArray = NULL;
190 cJSON_AddItemToObject (jsonAcl, OIC_JSON_RECURRENCES_NAME,
191 jsonRecurArray = cJSON_CreateArray());
192 VERIFY_NON_NULL(TAG, jsonRecurArray, ERROR);
193 for (size_t i = 0; i < acl->prdRecrLen; i++)
195 cJSON_AddItemToArray (jsonRecurArray,
196 cJSON_CreateString(acl->recurrences[i]));
200 // Owners -- Mandatory
201 cJSON *jsonOwnrArray = NULL;
202 cJSON_AddItemToObject (jsonAcl, OIC_JSON_OWNERS_NAME, jsonOwnrArray = cJSON_CreateArray());
203 VERIFY_NON_NULL(TAG, jsonOwnrArray, ERROR);
204 for (size_t i = 0; i < acl->ownersLen; i++)
208 b64Ret = b64Encode(acl->owners[i].id, sizeof(((OicUuid_t*)0)->id), base64Buff,
209 sizeof(base64Buff), &outLen);
210 VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
212 cJSON_AddItemToArray (jsonOwnrArray, cJSON_CreateString(base64Buff));
215 // Attach current acl node to Acl Array
216 cJSON_AddItemToArray(jsonAclArray, jsonAcl);
220 jsonStr = cJSON_PrintUnformatted(jsonRoot);
226 cJSON_Delete(jsonRoot);
232 * This internal method converts JSON ACL into binary ACL.
234 OicSecAcl_t * JSONToAclBin(const char * jsonStr, const bool isIncResName)
236 OCStackResult ret = OC_STACK_ERROR;
237 OicSecAcl_t * headAcl = NULL;
238 OicSecAcl_t * prevAcl = NULL;
239 cJSON *jsonRoot = NULL;
240 cJSON *jsonAclArray = NULL;
242 VERIFY_NON_NULL(TAG, jsonStr, ERROR);
244 jsonRoot = cJSON_Parse(jsonStr);
245 VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
249 jsonAclArray = cJSON_GetObjectItem(jsonRoot, OIC_JSON_ACL_NAME);
253 jsonAclArray = jsonRoot;
255 VERIFY_NON_NULL(TAG, jsonAclArray, ERROR);
257 if (cJSON_Array == jsonAclArray->type)
259 int numAcl = cJSON_GetArraySize(jsonAclArray);
262 VERIFY_SUCCESS(TAG, numAcl > 0, INFO);
265 cJSON *jsonAcl = cJSON_GetArrayItem(jsonAclArray, idx);
266 VERIFY_NON_NULL(TAG, jsonAcl, ERROR);
268 OicSecAcl_t *acl = (OicSecAcl_t*)OICCalloc(1, sizeof(OicSecAcl_t));
269 VERIFY_NON_NULL(TAG, acl, ERROR);
271 headAcl = (headAcl) ? headAcl : acl;
277 size_t jsonObjLen = 0;
278 cJSON *jsonObj = NULL;
280 unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
282 B64Result b64Ret = B64_OK;
284 // Subject -- Mandatory
285 jsonObj = cJSON_GetObjectItem(jsonAcl, OIC_JSON_SUBJECT_NAME);
286 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
287 VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR);
289 b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring), base64Buff,
290 sizeof(base64Buff), &outLen);
291 VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(acl->subject.id)), ERROR);
292 memcpy(acl->subject.id, base64Buff, outLen);
294 // Resources -- Mandatory
295 jsonObj = cJSON_GetObjectItem(jsonAcl, OIC_JSON_RESOURCES_NAME);
296 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
297 VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR);
299 acl->resourcesLen = cJSON_GetArraySize(jsonObj);
300 VERIFY_SUCCESS(TAG, acl->resourcesLen > 0, ERROR);
301 acl->resources = (char**)OICCalloc(acl->resourcesLen, sizeof(char*));
302 VERIFY_NON_NULL(TAG, (acl->resources), ERROR);
307 cJSON *jsonRsrc = cJSON_GetArrayItem(jsonObj, idxx);
308 VERIFY_NON_NULL(TAG, jsonRsrc, ERROR);
310 jsonObjLen = strlen(jsonRsrc->valuestring) + 1;
311 acl->resources[idxx] = (char*)OICMalloc(jsonObjLen);
312 VERIFY_NON_NULL(TAG, (acl->resources[idxx]), ERROR);
313 OICStrcpy(acl->resources[idxx], jsonObjLen, jsonRsrc->valuestring);
314 } while ( ++idxx < acl->resourcesLen);
316 // Permissions -- Mandatory
317 jsonObj = cJSON_GetObjectItem(jsonAcl,
318 OIC_JSON_PERMISSION_NAME);
319 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
320 VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
321 acl->permission = jsonObj->valueint;
323 //Period -- Not Mandatory
324 cJSON *jsonPeriodObj = cJSON_GetObjectItem(jsonAcl,
325 OIC_JSON_PERIODS_NAME);
328 VERIFY_SUCCESS(TAG, cJSON_Array == jsonPeriodObj->type,
330 acl->prdRecrLen = cJSON_GetArraySize(jsonPeriodObj);
331 if(acl->prdRecrLen > 0)
333 acl->periods = (char**)OICCalloc(acl->prdRecrLen,
335 VERIFY_NON_NULL(TAG, acl->periods, ERROR);
337 cJSON *jsonPeriod = NULL;
338 for(size_t i = 0; i < acl->prdRecrLen; i++)
340 jsonPeriod = cJSON_GetArrayItem(jsonPeriodObj, i);
341 VERIFY_NON_NULL(TAG, jsonPeriod, ERROR);
343 jsonObjLen = strlen(jsonPeriod->valuestring) + 1;
344 acl->periods[i] = (char*)OICMalloc(jsonObjLen);
345 VERIFY_NON_NULL(TAG, acl->periods[i], ERROR);
346 OICStrcpy(acl->periods[i], jsonObjLen,
347 jsonPeriod->valuestring);
352 //Recurrence -- Not mandatory
353 cJSON *jsonRecurObj = cJSON_GetObjectItem(jsonAcl,
354 OIC_JSON_RECURRENCES_NAME);
357 VERIFY_SUCCESS(TAG, cJSON_Array == jsonRecurObj->type,
360 if(acl->prdRecrLen > 0)
362 acl->recurrences = (char**)OICCalloc(acl->prdRecrLen,
364 VERIFY_NON_NULL(TAG, acl->recurrences, ERROR);
366 cJSON *jsonRecur = NULL;
367 for(size_t i = 0; i < acl->prdRecrLen; i++)
369 jsonRecur = cJSON_GetArrayItem(jsonRecurObj, i);
370 VERIFY_NON_NULL(TAG, jsonRecur, ERROR);
371 jsonObjLen = strlen(jsonRecur->valuestring) + 1;
372 acl->recurrences[i] = (char*)OICMalloc(jsonObjLen);
373 VERIFY_NON_NULL(TAG, acl->recurrences[i], ERROR);
374 OICStrcpy(acl->recurrences[i], jsonObjLen,
375 jsonRecur->valuestring);
380 // Owners -- Mandatory
381 jsonObj = cJSON_GetObjectItem(jsonAcl, OIC_JSON_OWNERS_NAME);
382 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
383 VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR);
385 acl->ownersLen = cJSON_GetArraySize(jsonObj);
386 VERIFY_SUCCESS(TAG, acl->ownersLen > 0, ERROR);
387 acl->owners = (OicUuid_t*)OICCalloc(acl->ownersLen, sizeof(OicUuid_t));
388 VERIFY_NON_NULL(TAG, (acl->owners), ERROR);
393 cJSON *jsonOwnr = cJSON_GetArrayItem(jsonObj, idxx);
394 VERIFY_NON_NULL(TAG, jsonOwnr, ERROR);
395 VERIFY_SUCCESS(TAG, cJSON_String == jsonOwnr->type, ERROR);
398 b64Ret = b64Decode(jsonOwnr->valuestring, strlen(jsonOwnr->valuestring), base64Buff,
399 sizeof(base64Buff), &outLen);
401 VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(acl->owners[idxx].id)),
403 memcpy(acl->owners[idxx].id, base64Buff, outLen);
404 } while ( ++idxx < acl->ownersLen);
407 } while( ++idx < numAcl);
413 cJSON_Delete(jsonRoot);
414 if (OC_STACK_OK != ret)
416 DeleteACLList(headAcl);
422 static bool UpdatePersistentStorage(const OicSecAcl_t *acl)
424 // Convert ACL data into JSON for update to persistent storage
425 char *jsonStr = BinToAclJSON(acl, true);
428 cJSON *jsonAcl = cJSON_Parse(jsonStr);
431 if ((jsonAcl) && (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_ACL_NAME, jsonAcl)))
435 cJSON_Delete(jsonAcl);
441 * This method removes ACE for the subject and resource from the ACL
443 * @param subject - subject of the ACE
444 * @param resource - resource of the ACE
447 * OC_STACK_RESOURCE_DELETED on success
448 * OC_STACK_NO_RESOURC on failure to find the appropriate ACE
449 * OC_STACK_INVALID_PARAM on invalid parameter
451 static OCStackResult RemoveACE(const OicUuid_t * subject,
452 const char * resource)
454 OC_LOG(DEBUG, TAG, "IN RemoveACE");
456 OicSecAcl_t *acl = NULL;
457 OicSecAcl_t *tempAcl = NULL;
458 bool deleteFlag = false;
459 OCStackResult ret = OC_STACK_NO_RESOURCE;
461 if(memcmp(subject->id, &WILDCARD_SUBJECT_ID, sizeof(subject->id)) == 0)
463 OC_LOG_V (ERROR, TAG, "%s received invalid parameter", __func__ );
464 return OC_STACK_INVALID_PARAM;
467 //If resource is NULL then delete all the ACE for the subject.
468 if(NULL == resource || resource[0] == '\0')
470 LL_FOREACH_SAFE(gAcl, acl, tempAcl)
472 if(memcmp(acl->subject.id, subject->id, sizeof(subject->id)) == 0)
474 LL_DELETE(gAcl, acl);
482 //Looping through ACL to find the right ACE to delete. If the required resource is the only
483 //resource in the ACE for the subject then delete the whole ACE. If there are more resources
484 //than the required resource in the ACE, for the subject then just delete the resource from
486 LL_FOREACH_SAFE(gAcl, acl, tempAcl)
488 if(memcmp(acl->subject.id, subject->id, sizeof(subject->id)) == 0)
490 if(1 == acl->resourcesLen && strcmp(acl->resources[0], resource) == 0)
492 LL_DELETE(gAcl, acl);
501 for(i = 0; i < acl->resourcesLen; i++)
503 if(strcmp(acl->resources[i], resource) == 0)
511 OICFree(acl->resources[resPos]);
512 acl->resources[resPos] = NULL;
513 acl->resourcesLen -= 1;
514 for(i = resPos; i < acl->resourcesLen; i++)
516 acl->resources[i] = acl->resources[i+1];
528 if(UpdatePersistentStorage(gAcl))
530 ret = OC_STACK_RESOURCE_DELETED;
537 * This method parses the query string received for REST requests and
538 * retrieves the 'subject' field.
540 * @param query querystring passed in REST request
541 * @param subject subject UUID parsed from query string
543 * @return true if query parsed successfully and found 'subject', else false.
545 static bool GetSubjectFromQueryString(const char *query, OicUuid_t *subject)
547 OicParseQueryIter_t parseIter = {.attrPos=NULL};
549 ParseQueryIterInit((unsigned char *)query, &parseIter);
552 while(GetNextQuery(&parseIter))
554 if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_SUBJECT_NAME, parseIter.attrLen) == 0)
556 VERIFY_SUCCESS(TAG, 0 != parseIter.valLen, ERROR);
557 unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
559 B64Result b64Ret = B64_OK;
560 b64Ret = b64Decode((char *)parseIter.valPos, parseIter.valLen, base64Buff,
561 sizeof(base64Buff), &outLen);
562 VERIFY_SUCCESS(TAG, (B64_OK == b64Ret && outLen <= sizeof(subject->id)), ERROR);
563 memcpy(subject->id, base64Buff, outLen);
574 * This method parses the query string received for REST requests and
575 * retrieves the 'resource' field.
577 * @param query querystring passed in REST request
578 * @param resource resource parsed from query string
579 * @param resourceSize size of the memory pointed to resource
581 * @return true if query parsed successfully and found 'resource', else false.
583 static bool GetResourceFromQueryString(const char *query, char *resource, size_t resourceSize)
585 OicParseQueryIter_t parseIter = {.attrPos=NULL};
587 ParseQueryIterInit((unsigned char *)query, &parseIter);
589 while(GetNextQuery(&parseIter))
591 if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_RESOURCES_NAME, parseIter.attrLen) == 0)
593 VERIFY_SUCCESS(TAG, 0 != parseIter.valLen, ERROR);
594 OICStrcpy(resource, resourceSize, (char *)parseIter.valPos);
606 static OCEntityHandlerResult HandleACLGetRequest (const OCEntityHandlerRequest * ehRequest)
608 OCEntityHandlerResult ehRet = OC_EH_ERROR;
609 char* jsonStr = NULL;
611 // Process the REST querystring parameters
614 OC_LOG (DEBUG, TAG, "HandleACLGetRequest processing query");
616 OicUuid_t subject = {.id={0}};
617 char resource[MAX_URI_LENGTH] = {0};
619 OicSecAcl_t *savePtr = NULL;
620 const OicSecAcl_t *currentAce = NULL;
622 // 'Subject' field is MUST for processing a querystring in REST request.
624 true == GetSubjectFromQueryString(ehRequest->query, &subject),
627 GetResourceFromQueryString(ehRequest->query, resource, sizeof(resource));
630 * TODO : Currently, this code only provides one ACE for a Subject.
631 * Below code needs to be updated for scenarios when Subject have
632 * multiple ACE's in ACL resource.
634 while((currentAce = GetACLResourceData(&subject, &savePtr)))
637 * If REST querystring contains a specific resource, we need
638 * to search for that resource in ACE.
640 if (resource[0] != '\0')
642 for(size_t n = 0; n < currentAce->resourcesLen; n++)
644 if((currentAce->resources[n]) &&
645 (0 == strcmp(resource, currentAce->resources[n]) ||
646 0 == strcmp(WILDCARD_RESOURCE_URI, currentAce->resources[n])))
648 // Convert ACL data into JSON for transmission
649 jsonStr = BinToAclJSON(currentAce, false);
656 // Convert ACL data into JSON for transmission
657 jsonStr = BinToAclJSON(currentAce, false);
664 // Convert ACL data into JSON for transmission
665 jsonStr = BinToAclJSON(gAcl, false);
669 ehRet = (jsonStr ? OC_EH_OK : OC_EH_ERROR);
671 // Send response payload to request originator
672 SendSRMResponse(ehRequest, ehRet, jsonStr);
676 OC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
680 static OCEntityHandlerResult HandleACLPostRequest (const OCEntityHandlerRequest * ehRequest)
682 OCEntityHandlerResult ehRet = OC_EH_ERROR;
684 // Convert JSON ACL data into binary. This will also validate the ACL data received.
685 OicSecAcl_t* newAcl = JSONToAclBin(((OCSecurityPayload*)ehRequest->payload)->securityData, false);
689 // Append the new ACL to existing ACL
690 LL_APPEND(gAcl, newAcl);
692 if(UpdatePersistentStorage(gAcl))
694 ehRet = OC_EH_RESOURCE_CREATED;
698 // Send payload to request originator
699 SendSRMResponse(ehRequest, ehRet, NULL);
701 OC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
705 static OCEntityHandlerResult HandleACLDeleteRequest(const OCEntityHandlerRequest *ehRequest)
707 OC_LOG (DEBUG, TAG, "Processing ACLDeleteRequest");
708 OCEntityHandlerResult ehRet = OC_EH_ERROR;
709 OicUuid_t subject = {.id={0}};
710 char resource[MAX_URI_LENGTH] = {0};
712 VERIFY_NON_NULL(TAG, ehRequest->query, ERROR);
714 // 'Subject' field is MUST for processing a querystring in REST request.
716 true == GetSubjectFromQueryString(ehRequest->query, &subject),
719 GetResourceFromQueryString(ehRequest->query, resource, sizeof(resource));
721 if(OC_STACK_RESOURCE_DELETED == RemoveACE(&subject, resource))
723 ehRet = OC_EH_RESOURCE_DELETED;
727 // Send payload to request originator
728 SendSRMResponse(ehRequest, ehRet, NULL);
734 * This internal method is the entity handler for ACL resources and
735 * will handle REST request (GET/PUT/POST/DEL) for them.
737 OCEntityHandlerResult ACLEntityHandler (OCEntityHandlerFlag flag,
738 OCEntityHandlerRequest * ehRequest,
739 void* callbackParameter)
741 OC_LOG(DEBUG, TAG, "Received request ACLEntityHandler");
742 (void)callbackParameter;
743 OCEntityHandlerResult ehRet = OC_EH_ERROR;
750 if (flag & OC_REQUEST_FLAG)
752 // TODO : Handle PUT method
753 OC_LOG (DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
754 switch (ehRequest->method)
757 ehRet = HandleACLGetRequest(ehRequest);
761 ehRet = HandleACLPostRequest(ehRequest);
765 ehRet = HandleACLDeleteRequest(ehRequest);
770 SendSRMResponse(ehRequest, ehRet, NULL);
778 * This internal method is used to create '/oic/sec/acl' resource.
780 OCStackResult CreateACLResource()
784 ret = OCCreateResource(&gAclHandle,
785 OIC_RSRC_TYPE_SEC_ACL,
790 OC_OBSERVABLE | OC_SECURE | OC_EXPLICIT_DISCOVERABLE);
792 if (OC_STACK_OK != ret)
794 OC_LOG (FATAL, TAG, "Unable to instantiate ACL resource");
801 * This internal method is to retrieve the default ACL.
802 * If SVR database in persistent storage got corrupted or
803 * is not available for some reason, a default ACL is created
804 * which allows user to initiate ACL provisioning again.
806 OCStackResult GetDefaultACL(OicSecAcl_t** defaultAcl)
808 OCStackResult ret = OC_STACK_ERROR;
810 OicUuid_t ownerId = {.id = {0}};
813 * TODO In future, when new virtual resources will be added in OIC
814 * specification, Iotivity stack should be able to add them in
815 * existing SVR database. To support this, we need to add 'versioning'
816 * mechanism in SVR database.
819 const char *rsrcs[] = {
820 OC_RSRVD_WELL_KNOWN_URI,
822 OC_RSRVD_PLATFORM_URI,
823 OC_RSRVD_RESOURCE_TYPES_URI,
825 OC_RSRVD_PRESENCE_URI,
826 #endif //WITH_PRESENCE
834 return OC_STACK_INVALID_PARAM;
837 OicSecAcl_t *acl = (OicSecAcl_t *)OICCalloc(1, sizeof(OicSecAcl_t));
838 VERIFY_NON_NULL(TAG, acl, ERROR);
840 // Subject -- Mandatory
841 memcpy(&(acl->subject), &WILDCARD_SUBJECT_ID, sizeof(acl->subject));
843 // Resources -- Mandatory
844 acl->resourcesLen = sizeof(rsrcs)/sizeof(rsrcs[0]);
846 acl->resources = (char**)OICCalloc(acl->resourcesLen, sizeof(char*));
847 VERIFY_NON_NULL(TAG, (acl->resources), ERROR);
849 for (size_t i = 0; i < acl->resourcesLen; i++)
851 size_t len = strlen(rsrcs[i]) + 1;
852 acl->resources[i] = (char*)OICMalloc(len * sizeof(char));
853 VERIFY_NON_NULL(TAG, (acl->resources[i]), ERROR);
854 OICStrcpy(acl->resources[i], len, rsrcs[i]);
857 acl->permission = PERMISSION_READ;
860 acl->recurrences = NULL;
862 // Device ID is the owner of this default ACL
863 ret = GetDoxmDeviceID( &ownerId);
864 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, FATAL);
867 acl->owners = (OicUuid_t*)OICMalloc(sizeof(OicUuid_t));
868 VERIFY_NON_NULL(TAG, (acl->owners), ERROR);
869 memcpy(acl->owners, &ownerId, sizeof(OicUuid_t));
878 if (ret != OC_STACK_OK)
888 * Initialize ACL resource by loading data from persistent storage.
890 * @retval OC_STACK_OK for Success, otherwise some error value
892 OCStackResult InitACLResource()
894 OCStackResult ret = OC_STACK_ERROR;
896 // Read ACL resource from PS
897 char* jsonSVRDatabase = GetSVRDatabase();
901 // Convert JSON ACL into binary format
902 gAcl = JSONToAclBin(jsonSVRDatabase, true);
903 OICFree(jsonSVRDatabase);
906 * If SVR database in persistent storage got corrupted or
907 * is not available for some reason, a default ACL is created
908 * which allows user to initiate ACL provisioning again.
910 if (!jsonSVRDatabase || !gAcl)
912 GetDefaultACL(&gAcl);
913 // TODO Needs to update persistent storage
915 VERIFY_NON_NULL(TAG, gAcl, FATAL);
917 // Instantiate 'oic.sec.acl'
918 ret = CreateACLResource();
921 if (OC_STACK_OK != ret)
929 * Perform cleanup for ACL resources.
933 void DeInitACLResource()
935 OCDeleteResource(gAclHandle);
943 * This method is used by PolicyEngine to retrieve ACL for a Subject.
945 * @param subjectId ID of the subject for which ACL is required.
946 * @param savePtr is used internally by @ref GetACLResourceData to maintain index between
947 * successive calls for same subjectId.
949 * @retval reference to @ref OicSecAcl_t if ACL is found, else NULL
951 * @note On the first call to @ref GetACLResourceData, savePtr should point to NULL
953 const OicSecAcl_t* GetACLResourceData(const OicUuid_t* subjectId, OicSecAcl_t **savePtr)
955 OicSecAcl_t *acl = NULL;
956 OicSecAcl_t *begin = NULL;
958 if ( NULL == subjectId)
964 * savePtr MUST point to NULL if this is the 'first' call to retrieve ACL for
967 if (NULL == *savePtr)
974 * If this is a 'successive' call, search for location pointed by
975 * savePtr and assign 'begin' to the next ACL after it in the linked
976 * list and start searching from there.
978 LL_FOREACH(gAcl, acl)
987 // Find the next ACL corresponding to the 'subjectID' and return it.
988 LL_FOREACH(begin, acl)
990 if (memcmp(&(acl->subject), subjectId, sizeof(OicUuid_t)) == 0)
997 // Cleanup in case no ACL is found
1003 OCStackResult InstallNewACL(const char* newJsonStr, const bool isIncResName)
1005 OCStackResult ret = OC_STACK_ERROR;
1007 // Convert JSON ACL data into binary. This will also validate the ACL data received.
1008 OicSecAcl_t* newAcl = JSONToAclBin(newJsonStr, isIncResName);
1012 // Append the new ACL to existing ACL
1013 LL_APPEND(gAcl, newAcl);
1015 // Convert ACL data into JSON for update to persistent storage
1016 char *jsonStr = BinToAclJSON(gAcl, true);
1019 cJSON *jsonAcl = cJSON_Parse(jsonStr);
1024 ret = UpdateSVRDatabase(OIC_JSON_ACL_NAME, jsonAcl);
1026 cJSON_Delete(jsonAcl);