}
//If resource is NULL then delete all the ACE for the subject.
- if(NULL == resource)
+ if(NULL == resource || resource[0] == '\0')
{
LL_FOREACH_SAFE(gAcl, acl, tempAcl)
{
return ret;
}
+/*
+ * This method parses the query string received for REST requests and
+ * retrieves the 'subject' field.
+ *
+ * @param query querystring passed in REST request
+ * @param subject subject UUID parsed from query string
+ *
+ * @return true if query parsed successfully and found 'subject', else false.
+ */
+static bool GetSubjectFromQueryString(const char *query, OicUuid_t *subject)
+{
+ OicParseQueryIter_t parseIter = {.attrPos=NULL};
+
+ ParseQueryIterInit((unsigned char *)query, &parseIter);
+
+ while(GetNextQuery(&parseIter))
+ {
+ if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_SUBJECT_NAME, parseIter.attrLen) == 0)
+ {
+ VERIFY_SUCCESS(TAG, 0 != parseIter.valLen, ERROR);
+ 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, (B64_OK == b64Ret && outLen <= sizeof(subject->id)), ERROR);
+ memcpy(subject->id, base64Buff, outLen);
+
+ return true;
+ }
+ }
+
+exit:
+ return false;
+}
+
+/*
+ * This method parses the query string received for REST requests and
+ * retrieves the 'resource' field.
+ *
+ * @param query querystring passed in REST request
+ * @param resource resource parsed from query string
+ * @param resourceSize size of the memory pointed to resource
+ *
+ * @return true if query parsed successfully and found 'resource', else false.
+ */
+static bool GetResourceFromQueryString(const char *query, char *resource, size_t resourceSize)
+{
+ OicParseQueryIter_t parseIter = {.attrPos=NULL};
+
+ ParseQueryIterInit((unsigned char *)query, &parseIter);
+
+ while(GetNextQuery(&parseIter))
+ {
+ if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_RESOURCES_NAME, parseIter.attrLen) == 0)
+ {
+ VERIFY_SUCCESS(TAG, 0 != parseIter.valLen, ERROR);
+ OICStrcpy(resource, resourceSize, (char *)parseIter.valPos);
+
+ return true;
+ }
+ }
+
+exit:
+ return false;
+}
+
+
+
static OCEntityHandlerResult HandleACLGetRequest (const OCEntityHandlerRequest * ehRequest)
{
- // Convert ACL data into JSON for transmission
- char* jsonStr = BinToAclJSON(gAcl);
+ OCEntityHandlerResult ehRet = OC_EH_ERROR;
+ char* jsonStr = NULL;
- /*
- * A device should 'always' have a default ACL. Therefore,
- * jsonStr should never be NULL.
- */
- OCEntityHandlerResult ehRet = (jsonStr ? OC_EH_OK : OC_EH_ERROR);
+ // Process the REST querystring parameters
+ if(ehRequest->query)
+ {
+ OC_LOG (INFO, TAG, PCF("HandleACLGetRequest processing query"));
+
+ OicUuid_t subject = {.id={0}};
+ char resource[MAX_URI_LENGTH] = {0};
+
+ OicSecAcl_t *savePtr = NULL;
+ const OicSecAcl_t *currentAce = NULL;
+
+ // 'Subject' field is MUST for processing a querystring in REST request.
+ VERIFY_SUCCESS(TAG,
+ true == GetSubjectFromQueryString(ehRequest->query, &subject),
+ ERROR);
+
+ GetResourceFromQueryString(ehRequest->query, resource, sizeof(resource));
+
+ /*
+ * TODO : Currently, this code only provides one ACE for a Subject.
+ * Below code needs to be updated for scenarios when Subject have
+ * multiple ACE's in ACL resource.
+ */
+ while((currentAce = GetACLResourceData(&subject, &savePtr)))
+ {
+ /*
+ * If REST querystring contains a specific resource, we need
+ * to search for that resource in ACE.
+ */
+ if (resource[0] != '\0')
+ {
+ for(size_t n = 0; n < currentAce->resourcesLen; n++)
+ {
+ if((currentAce->resources[n]) &&
+ (0 == strcmp(resource, currentAce->resources[n]) ||
+ 0 == strcmp(WILDCARD_RESOURCE_URI, currentAce->resources[n])))
+ {
+ // Convert ACL data into JSON for transmission
+ jsonStr = BinToAclJSON(currentAce);
+ goto exit;
+ }
+ }
+ }
+ else
+ {
+ // Convert ACL data into JSON for transmission
+ jsonStr = BinToAclJSON(currentAce);
+ goto exit;
+ }
+ }
+ }
+ else
+ {
+ // Convert ACL data into JSON for transmission
+ jsonStr = BinToAclJSON(gAcl);
+ }
+
+exit:
+ ehRet = (jsonStr ? OC_EH_OK : OC_EH_ERROR);
// Send response payload to request originator
SendSRMResponse(ehRequest, ehRet, jsonStr);
{
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;
+ char resource[MAX_URI_LENGTH] = {0};
- //Parsing REST query to get subject & resource
- ParseQueryIterInit((unsigned char *)ehRequest->query, &parseIter);
+ VERIFY_NON_NULL(TAG, ehRequest->query, ERROR);
- 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;
+ // 'Subject' field is MUST for processing a querystring in REST request.
+ VERIFY_SUCCESS(TAG,
+ true == GetSubjectFromQueryString(ehRequest->query, &subject),
+ ERROR);
- 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);
- }
- }
+ GetResourceFromQueryString(ehRequest->query, resource, sizeof(resource));
if(OC_STACK_RESOURCE_DELETED == RemoveACE(&subject, resource))
{
ehRet = OC_EH_RESOURCE_DELETED;
}
- OICFree(resource);
+exit:
// Send payload to request originator
SendSRMResponse(ehRequest, ehRet, NULL);
-exit:
return ehRet;
}
if (flag & OC_REQUEST_FLAG)
{
- // TODO : Handle PUT and DEL methods
+ // TODO : Handle PUT method
OC_LOG (INFO, TAG, PCF("Flag includes OC_REQUEST_FLAG"));
switch (ehRequest->method)
{
return bRet;
}
-static bool ValidateQuery(unsigned char * query)
+static bool ValidateQuery(const char * query)
{
// Send doxm resource data if the state of doxm resource
// matches with the query parameters.
return false;
}
+ bool bOwnedQry = false; // does querystring contains 'owned' query ?
+ bool bOwnedMatch = false; // does 'owned' query value matches with doxm.owned status?
+ bool bDeviceIDQry = false; // does querystring contains 'deviceid' query ?
+ bool bDeviceIDMatch = false; // does 'deviceid' query matches with doxm.deviceid ?
+
OicParseQueryIter_t parseIter = {.attrPos = NULL};
- ParseQueryIterInit(query, &parseIter);
+ ParseQueryIterInit((unsigned char*)query, &parseIter);
while(GetNextQuery(&parseIter))
{
if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_OWNED_NAME, parseIter.attrLen) == 0)
{
+ bOwnedQry = true;
if((strncasecmp((char *)parseIter.valPos, OIC_SEC_TRUE, parseIter.valLen) == 0) &&
(gDoxm->owned))
{
- return true;
+ bOwnedMatch = true;
}
else if((strncasecmp((char *)parseIter.valPos, OIC_SEC_FALSE, parseIter.valLen) == 0)
&& (!gDoxm->owned))
{
- return true;
+ bOwnedMatch = true;
+ }
+ }
+
+ if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_DEVICE_ID_NAME, parseIter.attrLen) == 0)
+ {
+ bDeviceIDQry = true;
+ OicUuid_t subject = {.id={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, (B64_OK == b64Ret && outLen <= sizeof(subject.id)), ERROR);
+ memcpy(subject.id, base64Buff, outLen);
+ if(0 == memcmp(&gDoxm->deviceID.id, &subject.id, sizeof(gDoxm->deviceID.id)))
+ {
+ bDeviceIDMatch = true;
}
}
}
- return false;
+
+exit:
+ return ((bOwnedQry ? bOwnedMatch : true) && (bDeviceIDQry ? bDeviceIDMatch : true));
}
static OCEntityHandlerResult HandleDoxmGetRequest (const OCEntityHandlerRequest * ehRequest)
if(ehRequest->query)
{
OC_LOG (INFO, TAG, PCF("HandleDoxmGetRequest processing query"));
- if(!ValidateQuery((unsigned char *)ehRequest->query))
+ if(!ValidateQuery(ehRequest->query))
{
ehRet = OC_EH_ERROR;
}
OICFree(jsonStr);
}
}
+
+static OCStackResult populateAcl(OicSecAcl_t *acl, int numRsrc)
+{
+ OCStackResult ret = OC_STACK_ERROR;
+ memcpy(acl->subject.id, "2222222222222222", sizeof(acl->subject.id));
+ acl->resourcesLen = numRsrc;
+ acl->resources = (char**)OICCalloc(acl->resourcesLen, sizeof(char*));
+ VERIFY_NON_NULL(TAG, acl->resources, ERROR);
+ acl->resources[0] = (char*)OICMalloc(strlen("/a/led")+1);
+ VERIFY_NON_NULL(TAG, acl->resources[0], ERROR);
+ OICStrcpy(acl->resources[0], sizeof(acl->resources[0]), "/a/led");
+ if(numRsrc == 2)
+ {
+ acl->resources[1] = (char*)OICMalloc(strlen("/a/fan")+1);
+ VERIFY_NON_NULL(TAG, acl->resources[1], ERROR);
+ OICStrcpy(acl->resources[1], sizeof(acl->resources[1]), "/a/fan");
+ }
+ acl->permission = 6;
+ acl->ownersLen = 1;
+ acl->owners = (OicUuid_t*)OICCalloc(acl->ownersLen, sizeof(OicUuid_t));
+ VERIFY_NON_NULL(TAG, acl->owners, ERROR);
+ memcpy(acl->owners->id, "1111111111111111", sizeof(acl->owners->id));
+
+ ret = OC_STACK_OK;
+exit:
+ return ret;
+
+}
+
//'DELETE' ACL test
TEST(ACLResourceTest, ACLDeleteWithSingleResourceTest)
{
SetPersistentHandler(&ps, true);
- //ACE to POST
- memcpy(acl.subject.id, "2222222222222222", sizeof(acl.subject.id));
- acl.resourcesLen = 1;
- acl.resources = (char**)OICCalloc(acl.resourcesLen, sizeof(char*));
- VERIFY_NON_NULL(TAG, acl.resources, ERROR);
- acl.resources[0] = (char*)OICMalloc(strlen("/a/led")+1);
- VERIFY_NON_NULL(TAG, acl.resources[0], ERROR);
- OICStrcpy(acl.resources[0], sizeof(acl.resources[0]), "/a/led");
- acl.permission = 6;
- acl.ownersLen = 1;
- acl.owners = (OicUuid_t*)OICCalloc(acl.ownersLen, sizeof(OicUuid_t));
- VERIFY_NON_NULL(TAG, acl.owners, ERROR);
- memcpy(acl.owners->id, "1111111111111111", sizeof(acl.owners->id));
+ //Populate ACL
+ VERIFY_SUCCESS(TAG, (OC_STACK_OK == populateAcl(&acl, 1)), ERROR);
//GET json POST payload
jsonStr = BinToAclJSON(&acl);
SetPersistentHandler(&ps, true);
- memcpy(acl.subject.id, "2222222222222222", sizeof(acl.subject.id));
- acl.resourcesLen = 2;
- acl.resources = (char**)OICCalloc(acl.resourcesLen, sizeof(char*));
- VERIFY_NON_NULL(TAG, acl.resources, ERROR);
- acl.resources[0] = (char*)OICMalloc(strlen("/a/led")+1);
- VERIFY_NON_NULL(TAG, acl.resources[0], ERROR);
- OICStrcpy(acl.resources[0], sizeof(acl.resources[0]), "/a/led");
- acl.resources[1] = (char*)OICMalloc(strlen("/a/fan")+1);
- VERIFY_NON_NULL(TAG, acl.resources[1], ERROR);
- OICStrcpy(acl.resources[1], sizeof(acl.resources[1]), "/a/fan");
- acl.permission = 6;
- acl.ownersLen = 1;
- acl.owners = (OicUuid_t*)OICCalloc(acl.ownersLen, sizeof(OicUuid_t));
- VERIFY_NON_NULL(TAG, acl.owners, ERROR);
- memcpy(acl.owners->id, "1111111111111111", sizeof(acl.owners->id));
+ //Populate ACL
+ VERIFY_SUCCESS(TAG, (OC_STACK_OK == populateAcl(&acl, 2)), ERROR);
+ //GET json POST payload
jsonStr = BinToAclJSON(&acl);
VERIFY_NON_NULL(TAG, jsonStr, ERROR);
OICFree(jsonStr);
}
+//'GET' with query ACL test
+
+TEST(ACLResourceTest, ACLGetWithQueryTest)
+{
+ OCEntityHandlerRequest ehReq = OCEntityHandlerRequest();
+ static OCPersistentStorage ps = OCPersistentStorage();
+ OicSecAcl_t acl = OicSecAcl_t();
+ char *jsonStr = NULL;
+ OCEntityHandlerResult ehRet = OC_EH_ERROR;
+ char query[] = "sub=MjIyMjIyMjIyMjIyMjIyMg==;rsrc=/a/led";
+
+ SetPersistentHandler(&ps, true);
+
+ //Populate ACL
+ VERIFY_SUCCESS(TAG, (OC_STACK_OK == populateAcl(&acl, 1)), ERROR);
+
+ //GET json POST payload
+ jsonStr = BinToAclJSON(&acl);
+ VERIFY_NON_NULL(TAG, jsonStr, ERROR);
+
+ //Create Entity Handler POST request payload
+ ehReq.method = OC_REST_POST;
+ ehReq.payload = (OCPayload*)OCSecurityPayloadCreate(jsonStr);
+ ehRet = ACLEntityHandler(OC_REQUEST_FLAG, &ehReq);
+ EXPECT_TRUE(OC_EH_ERROR == ehRet);
+
+ //Create Entity Handler GET request wit query
+ ehReq.method = OC_REST_GET;
+ ehReq.query = (char*)OICMalloc(strlen(query)+1);
+ VERIFY_NON_NULL(TAG, ehReq.query, ERROR);
+ OICStrcpy(ehReq.query, strlen(query)+1, query);
+
+ ehRet = ACLEntityHandler(OC_REQUEST_FLAG, &ehReq);
+ EXPECT_TRUE(OC_EH_OK == ehRet);
+
+exit:
+ // Perform cleanup
+ OCPayloadDestroy(ehReq.payload);
+ OICFree(ehReq.query);
+ OICFree(jsonStr);
+}
OICFree(req.query);
}
+TEST(DoxmEntityHandlerTest, DoxmEntityHandlerDeviceIdQuery)
+{
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, InitDoxmResource());
+ char query[] = "deviceid=MjIyMjIyMjIyMjIyMjIyMg==";
+ OCEntityHandlerRequest req = OCEntityHandlerRequest();
+ req.method = OC_REST_GET;
+ req.query = OICStrdup(query);
+ EXPECT_EQ(OC_EH_ERROR, DoxmEntityHandler(OCEntityHandlerFlag::OC_REQUEST_FLAG, &req));
+
+ OICFree(req.query);
+}
+
//BinToDoxmJSON Tests
TEST(BinToDoxmJSONTest, BinToDoxmJSONNullDoxm)
{