Commit ff305fc7 authored by Shilpa Sodani's avatar Shilpa Sodani Committed by Sachin Agrawal

Updated ACL and Cred EntityHandler to process Delete Request

Added HandleACLDeleteRequest function to ACL resource to process
delete request.

Added HandelDeleteRequest function to Cred resource to process
delete request.

Changed Rest query separator to ";" from "&"

Change-Id: I5f7a0e446051f63e6aad9e49e4cbce1e34dc5f57
Signed-off-by: default avatarShilpa Sodani <shilpa.a.sodani@intel.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/2035Tested-by: default avatarjenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: default avatarSachin Agrawal <sachin.agrawal@intel.com>
parent 86daa132
......@@ -33,14 +33,54 @@
#include "srmresourcestrings.h"
#include "doxmresource.h"
#include "srmutility.h"
#include "ocserverrequest.h"
#include <stdlib.h>
#ifdef WITH_ARDUINO
#include <string.h>
#else
#include <strings.h>
#endif
#define TAG PCF("SRM-ACL")
OicSecAcl_t *gAcl = NULL;
static OCResourceHandle gAclHandle = NULL;
/**
* This function frees OicSecAcl_t object's fields and object itself.
*/
static void FreeACE(OicSecAcl_t *ace)
{
size_t i;
if(NULL == ace)
{
OC_LOG (INFO, TAG, PCF("Invalid Parameter"));
return;
}
// Clean Resources
for (i = 0; i < ace->resourcesLen; i++)
{
OICFree(ace->resources[i]);
}
OICFree(ace->resources);
//Clean Period & Recurrence
for(i = 0; i < ace->prdRecrLen; i++)
{
OICFree(ace->periods[i]);
OICFree(ace->recurrences[i]);
}
OICFree(ace->periods);
OICFree(ace->recurrences);
// Clean Owners
OICFree(ace->owners);
// Clean ACL node itself
OICFree(ace);
}
void DeleteACLList(OicSecAcl_t* acl)
{
if (acl)
......@@ -48,31 +88,8 @@ void DeleteACLList(OicSecAcl_t* acl)
OicSecAcl_t *aclTmp1 = NULL, *aclTmp2 = NULL;
LL_FOREACH_SAFE(acl, aclTmp1, aclTmp2)
{
int i = 0;
LL_DELETE(acl, aclTmp1);
// Clean Resources
for (i = 0; i < aclTmp1->resourcesLen; i++)
{
OICFree(aclTmp1->resources[i]);
}
OICFree(aclTmp1->resources);
//Clean Period & Recurrence
for(i = 0; i < aclTmp1->prdRecrLen; i++)
{
OICFree(aclTmp1->periods[i]);
OICFree(aclTmp1->recurrences[i]);
}
OICFree(aclTmp1->periods);
OICFree(aclTmp1->recurrences);
// Clean Owners
OICFree(aclTmp1->owners);
// Clean ACL node itself
OICFree(aclTmp1);
FreeACE(aclTmp1);
}
}
}
......@@ -125,7 +142,7 @@ char * BinToAclJSON(const OicSecAcl_t * acl)
cJSON *jsonRsrcArray = NULL;
cJSON_AddItemToObject (jsonAcl, OIC_JSON_RESOURCES_NAME, jsonRsrcArray = cJSON_CreateArray());
VERIFY_NON_NULL(TAG, jsonRsrcArray, ERROR);
for (int i = 0; i < acl->resourcesLen; i++)
for (size_t i = 0; i < acl->resourcesLen; i++)
{
cJSON_AddItemToArray (jsonRsrcArray, cJSON_CreateString(acl->resources[i]));
}
......@@ -165,7 +182,7 @@ char * BinToAclJSON(const OicSecAcl_t * acl)
cJSON *jsonOwnrArray = NULL;
cJSON_AddItemToObject (jsonAcl, OIC_JSON_OWNERS_NAME, jsonOwnrArray = cJSON_CreateArray());
VERIFY_NON_NULL(TAG, jsonOwnrArray, ERROR);
for (int i = 0; i < acl->ownersLen; i++)
for (size_t i = 0; i < acl->ownersLen; i++)
{
outLen = 0;
......@@ -258,7 +275,7 @@ OicSecAcl_t * JSONToAclBin(const char * jsonStr)
acl->resources = (char**)OICCalloc(acl->resourcesLen, sizeof(char*));
VERIFY_NON_NULL(TAG, (acl->resources), ERROR);
int idxx = 0;
size_t idxx = 0;
do
{
cJSON *jsonRsrc = cJSON_GetArrayItem(jsonObj, idxx);
......@@ -374,6 +391,119 @@ exit:
return headAcl;
}
static bool UpdatePersistentStorage(const OicSecAcl_t *acl)
{
// Convert ACL data into JSON for update to persistent storage
char *jsonStr = BinToAclJSON(acl);
if (jsonStr)
{
cJSON *jsonAcl = cJSON_Parse(jsonStr);
OICFree(jsonStr);
if ((jsonAcl) && (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_ACL_NAME, jsonAcl)))
{
return true;
}
cJSON_Delete(jsonAcl);
}
return false;
}
/*
* This method removes ACE for the subject and resource from the ACL
*
* @param subject - subject of the ACE
* @param resource - resource of the ACE
*
* @return
* OC_STACK_RESOURCE_DELETED on success
* OC_STACK_NO_RESOURC on failure to find the appropriate ACE
* OC_STACK_INVALID_PARAM on invalid parameter
*/
static OCStackResult RemoveACE(const OicUuid_t * subject,
const char * resource)
{
OC_LOG(INFO, TAG, PCF("IN RemoveACE"));
OicSecAcl_t *acl = NULL;
OicSecAcl_t *tempAcl = NULL;
bool deleteFlag = false;
OCStackResult ret = OC_STACK_NO_RESOURCE;
if(memcmp(subject->id, &WILDCARD_SUBJECT_ID, sizeof(subject->id)) == 0)
{
OC_LOG_V (INFO, TAG, PCF("%s received invalid parameter"), __func__ );
return OC_STACK_INVALID_PARAM;
}
//If resource is NULL then delete all the ACE for the subject.
if(NULL == resource)
{
LL_FOREACH_SAFE(gAcl, acl, tempAcl)
{
if(memcmp(acl->subject.id, subject->id, sizeof(subject->id)) == 0)
{
LL_DELETE(gAcl, acl);
FreeACE(acl);
deleteFlag = true;
}
}
}
else
{
//Looping through ACL to find the right ACE to delete. If the required resource is the only
//resource in the ACE for the subject then delete the whole ACE. If there are more resources
//than the required resource in the ACE, for the subject then just delete the resource from
//the resource array
LL_FOREACH_SAFE(gAcl, acl, tempAcl)
{
if(memcmp(acl->subject.id, subject->id, sizeof(subject->id)) == 0)
{
if(1 == acl->resourcesLen && strcmp(acl->resources[0], resource) == 0)
{
LL_DELETE(gAcl, acl);
FreeACE(acl);
deleteFlag = true;
break;
}
else
{
int resPos = -1;
size_t i;
for(i = 0; i < acl->resourcesLen; i++)
{
if(strcmp(acl->resources[i], resource) == 0)
{
resPos = i;
break;
}
}
if((0 <= resPos))
{
OICFree(acl->resources[resPos]);
acl->resources[resPos] = NULL;
acl->resourcesLen -= 1;
for(i = resPos; i < acl->resourcesLen; i++)
{
acl->resources[i] = acl->resources[i+1];
}
deleteFlag = true;
break;
}
}
}
}
}
if(deleteFlag)
{
if(UpdatePersistentStorage(gAcl))
{
ret = OC_STACK_RESOURCE_DELETED;
}
}
return ret;
}
static OCEntityHandlerResult HandleACLGetRequest (const OCEntityHandlerRequest * ehRequest)
{
// Convert ACL data into JSON for transmission
......@@ -406,19 +536,9 @@ static OCEntityHandlerResult HandleACLPostRequest (const OCEntityHandlerRequest
// Append the new ACL to existing ACL
LL_APPEND(gAcl, newAcl);
// Convert ACL data into JSON for update to persistent storage
char *jsonStr = BinToAclJSON(gAcl);
if (jsonStr)
if(UpdatePersistentStorage(gAcl))
{
cJSON *jsonAcl = cJSON_Parse(jsonStr);
OICFree(jsonStr);
if ((jsonAcl) &&
(OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_ACL_NAME, jsonAcl)))
{
ehRet = OC_EH_RESOURCE_CREATED;
}
cJSON_Delete(jsonAcl);
ehRet = OC_EH_RESOURCE_CREATED;
}
}
......@@ -429,6 +549,57 @@ static OCEntityHandlerResult HandleACLPostRequest (const OCEntityHandlerRequest
return ehRet;
}
static OCEntityHandlerResult HandleACLDeleteRequest(const OCEntityHandlerRequest *ehRequest)
{
OC_LOG (INFO, TAG, PCF("Processing ACLDeleteRequest"));
OCEntityHandlerResult ehRet = OC_EH_ERROR;
if(NULL == ehRequest->query)
{
return ehRet;
}
OicParseQueryIter_t parseIter = {.attrPos=NULL};
OicUuid_t subject = {.id={0}};
char * resource = NULL;
//Parsing REST query to get subject & resource
ParseQueryIterInit((unsigned char *)ehRequest->query, &parseIter);
while(GetNextQuery(&parseIter))
{
if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_SUBJECT_NAME, parseIter.attrLen) == 0)
{
unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
uint32_t outLen = 0;
B64Result b64Ret = B64_OK;
b64Ret = b64Decode((char *)parseIter.valPos, parseIter.valLen, base64Buff,
sizeof(base64Buff), &outLen);
VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(subject.id)), ERROR);
memcpy(subject.id, base64Buff, outLen);
}
if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_RESOURCES_NAME, parseIter.attrLen) == 0)
{
resource = (char *)OICMalloc(parseIter.valLen);
VERIFY_NON_NULL(TAG, resource, ERROR);
OICStrcpy(resource, sizeof(resource), (char *)parseIter.valPos);
}
}
if(OC_STACK_RESOURCE_DELETED == RemoveACE(&subject, resource))
{
ehRet = OC_EH_RESOURCE_DELETED;
}
OICFree(resource);
// Send payload to request originator
SendSRMResponse(ehRequest, ehRet, NULL);
exit:
return ehRet;
}
/*
* This internal method is the entity handler for ACL resources and
* will handle REST request (GET/PUT/POST/DEL) for them.
......@@ -437,6 +608,7 @@ OCEntityHandlerResult ACLEntityHandler (OCEntityHandlerFlag flag,
OCEntityHandlerRequest * ehRequest,
void* callbackParameter)
{
OC_LOG(INFO, TAG, PCF("Received request ACLEntityHandler\n"));
OCEntityHandlerResult ehRet = OC_EH_ERROR;
if (!ehRequest)
......@@ -458,6 +630,10 @@ OCEntityHandlerResult ACLEntityHandler (OCEntityHandlerFlag flag,
ehRet = HandleACLPostRequest(ehRequest);
break;
case OC_REST_DELETE:
ehRet = HandleACLDeleteRequest(ehRequest);
break;
default:
ehRet = OC_EH_ERROR;
SendSRMResponse(ehRequest, ehRet, NULL);
......@@ -500,7 +676,7 @@ OCStackResult GetDefaultACL(OicSecAcl_t** defaultAcl)
{
OCStackResult ret = OC_STACK_ERROR;
OicUuid_t ownerId = {};
OicUuid_t ownerId = {.id={}};
/*
* TODO In future, when new virtual resources will be added in OIC
......@@ -539,7 +715,7 @@ OCStackResult GetDefaultACL(OicSecAcl_t** defaultAcl)
acl->resources = (char**)OICCalloc(acl->resourcesLen, sizeof(char*));
VERIFY_NON_NULL(TAG, (acl->resources), ERROR);
for (int i = 0; i < acl->resourcesLen; i++)
for (size_t i = 0; i < acl->resourcesLen; i++)
{
size_t len = strlen(rsrcs[i]) + 1;
acl->resources[i] = (char*)OICMalloc(len * sizeof(char));
......
......@@ -34,7 +34,11 @@
#include "srmutility.h"
#include "cainterface.h"
#include <stdlib.h>
#ifdef WITH_ARDUINO
#include <string.h>
#else
#include <strings.h>
#endif
#include <stdint.h>
......@@ -43,35 +47,47 @@
static OicSecCred_t *gCred = NULL;
static OCResourceHandle gCredHandle = NULL;
void DeleteCredList(OicSecCred_t* cred)
/**
* This function frees OicSecCred_t object's fields and object itself.
*/
static void FreeCred(OicSecCred_t *cred)
{
if (cred)
if(NULL == cred)
{
OicSecCred_t *credTmp1 = NULL, *credTmp2 = NULL;
LL_FOREACH_SAFE(cred, credTmp1, credTmp2)
{
LL_DELETE(cred, credTmp1);
//Note: Need further clarification on roleID data type
OC_LOG (INFO, TAG, PCF("Invalid Parameter"));
return;
}
//Note: Need further clarification on roleID data type
#if 0
//Clean roleIds
OICFree(credTmp1->roleIds);
//Clean roleIds
OICFree(cred->roleIds);
#endif
//Clean PublicData
OICFree(credTmp1->publicData.data);
//Clean PublicData
OICFree(cred->publicData.data);
//Clean PrivateData
OICFree(credTmp1->privateData.data);
//Clean PrivateData
OICFree(cred->privateData.data);
//Clean Period
OICFree(credTmp1->period);
//Clean Period
OICFree(cred->period);
//Clean Owners
OICFree(credTmp1->owners);
//Clean Owners
OICFree(cred->owners);
//Clean Cred node itself
OICFree(credTmp1);
//Clean Cred node itself
OICFree(cred);
}
void DeleteCredList(OicSecCred_t* cred)
{
if (cred)
{
OicSecCred_t *credTmp1 = NULL, *credTmp2 = NULL;
LL_FOREACH_SAFE(cred, credTmp1, credTmp2)
{
LL_DELETE(cred, credTmp1);
FreeCred(credTmp1);
}
}
}
......@@ -395,7 +411,35 @@ exit:
return cred;
}
/*
static bool UpdatePersistentStorage(const OicSecCred_t *cred)
{
bool ret = false;
// Convert Cred data into JSON for update to persistent storage
char *jsonStr = BinToCredJSON(cred);
if (jsonStr)
{
cJSON *jsonCred = cJSON_Parse(jsonStr);
OICFree(jsonStr);
if ((jsonCred) &&
(OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_CRED_NAME, jsonCred)))
{
ret = true;
}
cJSON_Delete(jsonCred );
}
else //Empty cred list
{
if (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_CRED_NAME, NULL))
{
ret = true;
}
}
return ret;
}
/**
* Compare function used LL_SORT for sorting credentials
*
* @param first pointer to OicSecCred_t struct
......@@ -458,6 +502,8 @@ static uint16_t GetCredId()
exit:
return 0;
}
/**
* This function adds the new cred to the credential list.
*
......@@ -482,23 +528,41 @@ OCStackResult AddCredential(OicSecCred_t * newCred)
//Append the new Cred to existing list
LL_APPEND(gCred, newCred);
//Convert CredList to JSON and update the persistent Storage
jsonStr = BinToCredJSON(gCred);
if(jsonStr)
if(UpdatePersistentStorage(gCred))
{
cJSON *jsonCred = cJSON_Parse(jsonStr);
OICFree(jsonStr);
ret = OC_STACK_OK;
}
if((jsonCred) && (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_CRED_NAME, jsonCred)))
exit:
return ret;
}
OCStackResult RemoveCredential(const OicUuid_t *subject)
{
OCStackResult ret = OC_STACK_ERROR;
OicSecCred_t *cred = NULL;
OicSecCred_t *tempCred = NULL;
bool deleteFlag = false;
LL_FOREACH_SAFE(gCred, cred, tempCred)
{
if(memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
{
ret = OC_STACK_OK;
LL_DELETE(gCred, cred);
FreeCred(cred);
deleteFlag = 1;
}
cJSON_Delete(jsonCred);
}
exit:
if(deleteFlag)
{
if(UpdatePersistentStorage(gCred))
{
ret = OC_STACK_RESOURCE_DELETED;
}
}
return ret;
}
static OCEntityHandlerResult HandlePostRequest(const OCEntityHandlerRequest * ehRequest)
......@@ -520,6 +584,49 @@ static OCEntityHandlerResult HandlePostRequest(const OCEntityHandlerRequest * eh
return ret;
}
static OCEntityHandlerResult HandleDeleteRequest(const OCEntityHandlerRequest *ehRequest)
{
OC_LOG_V (INFO, TAG, PCF("Processing CredDeleteRequest"));
OCEntityHandlerResult ehRet = OC_EH_ERROR;
if(NULL == ehRequest->query)
{
return ehRet;
}
OicParseQueryIter_t parseIter = {.attrPos=NULL};
OicUuid_t subject = {.id={0}};
//Parsing REST query to get the subject
ParseQueryIterInit((unsigned char *)ehRequest->query, &parseIter);
while(GetNextQuery(&parseIter))
{
if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_SUBJECT_NAME,
parseIter.attrLen) == 0)
{
unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
uint32_t outLen = 0;
B64Result b64Ret = B64_OK;
b64Ret = b64Decode((char *)parseIter.valPos, parseIter.valLen,
base64Buff, sizeof(base64Buff), &outLen);
VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(subject.id)), ERROR);
memcpy(subject.id, base64Buff, outLen);
}
}
if(OC_STACK_RESOURCE_DELETED == RemoveCredential(&subject))
{
ehRet = OC_EH_RESOURCE_DELETED;
}
exit:
return ehRet;
}
/*
* This internal method is the entity handler for Cred resources
* to handle REST request (PUT/POST/DEL)
......@@ -546,6 +653,9 @@ OCEntityHandlerResult CredEntityHandler (OCEntityHandlerFlag flag,
case OC_REST_POST:
ret = HandlePostRequest(ehRequest);
break;
case OC_REST_DELETE:
ret = HandleDeleteRequest(ehRequest);
break;
default:
ret = OC_EH_ERROR;
break;
......@@ -655,16 +765,16 @@ const OicSecCred_t* GetCredResourceData(const OicUuid_t* subject)
{
OicSecCred_t *cred = NULL;
if ( NULL == subject)
if ( NULL == subject)
{
return NULL;
return NULL;
}
LL_FOREACH(gCred, cred)
{
if(memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
{
return cred;
return cred;
}
}
return NULL;
......
......@@ -128,6 +128,7 @@ OCStackResult UpdateSVRDatabase(const char* rsrcName, cJSON* jsonObj)
{
OCStackResult ret = OC_STACK_ERROR;
cJSON *jsonSVRDb = NULL;
OCPersistentStorage* ps = NULL;
// Read SVR database from PS
char* jsonSVRDbStr = GetSVRDatabase();
......@@ -140,7 +141,13 @@ OCStackResult UpdateSVRDatabase(const char* rsrcName, cJSON* jsonObj)
OICFree(jsonSVRDbStr);
jsonSVRDbStr = NULL;
if (jsonObj->child )
//If Cred resource gets updated with empty list then delete the Cred
//object from database.
if(NULL == jsonObj && (0 == strcmp(rsrcName, OIC_JSON_CRED_NAME)))
{
cJSON_DeleteItemFromObject(jsonSVRDb, rsrcName);
}
else if (jsonObj->child )
{
// Create a duplicate of the JSON object which was passed.
cJSON* jsonDuplicateObj = cJSON_Duplicate(jsonObj, 1);
......@@ -164,31 +171,31 @@ OCStackResult UpdateSVRDatabase(const char* rsrcName, cJSON* jsonObj)
// Replace the modified json object in existing SVR database json
cJSON_ReplaceItemInObject(jsonSVRDb, rsrcName, jsonDuplicateObj->child);
}
}
// Generate string representation of updated SVR database json object
jsonSVRDbStr = cJSON_PrintUnformatted(jsonSVRDb);
VERIFY_NON_NULL(TAG,jsonSVRDbStr, ERROR);
// Generate string representation of updated SVR database json object
jsonSVRDbStr = cJSON_PrintUnformatted(jsonSVRDb);