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"
45 #define NUMBER_OF_SEC_PROV_RSCS 4
46 #define NUMBER_OF_DEFAULT_SEC_RSCS 2
48 OicSecAcl_t *gAcl = NULL;
49 static OCResourceHandle gAclHandle = NULL;
52 * This function frees OicSecAcl_t object's fields and object itself.
54 static void FreeACE(OicSecAcl_t *ace)
59 OIC_LOG (ERROR, TAG, "Invalid Parameter");
64 for (i = 0; i < ace->resourcesLen; i++)
66 OICFree(ace->resources[i]);
68 OICFree(ace->resources);
73 for(i = 0; i < ace->prdRecrLen; i++)
75 OICFree(ace->periods[i]);
77 OICFree(ace->periods);
83 for(i = 0; i < ace->prdRecrLen; i++)
85 OICFree(ace->recurrences[i]);
87 OICFree(ace->recurrences);
93 // Clean ACL node itself
97 void DeleteACLList(OicSecAcl_t* acl)
101 OicSecAcl_t *aclTmp1 = NULL;
102 OicSecAcl_t *aclTmp2 = NULL;
103 LL_FOREACH_SAFE(acl, aclTmp1, aclTmp2)
105 LL_DELETE(acl, aclTmp1);
112 * This internal method converts ACL data into JSON format.
114 * Note: Caller needs to invoke 'free' when finished done using
117 char * BinToAclJSON(const OicSecAcl_t * acl)
119 cJSON *jsonRoot = NULL;
120 char *jsonStr = NULL;
124 jsonRoot = cJSON_CreateObject();
125 VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
127 cJSON *jsonAclArray = NULL;
128 cJSON_AddItemToObject (jsonRoot, OIC_JSON_ACL_NAME, jsonAclArray = cJSON_CreateArray());
129 VERIFY_NON_NULL(TAG, jsonAclArray, ERROR);
133 char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {};
136 B64Result b64Ret = B64_OK;
138 cJSON *jsonAcl = cJSON_CreateObject();
140 // Subject -- Mandatory
142 if (memcmp(&(acl->subject), &WILDCARD_SUBJECT_ID, sizeof(OicUuid_t)) == 0)
144 inLen = WILDCARD_SUBJECT_ID_LEN;
148 inLen = sizeof(OicUuid_t);
150 b64Ret = b64Encode(acl->subject.id, inLen, base64Buff,
151 sizeof(base64Buff), &outLen);
152 VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
153 cJSON_AddStringToObject(jsonAcl, OIC_JSON_SUBJECT_NAME, base64Buff );
155 // Resources -- Mandatory
156 cJSON *jsonRsrcArray = NULL;
157 cJSON_AddItemToObject (jsonAcl, OIC_JSON_RESOURCES_NAME, jsonRsrcArray = cJSON_CreateArray());
158 VERIFY_NON_NULL(TAG, jsonRsrcArray, ERROR);
159 for (size_t i = 0; i < acl->resourcesLen; i++)
161 cJSON_AddItemToArray (jsonRsrcArray, cJSON_CreateString(acl->resources[i]));
164 // Permissions -- Mandatory
165 cJSON_AddNumberToObject (jsonAcl, OIC_JSON_PERMISSION_NAME, acl->permission);
167 //Period & Recurrence -- Not Mandatory
168 if(0 != acl->prdRecrLen)
170 cJSON *jsonPeriodArray = NULL;
171 cJSON_AddItemToObject (jsonAcl, OIC_JSON_PERIODS_NAME,
172 jsonPeriodArray = cJSON_CreateArray());
173 VERIFY_NON_NULL(TAG, jsonPeriodArray, ERROR);
174 for (size_t i = 0; i < acl->prdRecrLen; i++)
176 cJSON_AddItemToArray (jsonPeriodArray,
177 cJSON_CreateString(acl->periods[i]));
181 //Recurrence -- Not Mandatory
182 if(0 != acl->prdRecrLen && acl->recurrences)
184 cJSON *jsonRecurArray = NULL;
185 cJSON_AddItemToObject (jsonAcl, OIC_JSON_RECURRENCES_NAME,
186 jsonRecurArray = cJSON_CreateArray());
187 VERIFY_NON_NULL(TAG, jsonRecurArray, ERROR);
188 for (size_t i = 0; i < acl->prdRecrLen; i++)
190 cJSON_AddItemToArray (jsonRecurArray,
191 cJSON_CreateString(acl->recurrences[i]));
195 // Owners -- Mandatory
196 cJSON *jsonOwnrArray = NULL;
197 cJSON_AddItemToObject (jsonAcl, OIC_JSON_OWNERS_NAME, jsonOwnrArray = cJSON_CreateArray());
198 VERIFY_NON_NULL(TAG, jsonOwnrArray, ERROR);
199 for (size_t i = 0; i < acl->ownersLen; i++)
203 b64Ret = b64Encode(acl->owners[i].id, sizeof(((OicUuid_t*)0)->id), base64Buff,
204 sizeof(base64Buff), &outLen);
205 VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
207 cJSON_AddItemToArray (jsonOwnrArray, cJSON_CreateString(base64Buff));
210 // Attach current acl node to Acl Array
211 cJSON_AddItemToArray(jsonAclArray, jsonAcl);
215 jsonStr = cJSON_PrintUnformatted(jsonRoot);
221 cJSON_Delete(jsonRoot);
227 * This internal method converts JSON ACL into binary ACL.
229 OicSecAcl_t * JSONToAclBin(const char * jsonStr)
231 OCStackResult ret = OC_STACK_ERROR;
232 OicSecAcl_t * headAcl = NULL;
233 OicSecAcl_t * prevAcl = NULL;
234 cJSON *jsonRoot = NULL;
235 cJSON *jsonAclArray = NULL;
237 VERIFY_NON_NULL(TAG, jsonStr, ERROR);
239 jsonRoot = cJSON_Parse(jsonStr);
240 VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
242 jsonAclArray = cJSON_GetObjectItem(jsonRoot, OIC_JSON_ACL_NAME);
243 VERIFY_NON_NULL(TAG, jsonAclArray, ERROR);
245 if (cJSON_Array == jsonAclArray->type)
247 int numAcl = cJSON_GetArraySize(jsonAclArray);
250 VERIFY_SUCCESS(TAG, numAcl > 0, INFO);
253 cJSON *jsonAcl = cJSON_GetArrayItem(jsonAclArray, idx);
254 VERIFY_NON_NULL(TAG, jsonAcl, ERROR);
256 OicSecAcl_t *acl = (OicSecAcl_t*)OICCalloc(1, sizeof(OicSecAcl_t));
257 VERIFY_NON_NULL(TAG, acl, ERROR);
259 headAcl = (headAcl) ? headAcl : acl;
265 size_t jsonObjLen = 0;
266 cJSON *jsonObj = NULL;
268 unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
270 B64Result b64Ret = B64_OK;
272 // Subject -- Mandatory
273 jsonObj = cJSON_GetObjectItem(jsonAcl, OIC_JSON_SUBJECT_NAME);
274 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
275 VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR);
277 b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring), base64Buff,
278 sizeof(base64Buff), &outLen);
279 VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(acl->subject.id)), ERROR);
280 memcpy(acl->subject.id, base64Buff, outLen);
282 // Resources -- Mandatory
283 jsonObj = cJSON_GetObjectItem(jsonAcl, OIC_JSON_RESOURCES_NAME);
284 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
285 VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR);
287 acl->resourcesLen = (size_t)cJSON_GetArraySize(jsonObj);
288 VERIFY_SUCCESS(TAG, acl->resourcesLen > 0, ERROR);
289 acl->resources = (char**)OICCalloc(acl->resourcesLen, sizeof(char*));
290 VERIFY_NON_NULL(TAG, (acl->resources), ERROR);
295 cJSON *jsonRsrc = cJSON_GetArrayItem(jsonObj, idxx);
296 VERIFY_NON_NULL(TAG, jsonRsrc, ERROR);
298 jsonObjLen = strlen(jsonRsrc->valuestring) + 1;
299 acl->resources[idxx] = (char*)OICMalloc(jsonObjLen);
300 VERIFY_NON_NULL(TAG, (acl->resources[idxx]), ERROR);
301 OICStrcpy(acl->resources[idxx], jsonObjLen, jsonRsrc->valuestring);
302 } while ( ++idxx < acl->resourcesLen);
304 // Permissions -- Mandatory
305 jsonObj = cJSON_GetObjectItem(jsonAcl,
306 OIC_JSON_PERMISSION_NAME);
307 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
308 VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
309 acl->permission = jsonObj->valueint;
311 //Period -- Not Mandatory
312 cJSON *jsonPeriodObj = cJSON_GetObjectItem(jsonAcl,
313 OIC_JSON_PERIODS_NAME);
316 VERIFY_SUCCESS(TAG, cJSON_Array == jsonPeriodObj->type,
318 acl->prdRecrLen = (size_t)cJSON_GetArraySize(jsonPeriodObj);
319 if(acl->prdRecrLen > 0)
321 acl->periods = (char**)OICCalloc(acl->prdRecrLen,
323 VERIFY_NON_NULL(TAG, acl->periods, ERROR);
325 cJSON *jsonPeriod = NULL;
326 for(size_t i = 0; i < acl->prdRecrLen; i++)
328 jsonPeriod = cJSON_GetArrayItem(jsonPeriodObj, i);
329 VERIFY_NON_NULL(TAG, jsonPeriod, ERROR);
331 jsonObjLen = strlen(jsonPeriod->valuestring) + 1;
332 acl->periods[i] = (char*)OICMalloc(jsonObjLen);
333 VERIFY_NON_NULL(TAG, acl->periods[i], ERROR);
334 OICStrcpy(acl->periods[i], jsonObjLen,
335 jsonPeriod->valuestring);
340 //Recurrence -- Not mandatory
341 cJSON *jsonRecurObj = cJSON_GetObjectItem(jsonAcl,
342 OIC_JSON_RECURRENCES_NAME);
345 VERIFY_SUCCESS(TAG, cJSON_Array == jsonRecurObj->type,
348 if(acl->prdRecrLen > 0)
350 acl->recurrences = (char**)OICCalloc(acl->prdRecrLen,
352 VERIFY_NON_NULL(TAG, acl->recurrences, ERROR);
354 cJSON *jsonRecur = NULL;
355 for(size_t i = 0; i < acl->prdRecrLen; i++)
357 jsonRecur = cJSON_GetArrayItem(jsonRecurObj, i);
358 VERIFY_NON_NULL(TAG, jsonRecur, ERROR);
359 jsonObjLen = strlen(jsonRecur->valuestring) + 1;
360 acl->recurrences[i] = (char*)OICMalloc(jsonObjLen);
361 VERIFY_NON_NULL(TAG, acl->recurrences[i], ERROR);
362 OICStrcpy(acl->recurrences[i], jsonObjLen,
363 jsonRecur->valuestring);
368 // Owners -- Mandatory
369 jsonObj = cJSON_GetObjectItem(jsonAcl, OIC_JSON_OWNERS_NAME);
370 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
371 VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR);
373 acl->ownersLen = (size_t)cJSON_GetArraySize(jsonObj);
374 VERIFY_SUCCESS(TAG, acl->ownersLen > 0, ERROR);
375 acl->owners = (OicUuid_t*)OICCalloc(acl->ownersLen, sizeof(OicUuid_t));
376 VERIFY_NON_NULL(TAG, (acl->owners), ERROR);
381 cJSON *jsonOwnr = cJSON_GetArrayItem(jsonObj, idxx);
382 VERIFY_NON_NULL(TAG, jsonOwnr, ERROR);
383 VERIFY_SUCCESS(TAG, cJSON_String == jsonOwnr->type, ERROR);
386 b64Ret = b64Decode(jsonOwnr->valuestring, strlen(jsonOwnr->valuestring), base64Buff,
387 sizeof(base64Buff), &outLen);
389 VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(acl->owners[idxx].id)),
391 memcpy(acl->owners[idxx].id, base64Buff, outLen);
392 } while ( ++idxx < acl->ownersLen);
395 } while( ++idx < numAcl);
401 cJSON_Delete(jsonRoot);
402 if (OC_STACK_OK != ret)
404 DeleteACLList(headAcl);
410 static bool UpdatePersistentStorage(const OicSecAcl_t *acl)
412 // Convert ACL data into JSON for update to persistent storage
413 char *jsonStr = BinToAclJSON(acl);
416 cJSON *jsonAcl = cJSON_Parse(jsonStr);
419 if ((jsonAcl) && (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_ACL_NAME, jsonAcl)))
423 cJSON_Delete(jsonAcl);
429 * This method removes ACE for the subject and resource from the ACL
431 * @param subject - subject of the ACE
432 * @param resource - resource of the ACE
435 * OC_STACK_RESOURCE_DELETED on success
436 * OC_STACK_NO_RESOURC on failure to find the appropriate ACE
437 * OC_STACK_INVALID_PARAM on invalid parameter
439 static OCStackResult RemoveACE(const OicUuid_t * subject,
440 const char * resource)
442 OIC_LOG(DEBUG, TAG, "IN RemoveACE");
444 OicSecAcl_t *acl = NULL;
445 OicSecAcl_t *tempAcl = NULL;
446 bool deleteFlag = false;
447 OCStackResult ret = OC_STACK_NO_RESOURCE;
449 if(memcmp(subject->id, &WILDCARD_SUBJECT_ID, sizeof(subject->id)) == 0)
451 OIC_LOG_V (ERROR, TAG, "%s received invalid parameter", __func__ );
452 return OC_STACK_INVALID_PARAM;
455 //If resource is NULL then delete all the ACE for the subject.
456 if(NULL == resource || resource[0] == '\0')
458 LL_FOREACH_SAFE(gAcl, acl, tempAcl)
460 if(memcmp(acl->subject.id, subject->id, sizeof(subject->id)) == 0)
462 LL_DELETE(gAcl, acl);
470 //Looping through ACL to find the right ACE to delete. If the required resource is the only
471 //resource in the ACE for the subject then delete the whole ACE. If there are more resources
472 //than the required resource in the ACE, for the subject then just delete the resource from
474 LL_FOREACH_SAFE(gAcl, acl, tempAcl)
476 if(memcmp(acl->subject.id, subject->id, sizeof(subject->id)) == 0)
478 if(1 == acl->resourcesLen && strcmp(acl->resources[0], resource) == 0)
480 LL_DELETE(gAcl, acl);
489 for(i = 0; i < acl->resourcesLen; i++)
491 if(strcmp(acl->resources[i], resource) == 0)
499 OICFree(acl->resources[resPos]);
500 acl->resources[resPos] = NULL;
501 acl->resourcesLen -= 1;
502 for(i = (size_t)resPos; i < acl->resourcesLen; i++)
504 acl->resources[i] = acl->resources[i+1];
516 if(UpdatePersistentStorage(gAcl))
518 ret = OC_STACK_RESOURCE_DELETED;
525 * This method parses the query string received for REST requests and
526 * retrieves the 'subject' field.
528 * @param query querystring passed in REST request
529 * @param subject subject UUID parsed from query string
531 * @return true if query parsed successfully and found 'subject', else false.
533 static bool GetSubjectFromQueryString(const char *query, OicUuid_t *subject)
535 OicParseQueryIter_t parseIter = {.attrPos=NULL};
537 ParseQueryIterInit((unsigned char *)query, &parseIter);
540 while(GetNextQuery(&parseIter))
542 if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_SUBJECT_NAME, parseIter.attrLen) == 0)
544 VERIFY_SUCCESS(TAG, 0 != parseIter.valLen, ERROR);
545 unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
547 B64Result b64Ret = B64_OK;
548 b64Ret = b64Decode((char *)parseIter.valPos, parseIter.valLen, base64Buff,
549 sizeof(base64Buff), &outLen);
550 VERIFY_SUCCESS(TAG, (B64_OK == b64Ret && outLen <= sizeof(subject->id)), ERROR);
551 memcpy(subject->id, base64Buff, outLen);
562 * This method parses the query string received for REST requests and
563 * retrieves the 'resource' field.
565 * @param query querystring passed in REST request
566 * @param resource resource parsed from query string
567 * @param resourceSize size of the memory pointed to resource
569 * @return true if query parsed successfully and found 'resource', else false.
571 static bool GetResourceFromQueryString(const char *query, char *resource, size_t resourceSize)
573 OicParseQueryIter_t parseIter = {.attrPos=NULL};
575 ParseQueryIterInit((unsigned char *)query, &parseIter);
577 while(GetNextQuery(&parseIter))
579 if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_RESOURCES_NAME, parseIter.attrLen) == 0)
581 VERIFY_SUCCESS(TAG, 0 != parseIter.valLen, ERROR);
582 OICStrcpy(resource, resourceSize, (char *)parseIter.valPos);
594 static OCEntityHandlerResult HandleACLGetRequest (const OCEntityHandlerRequest * ehRequest)
596 OCEntityHandlerResult ehRet = OC_EH_ERROR;
597 char* jsonStr = NULL;
599 // Process the REST querystring parameters
602 OIC_LOG (DEBUG, TAG, "HandleACLGetRequest processing query");
604 OicUuid_t subject = {.id={0}};
605 char resource[MAX_URI_LENGTH] = {0};
607 OicSecAcl_t *savePtr = NULL;
608 const OicSecAcl_t *currentAce = NULL;
610 // 'Subject' field is MUST for processing a querystring in REST request.
612 true == GetSubjectFromQueryString(ehRequest->query, &subject),
615 GetResourceFromQueryString(ehRequest->query, resource, sizeof(resource));
618 * TODO : Currently, this code only provides one ACE for a Subject.
619 * Below code needs to be updated for scenarios when Subject have
620 * multiple ACE's in ACL resource.
622 while((currentAce = GetACLResourceData(&subject, &savePtr)))
625 * If REST querystring contains a specific resource, we need
626 * to search for that resource in ACE.
628 if (resource[0] != '\0')
630 for(size_t n = 0; n < currentAce->resourcesLen; n++)
632 if((currentAce->resources[n]) &&
633 (0 == strcmp(resource, currentAce->resources[n]) ||
634 0 == strcmp(WILDCARD_RESOURCE_URI, currentAce->resources[n])))
636 // Convert ACL data into JSON for transmission
637 jsonStr = BinToAclJSON(currentAce);
644 // Convert ACL data into JSON for transmission
645 jsonStr = BinToAclJSON(currentAce);
652 // Convert ACL data into JSON for transmission
653 jsonStr = BinToAclJSON(gAcl);
657 ehRet = (jsonStr ? OC_EH_OK : OC_EH_ERROR);
659 // Send response payload to request originator
660 SendSRMResponse(ehRequest, ehRet, jsonStr);
664 OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
668 static OCEntityHandlerResult HandleACLPostRequest (const OCEntityHandlerRequest * ehRequest)
670 OCEntityHandlerResult ehRet = OC_EH_ERROR;
672 // Convert JSON ACL data into binary. This will also validate the ACL data received.
673 OicSecAcl_t* newAcl = JSONToAclBin(((OCSecurityPayload*)ehRequest->payload)->securityData);
677 // Append the new ACL to existing ACL
678 LL_APPEND(gAcl, newAcl);
680 if(UpdatePersistentStorage(gAcl))
682 ehRet = OC_EH_RESOURCE_CREATED;
686 // Send payload to request originator
687 SendSRMResponse(ehRequest, ehRet, NULL);
689 OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
693 static OCEntityHandlerResult HandleACLDeleteRequest(const OCEntityHandlerRequest *ehRequest)
695 OIC_LOG (DEBUG, TAG, "Processing ACLDeleteRequest");
696 OCEntityHandlerResult ehRet = OC_EH_ERROR;
697 OicUuid_t subject = {.id={0}};
698 char resource[MAX_URI_LENGTH] = {0};
700 VERIFY_NON_NULL(TAG, ehRequest->query, ERROR);
702 // 'Subject' field is MUST for processing a querystring in REST request.
704 true == GetSubjectFromQueryString(ehRequest->query, &subject),
707 GetResourceFromQueryString(ehRequest->query, resource, sizeof(resource));
709 if(OC_STACK_RESOURCE_DELETED == RemoveACE(&subject, resource))
711 ehRet = OC_EH_RESOURCE_DELETED;
715 // Send payload to request originator
716 SendSRMResponse(ehRequest, ehRet, NULL);
722 * This internal method is the entity handler for ACL resources and
723 * will handle REST request (GET/PUT/POST/DEL) for them.
725 OCEntityHandlerResult ACLEntityHandler (OCEntityHandlerFlag flag,
726 OCEntityHandlerRequest * ehRequest,
727 void* callbackParameter)
729 OIC_LOG(DEBUG, TAG, "Received request ACLEntityHandler");
730 (void)callbackParameter;
731 OCEntityHandlerResult ehRet = OC_EH_ERROR;
738 if (flag & OC_REQUEST_FLAG)
740 // TODO : Handle PUT method
741 OIC_LOG (DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
742 switch (ehRequest->method)
745 ehRet = HandleACLGetRequest(ehRequest);
749 ehRet = HandleACLPostRequest(ehRequest);
753 ehRet = HandleACLDeleteRequest(ehRequest);
758 SendSRMResponse(ehRequest, ehRet, NULL);
766 * This internal method is used to create '/oic/sec/acl' resource.
768 OCStackResult CreateACLResource()
772 ret = OCCreateResource(&gAclHandle,
773 OIC_RSRC_TYPE_SEC_ACL,
778 OC_OBSERVABLE | OC_SECURE | OC_EXPLICIT_DISCOVERABLE);
780 if (OC_STACK_OK != ret)
782 OIC_LOG (FATAL, TAG, "Unable to instantiate ACL resource");
789 * This internal method is to retrieve the default ACL.
790 * If SVR database in persistent storage got corrupted or
791 * is not available for some reason, a default ACL is created
792 * which allows user to initiate ACL provisioning again.
794 OCStackResult GetDefaultACL(OicSecAcl_t** defaultAcl)
796 OCStackResult ret = OC_STACK_ERROR;
798 OicUuid_t ownerId = {.id = {0}};
801 * TODO In future, when new virtual resources will be added in OIC
802 * specification, Iotivity stack should be able to add them in
803 * existing SVR database. To support this, we need to add 'versioning'
804 * mechanism in SVR database.
807 const char *rsrcs[] = {
808 OC_RSRVD_WELL_KNOWN_URI,
810 OC_RSRVD_PLATFORM_URI,
811 OC_RSRVD_RESOURCE_TYPES_URI,
813 OC_RSRVD_PRESENCE_URI,
814 #endif //WITH_PRESENCE
822 return OC_STACK_INVALID_PARAM;
825 OicSecAcl_t *acl = (OicSecAcl_t *)OICCalloc(1, sizeof(OicSecAcl_t));
826 VERIFY_NON_NULL(TAG, acl, ERROR);
828 // Subject -- Mandatory
829 memcpy(&(acl->subject), &WILDCARD_SUBJECT_ID, sizeof(acl->subject));
831 // Resources -- Mandatory
832 acl->resourcesLen = sizeof(rsrcs)/sizeof(rsrcs[0]);
834 acl->resources = (char**)OICCalloc(acl->resourcesLen, sizeof(char*));
835 VERIFY_NON_NULL(TAG, (acl->resources), ERROR);
837 for (size_t i = 0; i < acl->resourcesLen; i++)
839 size_t len = strlen(rsrcs[i]) + 1;
840 acl->resources[i] = (char*)OICMalloc(len * sizeof(char));
841 VERIFY_NON_NULL(TAG, (acl->resources[i]), ERROR);
842 OICStrcpy(acl->resources[i], len, rsrcs[i]);
845 acl->permission = PERMISSION_READ;
848 acl->recurrences = NULL;
850 // Device ID is the owner of this default ACL
851 ret = GetDoxmDeviceID( &ownerId);
852 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, FATAL);
855 acl->owners = (OicUuid_t*)OICMalloc(sizeof(OicUuid_t));
856 VERIFY_NON_NULL(TAG, (acl->owners), ERROR);
857 memcpy(acl->owners, &ownerId, sizeof(OicUuid_t));
866 if (ret != OC_STACK_OK)
876 * Initialize ACL resource by loading data from persistent storage.
878 * @retval OC_STACK_OK for Success, otherwise some error value
880 OCStackResult InitACLResource()
882 OCStackResult ret = OC_STACK_ERROR;
884 // Read ACL resource from PS
885 char* jsonSVRDatabase = GetSVRDatabase();
889 // Convert JSON ACL into binary format
890 gAcl = JSONToAclBin(jsonSVRDatabase);
891 OICFree(jsonSVRDatabase);
894 * If SVR database in persistent storage got corrupted or
895 * is not available for some reason, a default ACL is created
896 * which allows user to initiate ACL provisioning again.
898 if (!jsonSVRDatabase || !gAcl)
900 GetDefaultACL(&gAcl);
901 // TODO Needs to update persistent storage
903 VERIFY_NON_NULL(TAG, gAcl, FATAL);
905 // Instantiate 'oic.sec.acl'
906 ret = CreateACLResource();
909 if (OC_STACK_OK != ret)
917 * Perform cleanup for ACL resources.
921 void DeInitACLResource()
923 OCDeleteResource(gAclHandle);
931 * This method is used by PolicyEngine to retrieve ACL for a Subject.
933 * @param subjectId ID of the subject for which ACL is required.
934 * @param savePtr is used internally by @ref GetACLResourceData to maintain index between
935 * successive calls for same subjectId.
937 * @retval reference to @ref OicSecAcl_t if ACL is found, else NULL
939 * @note On the first call to @ref GetACLResourceData, savePtr should point to NULL
941 const OicSecAcl_t* GetACLResourceData(const OicUuid_t* subjectId, OicSecAcl_t **savePtr)
943 OicSecAcl_t *acl = NULL;
944 OicSecAcl_t *begin = NULL;
946 if ( NULL == subjectId)
952 * savePtr MUST point to NULL if this is the 'first' call to retrieve ACL for
955 if (NULL == *savePtr)
962 * If this is a 'successive' call, search for location pointed by
963 * savePtr and assign 'begin' to the next ACL after it in the linked
964 * list and start searching from there.
966 LL_FOREACH(gAcl, acl)
975 // Find the next ACL corresponding to the 'subjectID' and return it.
976 LL_FOREACH(begin, acl)
978 if (memcmp(&(acl->subject), subjectId, sizeof(OicUuid_t)) == 0)
985 // Cleanup in case no ACL is found
991 OCStackResult InstallNewACL(const char* newJsonStr)
993 OCStackResult ret = OC_STACK_ERROR;
995 // Convert JSON ACL data into binary. This will also validate the ACL data received.
996 OicSecAcl_t* newAcl = JSONToAclBin(newJsonStr);
1000 // Append the new ACL to existing ACL
1001 LL_APPEND(gAcl, newAcl);
1003 // Convert ACL data into JSON for update to persistent storage
1004 char *jsonStr = BinToAclJSON(gAcl);
1007 cJSON *jsonAcl = cJSON_Parse(jsonStr);
1012 ret = UpdateSVRDatabase(OIC_JSON_ACL_NAME, jsonAcl);
1014 cJSON_Delete(jsonAcl);
1022 * This function generates default ACL for security resource in case of owned status.
1024 * @retval Default ACL for security resource.
1026 static OicSecAcl_t* GetSecDefaultACL()
1028 const char *sec_rsrcs[] = {
1033 OicSecAcl_t* newDefaultAcl = (OicSecAcl_t*)OICCalloc(1, sizeof(OicSecAcl_t));
1034 VERIFY_NON_NULL(TAG, newDefaultAcl, ERROR);
1036 // Subject -- Mandatory
1037 memcpy(&(newDefaultAcl->subject), &WILDCARD_SUBJECT_ID, WILDCARD_SUBJECT_ID_LEN);
1039 // Resources -- Mandatory
1040 newDefaultAcl->resourcesLen = NUMBER_OF_DEFAULT_SEC_RSCS;
1041 newDefaultAcl->resources = (char**)OICCalloc(NUMBER_OF_DEFAULT_SEC_RSCS, sizeof(char*));
1042 VERIFY_NON_NULL(TAG, (newDefaultAcl->resources), ERROR);
1044 for (size_t i = 0; i < NUMBER_OF_DEFAULT_SEC_RSCS; i++)
1046 size_t len = strlen(sec_rsrcs[i]) + 1;
1047 newDefaultAcl->resources[i] = (char*)OICMalloc(len * sizeof(char));
1048 VERIFY_NON_NULL(TAG, (newDefaultAcl->resources[i]), ERROR);
1049 OICStrcpy(newDefaultAcl->resources[i], len, sec_rsrcs[i]);
1052 // Permissions -- Mandatory
1053 newDefaultAcl->permission = PERMISSION_READ;
1055 //Period -- Not Mandatory
1056 newDefaultAcl->prdRecrLen = 0;
1057 newDefaultAcl->periods = NULL;
1059 //Recurrence -- Not Mandatory
1060 newDefaultAcl->recurrences = NULL;
1062 // Device ID is the owner of this default ACL
1063 OicUuid_t ownerId = {.id = {0}};
1064 OCStackResult res = GetDoxmDeviceID(&ownerId);
1065 VERIFY_SUCCESS(TAG, OC_STACK_OK == res, FATAL);
1067 // Owners -- Mandatory
1068 newDefaultAcl->ownersLen = 1;
1069 newDefaultAcl->owners = (OicUuid_t*)OICMalloc(sizeof(OicUuid_t));
1070 VERIFY_NON_NULL(TAG, (newDefaultAcl->owners), ERROR);
1071 memcpy(newDefaultAcl->owners, &ownerId, sizeof(OicUuid_t));
1073 return newDefaultAcl;
1075 DeleteACLList(newDefaultAcl);
1080 OCStackResult UpdateDefaultSecProvACL()
1082 OCStackResult ret = OC_STACK_OK;
1083 OicSecAcl_t *acl = NULL;
1084 OicSecAcl_t *tmp = NULL;
1088 int matchedRsrc = 0;
1089 bool isRemoved = false;
1091 LL_FOREACH_SAFE(gAcl, acl, tmp)
1093 //Find default security resource ACL
1094 if(memcmp(&acl->subject, &WILDCARD_SUBJECT_ID, sizeof(OicUuid_t)) == 0 &&
1095 ((PERMISSION_READ | PERMISSION_WRITE) == acl->permission))
1099 for(size_t i = 0; i < acl->resourcesLen; i++)
1101 if(strncmp(acl->resources[i], OIC_RSRC_DOXM_URI,
1102 strlen(OIC_RSRC_DOXM_URI) + 1) == 0 ||
1103 strncmp(acl->resources[i], OIC_RSRC_CRED_URI,
1104 strlen(OIC_RSRC_CRED_URI) + 1) == 0 ||
1105 strncmp(acl->resources[i], OIC_RSRC_ACL_URI,
1106 strlen(OIC_RSRC_ACL_URI) + 1) == 0 ||
1107 strncmp(acl->resources[i], OIC_RSRC_PSTAT_URI,
1108 strlen(OIC_RSRC_PSTAT_URI) + 1) == 0)
1114 //If default security resource ACL is detected, delete it.
1115 if(NUMBER_OF_SEC_PROV_RSCS == matchedRsrc)
1117 LL_DELETE(gAcl, acl);
1127 * Generate new security resource ACL as follows :
1129 * resources : '/oic/sec/doxm', '/oic/sec/pstat'
1132 OicSecAcl_t* newDefaultAcl = GetSecDefaultACL();
1135 LL_APPEND(gAcl, newDefaultAcl);
1137 char *jsonStr = BinToAclJSON(gAcl);
1140 cJSON *jsonAcl = cJSON_Parse(jsonStr);
1146 ret = UpdateSVRDatabase(OIC_JSON_ACL_NAME, jsonAcl);
1147 if(OC_STACK_OK != ret)
1149 OIC_LOG(WARNING, TAG, "Failed to update SVR DB");
1152 cJSON_Delete(jsonAcl);