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);
68 //Clean Period & Recurrence
69 for(i = 0; i < ace->prdRecrLen; i++)
71 OICFree(ace->periods[i]);
72 OICFree(ace->recurrences[i]);
74 OICFree(ace->periods);
75 OICFree(ace->recurrences);
80 // Clean ACL node itself
84 void DeleteACLList(OicSecAcl_t* acl)
88 OicSecAcl_t *aclTmp1 = NULL;
89 OicSecAcl_t *aclTmp2 = NULL;
90 LL_FOREACH_SAFE(acl, aclTmp1, aclTmp2)
92 LL_DELETE(acl, aclTmp1);
99 * This internal method converts ACL data into JSON format.
101 * Note: Caller needs to invoke 'free' when finished done using
104 char * BinToAclJSON(const OicSecAcl_t * acl)
106 cJSON *jsonRoot = NULL;
107 char *jsonStr = NULL;
111 jsonRoot = cJSON_CreateObject();
112 VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
114 cJSON *jsonAclArray = NULL;
115 cJSON_AddItemToObject (jsonRoot, OIC_JSON_ACL_NAME, jsonAclArray = cJSON_CreateArray());
116 VERIFY_NON_NULL(TAG, jsonAclArray, ERROR);
120 char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {};
123 B64Result b64Ret = B64_OK;
125 cJSON *jsonAcl = cJSON_CreateObject();
127 // Subject -- Mandatory
129 if (memcmp(&(acl->subject), &WILDCARD_SUBJECT_ID, sizeof(OicUuid_t)) == 0)
131 inLen = WILDCARD_SUBJECT_ID_LEN;
135 inLen = sizeof(OicUuid_t);
137 b64Ret = b64Encode(acl->subject.id, inLen, base64Buff,
138 sizeof(base64Buff), &outLen);
139 VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
140 cJSON_AddStringToObject(jsonAcl, OIC_JSON_SUBJECT_NAME, base64Buff );
142 // Resources -- Mandatory
143 cJSON *jsonRsrcArray = NULL;
144 cJSON_AddItemToObject (jsonAcl, OIC_JSON_RESOURCES_NAME, jsonRsrcArray = cJSON_CreateArray());
145 VERIFY_NON_NULL(TAG, jsonRsrcArray, ERROR);
146 for (size_t i = 0; i < acl->resourcesLen; i++)
148 cJSON_AddItemToArray (jsonRsrcArray, cJSON_CreateString(acl->resources[i]));
151 // Permissions -- Mandatory
152 cJSON_AddNumberToObject (jsonAcl, OIC_JSON_PERMISSION_NAME, acl->permission);
154 //Period & Recurrence -- Not Mandatory
155 if(0 != acl->prdRecrLen)
157 cJSON *jsonPeriodArray = NULL;
158 cJSON_AddItemToObject (jsonAcl, OIC_JSON_PERIODS_NAME,
159 jsonPeriodArray = cJSON_CreateArray());
160 VERIFY_NON_NULL(TAG, jsonPeriodArray, ERROR);
161 for (size_t i = 0; i < acl->prdRecrLen; i++)
163 cJSON_AddItemToArray (jsonPeriodArray,
164 cJSON_CreateString(acl->periods[i]));
168 //Recurrence -- Not Mandatory
169 if(0 != acl->prdRecrLen && acl->recurrences)
171 cJSON *jsonRecurArray = NULL;
172 cJSON_AddItemToObject (jsonAcl, OIC_JSON_RECURRENCES_NAME,
173 jsonRecurArray = cJSON_CreateArray());
174 VERIFY_NON_NULL(TAG, jsonRecurArray, ERROR);
175 for (size_t i = 0; i < acl->prdRecrLen; i++)
177 cJSON_AddItemToArray (jsonRecurArray,
178 cJSON_CreateString(acl->recurrences[i]));
182 // Owners -- Mandatory
183 cJSON *jsonOwnrArray = NULL;
184 cJSON_AddItemToObject (jsonAcl, OIC_JSON_OWNERS_NAME, jsonOwnrArray = cJSON_CreateArray());
185 VERIFY_NON_NULL(TAG, jsonOwnrArray, ERROR);
186 for (size_t i = 0; i < acl->ownersLen; i++)
190 b64Ret = b64Encode(acl->owners[i].id, sizeof(((OicUuid_t*)0)->id), base64Buff,
191 sizeof(base64Buff), &outLen);
192 VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
194 cJSON_AddItemToArray (jsonOwnrArray, cJSON_CreateString(base64Buff));
197 // Attach current acl node to Acl Array
198 cJSON_AddItemToArray(jsonAclArray, jsonAcl);
202 jsonStr = cJSON_PrintUnformatted(jsonRoot);
208 cJSON_Delete(jsonRoot);
214 * This internal method converts JSON ACL into binary ACL.
216 OicSecAcl_t * JSONToAclBin(const char * jsonStr)
218 OCStackResult ret = OC_STACK_ERROR;
219 OicSecAcl_t * headAcl = NULL;
220 OicSecAcl_t * prevAcl = NULL;
221 cJSON *jsonRoot = NULL;
222 cJSON *jsonAclArray = NULL;
224 VERIFY_NON_NULL(TAG, jsonStr, ERROR);
226 jsonRoot = cJSON_Parse(jsonStr);
227 VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
229 jsonAclArray = cJSON_GetObjectItem(jsonRoot, OIC_JSON_ACL_NAME);
230 VERIFY_NON_NULL(TAG, jsonAclArray, ERROR);
232 if (cJSON_Array == jsonAclArray->type)
234 int numAcl = cJSON_GetArraySize(jsonAclArray);
237 VERIFY_SUCCESS(TAG, numAcl > 0, INFO);
240 cJSON *jsonAcl = cJSON_GetArrayItem(jsonAclArray, idx);
241 VERIFY_NON_NULL(TAG, jsonAcl, ERROR);
243 OicSecAcl_t *acl = (OicSecAcl_t*)OICCalloc(1, sizeof(OicSecAcl_t));
244 VERIFY_NON_NULL(TAG, acl, ERROR);
246 headAcl = (headAcl) ? headAcl : acl;
252 size_t jsonObjLen = 0;
253 cJSON *jsonObj = NULL;
255 unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
257 B64Result b64Ret = B64_OK;
259 // Subject -- Mandatory
260 jsonObj = cJSON_GetObjectItem(jsonAcl, OIC_JSON_SUBJECT_NAME);
261 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
262 VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR);
264 b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring), base64Buff,
265 sizeof(base64Buff), &outLen);
266 VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(acl->subject.id)), ERROR);
267 memcpy(acl->subject.id, base64Buff, outLen);
269 // Resources -- Mandatory
270 jsonObj = cJSON_GetObjectItem(jsonAcl, OIC_JSON_RESOURCES_NAME);
271 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
272 VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR);
274 acl->resourcesLen = cJSON_GetArraySize(jsonObj);
275 VERIFY_SUCCESS(TAG, acl->resourcesLen > 0, ERROR);
276 acl->resources = (char**)OICCalloc(acl->resourcesLen, sizeof(char*));
277 VERIFY_NON_NULL(TAG, (acl->resources), ERROR);
282 cJSON *jsonRsrc = cJSON_GetArrayItem(jsonObj, idxx);
283 VERIFY_NON_NULL(TAG, jsonRsrc, ERROR);
285 jsonObjLen = strlen(jsonRsrc->valuestring) + 1;
286 acl->resources[idxx] = (char*)OICMalloc(jsonObjLen);
287 VERIFY_NON_NULL(TAG, (acl->resources[idxx]), ERROR);
288 OICStrcpy(acl->resources[idxx], jsonObjLen, jsonRsrc->valuestring);
289 } while ( ++idxx < acl->resourcesLen);
291 // Permissions -- Mandatory
292 jsonObj = cJSON_GetObjectItem(jsonAcl,
293 OIC_JSON_PERMISSION_NAME);
294 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
295 VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
296 acl->permission = jsonObj->valueint;
298 //Period -- Not Mandatory
299 cJSON *jsonPeriodObj = cJSON_GetObjectItem(jsonAcl,
300 OIC_JSON_PERIODS_NAME);
303 VERIFY_SUCCESS(TAG, cJSON_Array == jsonPeriodObj->type,
305 acl->prdRecrLen = cJSON_GetArraySize(jsonPeriodObj);
306 if(acl->prdRecrLen > 0)
308 acl->periods = (char**)OICCalloc(acl->prdRecrLen,
310 VERIFY_NON_NULL(TAG, acl->periods, ERROR);
312 cJSON *jsonPeriod = NULL;
313 for(size_t i = 0; i < acl->prdRecrLen; i++)
315 jsonPeriod = cJSON_GetArrayItem(jsonPeriodObj, i);
316 VERIFY_NON_NULL(TAG, jsonPeriod, ERROR);
318 jsonObjLen = strlen(jsonPeriod->valuestring) + 1;
319 acl->periods[i] = (char*)OICMalloc(jsonObjLen);
320 VERIFY_NON_NULL(TAG, acl->periods[i], ERROR);
321 OICStrcpy(acl->periods[i], jsonObjLen,
322 jsonPeriod->valuestring);
327 //Recurrence -- Not mandatory
328 cJSON *jsonRecurObj = cJSON_GetObjectItem(jsonAcl,
329 OIC_JSON_RECURRENCES_NAME);
332 VERIFY_SUCCESS(TAG, cJSON_Array == jsonRecurObj->type,
334 if(acl->prdRecrLen > 0)
336 acl->recurrences = (char**)OICCalloc(acl->prdRecrLen,
338 VERIFY_NON_NULL(TAG, acl->recurrences, ERROR);
340 cJSON *jsonRecur = NULL;
341 for(size_t i = 0; i < acl->prdRecrLen; i++)
343 jsonRecur = cJSON_GetArrayItem(jsonRecurObj, i);
344 jsonObjLen = strlen(jsonRecur->valuestring) + 1;
345 acl->recurrences[i] = (char*)OICMalloc(jsonObjLen);
346 VERIFY_NON_NULL(TAG, acl->recurrences[i], ERROR);
347 OICStrcpy(acl->recurrences[i], jsonObjLen,
348 jsonRecur->valuestring);
353 // Owners -- Mandatory
354 jsonObj = cJSON_GetObjectItem(jsonAcl, OIC_JSON_OWNERS_NAME);
355 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
356 VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR);
358 acl->ownersLen = cJSON_GetArraySize(jsonObj);
359 VERIFY_SUCCESS(TAG, acl->ownersLen > 0, ERROR);
360 acl->owners = (OicUuid_t*)OICCalloc(acl->ownersLen, sizeof(OicUuid_t));
361 VERIFY_NON_NULL(TAG, (acl->owners), ERROR);
366 cJSON *jsonOwnr = cJSON_GetArrayItem(jsonObj, idxx);
367 VERIFY_NON_NULL(TAG, jsonOwnr, ERROR);
368 VERIFY_SUCCESS(TAG, cJSON_String == jsonOwnr->type, ERROR);
371 b64Ret = b64Decode(jsonOwnr->valuestring, strlen(jsonOwnr->valuestring), base64Buff,
372 sizeof(base64Buff), &outLen);
374 VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(acl->owners[idxx].id)),
376 memcpy(acl->owners[idxx].id, base64Buff, outLen);
377 } while ( ++idxx < acl->ownersLen);
380 } while( ++idx < numAcl);
386 cJSON_Delete(jsonRoot);
387 if (OC_STACK_OK != ret)
389 DeleteACLList(headAcl);
395 static bool UpdatePersistentStorage(const OicSecAcl_t *acl)
397 // Convert ACL data into JSON for update to persistent storage
398 char *jsonStr = BinToAclJSON(acl);
401 cJSON *jsonAcl = cJSON_Parse(jsonStr);
404 if ((jsonAcl) && (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_ACL_NAME, jsonAcl)))
408 cJSON_Delete(jsonAcl);
414 * This method removes ACE for the subject and resource from the ACL
416 * @param subject - subject of the ACE
417 * @param resource - resource of the ACE
420 * OC_STACK_RESOURCE_DELETED on success
421 * OC_STACK_NO_RESOURC on failure to find the appropriate ACE
422 * OC_STACK_INVALID_PARAM on invalid parameter
424 static OCStackResult RemoveACE(const OicUuid_t * subject,
425 const char * resource)
427 OC_LOG(DEBUG, TAG, "IN RemoveACE");
429 OicSecAcl_t *acl = NULL;
430 OicSecAcl_t *tempAcl = NULL;
431 bool deleteFlag = false;
432 OCStackResult ret = OC_STACK_NO_RESOURCE;
434 if(memcmp(subject->id, &WILDCARD_SUBJECT_ID, sizeof(subject->id)) == 0)
436 OC_LOG_V (ERROR, TAG, "%s received invalid parameter", __func__ );
437 return OC_STACK_INVALID_PARAM;
440 //If resource is NULL then delete all the ACE for the subject.
441 if(NULL == resource || resource[0] == '\0')
443 LL_FOREACH_SAFE(gAcl, acl, tempAcl)
445 if(memcmp(acl->subject.id, subject->id, sizeof(subject->id)) == 0)
447 LL_DELETE(gAcl, acl);
455 //Looping through ACL to find the right ACE to delete. If the required resource is the only
456 //resource in the ACE for the subject then delete the whole ACE. If there are more resources
457 //than the required resource in the ACE, for the subject then just delete the resource from
459 LL_FOREACH_SAFE(gAcl, acl, tempAcl)
461 if(memcmp(acl->subject.id, subject->id, sizeof(subject->id)) == 0)
463 if(1 == acl->resourcesLen && strcmp(acl->resources[0], resource) == 0)
465 LL_DELETE(gAcl, acl);
474 for(i = 0; i < acl->resourcesLen; i++)
476 if(strcmp(acl->resources[i], resource) == 0)
484 OICFree(acl->resources[resPos]);
485 acl->resources[resPos] = NULL;
486 acl->resourcesLen -= 1;
487 for(i = resPos; i < acl->resourcesLen; i++)
489 acl->resources[i] = acl->resources[i+1];
501 if(UpdatePersistentStorage(gAcl))
503 ret = OC_STACK_RESOURCE_DELETED;
510 * This method parses the query string received for REST requests and
511 * retrieves the 'subject' field.
513 * @param query querystring passed in REST request
514 * @param subject subject UUID parsed from query string
516 * @return true if query parsed successfully and found 'subject', else false.
518 static bool GetSubjectFromQueryString(const char *query, OicUuid_t *subject)
520 OicParseQueryIter_t parseIter = {.attrPos=NULL};
522 ParseQueryIterInit((unsigned char *)query, &parseIter);
525 while(GetNextQuery(&parseIter))
527 if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_SUBJECT_NAME, parseIter.attrLen) == 0)
529 VERIFY_SUCCESS(TAG, 0 != parseIter.valLen, ERROR);
530 unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
532 B64Result b64Ret = B64_OK;
533 b64Ret = b64Decode((char *)parseIter.valPos, parseIter.valLen, base64Buff,
534 sizeof(base64Buff), &outLen);
535 VERIFY_SUCCESS(TAG, (B64_OK == b64Ret && outLen <= sizeof(subject->id)), ERROR);
536 memcpy(subject->id, base64Buff, outLen);
547 * This method parses the query string received for REST requests and
548 * retrieves the 'resource' field.
550 * @param query querystring passed in REST request
551 * @param resource resource parsed from query string
552 * @param resourceSize size of the memory pointed to resource
554 * @return true if query parsed successfully and found 'resource', else false.
556 static bool GetResourceFromQueryString(const char *query, char *resource, size_t resourceSize)
558 OicParseQueryIter_t parseIter = {.attrPos=NULL};
560 ParseQueryIterInit((unsigned char *)query, &parseIter);
562 while(GetNextQuery(&parseIter))
564 if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_RESOURCES_NAME, parseIter.attrLen) == 0)
566 VERIFY_SUCCESS(TAG, 0 != parseIter.valLen, ERROR);
567 OICStrcpy(resource, resourceSize, (char *)parseIter.valPos);
579 static OCEntityHandlerResult HandleACLGetRequest (const OCEntityHandlerRequest * ehRequest)
581 OCEntityHandlerResult ehRet = OC_EH_ERROR;
582 char* jsonStr = NULL;
584 // Process the REST querystring parameters
587 OC_LOG (DEBUG, TAG, "HandleACLGetRequest processing query");
589 OicUuid_t subject = {.id={0}};
590 char resource[MAX_URI_LENGTH] = {0};
592 OicSecAcl_t *savePtr = NULL;
593 const OicSecAcl_t *currentAce = NULL;
595 // 'Subject' field is MUST for processing a querystring in REST request.
597 true == GetSubjectFromQueryString(ehRequest->query, &subject),
600 GetResourceFromQueryString(ehRequest->query, resource, sizeof(resource));
603 * TODO : Currently, this code only provides one ACE for a Subject.
604 * Below code needs to be updated for scenarios when Subject have
605 * multiple ACE's in ACL resource.
607 while((currentAce = GetACLResourceData(&subject, &savePtr)))
610 * If REST querystring contains a specific resource, we need
611 * to search for that resource in ACE.
613 if (resource[0] != '\0')
615 for(size_t n = 0; n < currentAce->resourcesLen; n++)
617 if((currentAce->resources[n]) &&
618 (0 == strcmp(resource, currentAce->resources[n]) ||
619 0 == strcmp(WILDCARD_RESOURCE_URI, currentAce->resources[n])))
621 // Convert ACL data into JSON for transmission
622 jsonStr = BinToAclJSON(currentAce);
629 // Convert ACL data into JSON for transmission
630 jsonStr = BinToAclJSON(currentAce);
637 // Convert ACL data into JSON for transmission
638 jsonStr = BinToAclJSON(gAcl);
642 ehRet = (jsonStr ? OC_EH_OK : OC_EH_ERROR);
644 // Send response payload to request originator
645 SendSRMResponse(ehRequest, ehRet, jsonStr);
649 OC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
653 static OCEntityHandlerResult HandleACLPostRequest (const OCEntityHandlerRequest * ehRequest)
655 OCEntityHandlerResult ehRet = OC_EH_ERROR;
657 // Convert JSON ACL data into binary. This will also validate the ACL data received.
658 OicSecAcl_t* newAcl = JSONToAclBin(((OCSecurityPayload*)ehRequest->payload)->securityData);
662 // Append the new ACL to existing ACL
663 LL_APPEND(gAcl, newAcl);
665 if(UpdatePersistentStorage(gAcl))
667 ehRet = OC_EH_RESOURCE_CREATED;
671 // Send payload to request originator
672 SendSRMResponse(ehRequest, ehRet, NULL);
674 OC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
678 static OCEntityHandlerResult HandleACLDeleteRequest(const OCEntityHandlerRequest *ehRequest)
680 OC_LOG (DEBUG, TAG, "Processing ACLDeleteRequest");
681 OCEntityHandlerResult ehRet = OC_EH_ERROR;
682 OicUuid_t subject = {.id={0}};
683 char resource[MAX_URI_LENGTH] = {0};
685 VERIFY_NON_NULL(TAG, ehRequest->query, ERROR);
687 // 'Subject' field is MUST for processing a querystring in REST request.
689 true == GetSubjectFromQueryString(ehRequest->query, &subject),
692 GetResourceFromQueryString(ehRequest->query, resource, sizeof(resource));
694 if(OC_STACK_RESOURCE_DELETED == RemoveACE(&subject, resource))
696 ehRet = OC_EH_RESOURCE_DELETED;
700 // Send payload to request originator
701 SendSRMResponse(ehRequest, ehRet, NULL);
707 * This internal method is the entity handler for ACL resources and
708 * will handle REST request (GET/PUT/POST/DEL) for them.
710 OCEntityHandlerResult ACLEntityHandler (OCEntityHandlerFlag flag,
711 OCEntityHandlerRequest * ehRequest,
712 void* callbackParameter)
714 OC_LOG(DEBUG, TAG, "Received request ACLEntityHandler");
715 (void)callbackParameter;
716 OCEntityHandlerResult ehRet = OC_EH_ERROR;
723 if (flag & OC_REQUEST_FLAG)
725 // TODO : Handle PUT method
726 OC_LOG (DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
727 switch (ehRequest->method)
730 ehRet = HandleACLGetRequest(ehRequest);
734 ehRet = HandleACLPostRequest(ehRequest);
738 ehRet = HandleACLDeleteRequest(ehRequest);
743 SendSRMResponse(ehRequest, ehRet, NULL);
751 * This internal method is used to create '/oic/sec/acl' resource.
753 OCStackResult CreateACLResource()
757 ret = OCCreateResource(&gAclHandle,
758 OIC_RSRC_TYPE_SEC_ACL,
763 OC_OBSERVABLE | OC_SECURE | OC_EXPLICIT_DISCOVERABLE);
765 if (OC_STACK_OK != ret)
767 OC_LOG (FATAL, TAG, "Unable to instantiate ACL resource");
774 * This internal method is to retrieve the default ACL.
775 * If SVR database in persistent storage got corrupted or
776 * is not available for some reason, a default ACL is created
777 * which allows user to initiate ACL provisioning again.
779 OCStackResult GetDefaultACL(OicSecAcl_t** defaultAcl)
781 OCStackResult ret = OC_STACK_ERROR;
783 OicUuid_t ownerId = {.id = {0}};
786 * TODO In future, when new virtual resources will be added in OIC
787 * specification, Iotivity stack should be able to add them in
788 * existing SVR database. To support this, we need to add 'versioning'
789 * mechanism in SVR database.
792 const char *rsrcs[] = {
793 OC_RSRVD_WELL_KNOWN_URI,
795 OC_RSRVD_PLATFORM_URI,
796 OC_RSRVD_RESOURCE_TYPES_URI,
798 OC_RSRVD_PRESENCE_URI,
799 #endif //WITH_PRESENCE
807 return OC_STACK_INVALID_PARAM;
810 OicSecAcl_t *acl = (OicSecAcl_t *)OICCalloc(1, sizeof(OicSecAcl_t));
811 VERIFY_NON_NULL(TAG, acl, ERROR);
813 // Subject -- Mandatory
814 memcpy(&(acl->subject), &WILDCARD_SUBJECT_ID, sizeof(acl->subject));
816 // Resources -- Mandatory
817 acl->resourcesLen = sizeof(rsrcs)/sizeof(rsrcs[0]);
819 acl->resources = (char**)OICCalloc(acl->resourcesLen, sizeof(char*));
820 VERIFY_NON_NULL(TAG, (acl->resources), ERROR);
822 for (size_t i = 0; i < acl->resourcesLen; i++)
824 size_t len = strlen(rsrcs[i]) + 1;
825 acl->resources[i] = (char*)OICMalloc(len * sizeof(char));
826 VERIFY_NON_NULL(TAG, (acl->resources[i]), ERROR);
827 OICStrcpy(acl->resources[i], len, rsrcs[i]);
830 acl->permission = PERMISSION_READ;
833 acl->recurrences = NULL;
835 // Device ID is the owner of this default ACL
836 ret = GetDoxmDeviceID( &ownerId);
837 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, FATAL);
840 acl->owners = (OicUuid_t*)OICMalloc(sizeof(OicUuid_t));
841 VERIFY_NON_NULL(TAG, (acl->owners), ERROR);
842 memcpy(acl->owners, &ownerId, sizeof(OicUuid_t));
851 if (ret != OC_STACK_OK)
861 * Initialize ACL resource by loading data from persistent storage.
863 * @retval OC_STACK_OK for Success, otherwise some error value
865 OCStackResult InitACLResource()
867 OCStackResult ret = OC_STACK_ERROR;
869 // Read ACL resource from PS
870 char* jsonSVRDatabase = GetSVRDatabase();
874 // Convert JSON ACL into binary format
875 gAcl = JSONToAclBin(jsonSVRDatabase);
876 OICFree(jsonSVRDatabase);
879 * If SVR database in persistent storage got corrupted or
880 * is not available for some reason, a default ACL is created
881 * which allows user to initiate ACL provisioning again.
883 if (!jsonSVRDatabase || !gAcl)
885 GetDefaultACL(&gAcl);
886 // TODO Needs to update persistent storage
888 VERIFY_NON_NULL(TAG, gAcl, FATAL);
890 // Instantiate 'oic.sec.acl'
891 ret = CreateACLResource();
894 if (OC_STACK_OK != ret)
902 * Perform cleanup for ACL resources.
906 void DeInitACLResource()
908 OCDeleteResource(gAclHandle);
916 * This method is used by PolicyEngine to retrieve ACL for a Subject.
918 * @param subjectId ID of the subject for which ACL is required.
919 * @param savePtr is used internally by @ref GetACLResourceData to maintain index between
920 * successive calls for same subjectId.
922 * @retval reference to @ref OicSecAcl_t if ACL is found, else NULL
924 * @note On the first call to @ref GetACLResourceData, savePtr should point to NULL
926 const OicSecAcl_t* GetACLResourceData(const OicUuid_t* subjectId, OicSecAcl_t **savePtr)
928 OicSecAcl_t *acl = NULL;
929 OicSecAcl_t *begin = NULL;
931 if ( NULL == subjectId)
937 * savePtr MUST point to NULL if this is the 'first' call to retrieve ACL for
940 if (NULL == *savePtr)
947 * If this is a 'successive' call, search for location pointed by
948 * savePtr and assign 'begin' to the next ACL after it in the linked
949 * list and start searching from there.
951 LL_FOREACH(gAcl, acl)
960 // Find the next ACL corresponding to the 'subjectID' and return it.
961 LL_FOREACH(begin, acl)
963 if (memcmp(&(acl->subject), subjectId, sizeof(OicUuid_t)) == 0)
970 // Cleanup in case no ACL is found
976 OCStackResult InstallNewACL(const char* newJsonStr)
978 OCStackResult ret = OC_STACK_ERROR;
980 // Convert JSON ACL data into binary. This will also validate the ACL data received.
981 OicSecAcl_t* newAcl = JSONToAclBin(newJsonStr);
985 // Append the new ACL to existing ACL
986 LL_APPEND(gAcl, newAcl);
988 // Convert ACL data into JSON for update to persistent storage
989 char *jsonStr = BinToAclJSON(gAcl);
992 cJSON *jsonAcl = cJSON_Parse(jsonStr);
997 ret = UpdateSVRDatabase(OIC_JSON_ACL_NAME, jsonAcl);
999 cJSON_Delete(jsonAcl);