From 2c5b9d1fa9fe6af0877e29e64e018908d88133a2 Mon Sep 17 00:00:00 2001 From: Moumita Ray Date: Tue, 28 Apr 2015 14:14:54 -0700 Subject: [PATCH] Added new function in EntityHandler to parse and validate query string. IOT-491: When client creates a resource and calls GET with different resource type name and interface,GET should fail but it is successful. Analysis: Since APP creates resource, it should know the resource/interface types and it should check for resourceTypeName and ResourceInterface to identify a known resource prior to handle entity Request. Change-Id: I9159b465bf708a4cb5835f4b3adf0aea3a2c87bb Signed-off-by: Moumita Ray Reviewed-on: https://gerrit.iotivity.org/gerrit/860 Tested-by: jenkins-iotivity Reviewed-by: Erich Keane --- .../linux/SimpleClientServer/ocserver.cpp | 178 +++++++++++++----- .../linux/SimpleClientServer/ocserver.h | 5 + resource/examples/simpleserver.cpp | 68 +++++-- 3 files changed, 189 insertions(+), 62 deletions(-) diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.cpp b/resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.cpp index 1040fc30f..f13392527 100644 --- a/resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.cpp +++ b/resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.cpp @@ -80,6 +80,11 @@ const char *platformVersion = "myPlatformVersion"; const char *supportUrl = "mySupportUrl"; const char *version = "myVersion"; +// Entity handler should check for resourceTypeName and ResourceInterface in order to GET +// the existence of a known resource +const char *resourceTypeName = "core.light"; +const char *resourceInterface = "oc.mi.def"; + OCDeviceInfo deviceInfo; //This function takes the request as an input and returns the response @@ -169,10 +174,53 @@ bool checkIfQueryForPowerPassed(char * query) return true; } +/* This method check the validity of resourceTypeName and resource interfaces + * Entity Handler has to parse the query string in order to process it + */ + +OCEntityHandlerResult ValidateQueryParams (OCEntityHandlerRequest *entityHandlerRequest) +{ + bool resourceList = true; + uint8_t resourceIndex = 0; + OCEntityHandlerResult ehResult = OC_EH_ERROR; + + // Validate pointer + if (!entityHandlerRequest) + { + OC_LOG (ERROR, TAG, "Invalid request pointer"); + return ehResult; + } + //Added check for resource type & interface in server entity handle + + while(resourceList) + { + const char* typeName = OCGetResourceTypeName(entityHandlerRequest->resource, + resourceIndex); + const char* interfaceName = OCGetResourceInterfaceName(entityHandlerRequest->resource, + resourceIndex); + if(typeName && interfaceName) + { + if(strcmp(typeName,resourceTypeName) == 0 && + strcmp(interfaceName,resourceInterface) == 0) + { + ehResult = OC_EH_OK; + break; + } + resourceIndex++; + } + else + { + resourceList = false; + } + } + return ehResult; +} + OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize) { OCEntityHandlerResult ehResult; + char *getResp = constructJsonResponse(ehRequest); bool queryPassed = checkIfQueryForPowerPassed(ehRequest->query); @@ -462,7 +510,7 @@ OCDeviceEntityHandlerCb (OCEntityHandlerFlag flag, { OC_LOG_V (INFO, TAG, "Inside device default entity handler - flags: 0x%x, uri: %s", flag, uri); - OCEntityHandlerResult ehResult = OC_EH_OK; + OCEntityHandlerResult ehResult = OC_EH_ERROR; OCEntityHandlerResponse response; char payload[MAX_RESPONSE_LENGTH] = {0}; @@ -472,13 +520,17 @@ OCDeviceEntityHandlerCb (OCEntityHandlerFlag flag, OC_LOG (ERROR, TAG, "Invalid request pointer"); return OC_EH_ERROR; } - // Initialize certain response fields response.numSendVendorSpecificHeaderOptions = 0; memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions); memset(response.resourceUri, 0, sizeof response.resourceUri); + // Entity handler to check the validity of resourceTypeName and resource interfaces + // It is Entity handler's responsibility to keep track of the list of resources prior to call + // Requested method + ehResult = ValidateQueryParams(entityHandlerRequest); + if (flag & OC_INIT_FLAG) { OC_LOG (INFO, TAG, "Flag includes OC_INIT_FLAG"); @@ -486,34 +538,43 @@ OCDeviceEntityHandlerCb (OCEntityHandlerFlag flag, if (flag & OC_REQUEST_FLAG) { OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG"); - if (entityHandlerRequest->resource == NULL) + // Entity handler to check the validity of resourceType and resource interface + if( ehResult == OC_EH_OK ) { - OC_LOG (INFO, TAG, "Received request from client to a non-existing resource"); - ehResult = ProcessNonExistingResourceRequest(entityHandlerRequest, - payload, sizeof(payload) - 1); - } - else if (OC_REST_GET == entityHandlerRequest->method) - { - OC_LOG (INFO, TAG, "Received OC_REST_GET from client"); - ehResult = ProcessGetRequest (entityHandlerRequest, payload, sizeof(payload) - 1); - } - else if (OC_REST_PUT == entityHandlerRequest->method) - { - OC_LOG (INFO, TAG, "Received OC_REST_PUT from client"); - ehResult = ProcessPutRequest (entityHandlerRequest, payload, sizeof(payload) - 1); - } - else if (OC_REST_DELETE == entityHandlerRequest->method) - { - OC_LOG (INFO, TAG, "Received OC_REST_DELETE from client"); - ehResult = ProcessDeleteRequest (entityHandlerRequest, payload, sizeof(payload) - 1); + if (entityHandlerRequest->resource == NULL) + { + OC_LOG (INFO, TAG, "Received request from client to a non-existing resource"); + ehResult = ProcessNonExistingResourceRequest(entityHandlerRequest, + payload, sizeof(payload) - 1); + } + else if (OC_REST_GET == entityHandlerRequest->method) + { + OC_LOG (INFO, TAG, "Received OC_REST_GET from client"); + ehResult = ProcessGetRequest (entityHandlerRequest, payload, sizeof(payload) - 1); + } + else if (OC_REST_PUT == entityHandlerRequest->method) + { + OC_LOG (INFO, TAG, "Received OC_REST_PUT from client"); + ehResult = ProcessPutRequest (entityHandlerRequest, payload, sizeof(payload) - 1); + } + else if (OC_REST_DELETE == entityHandlerRequest->method) + { + OC_LOG (INFO, TAG, "Received OC_REST_DELETE from client"); + ehResult = ProcessDeleteRequest (entityHandlerRequest, payload, sizeof(payload) - 1); + } + else + { + OC_LOG_V (INFO, TAG, "Received unsupported method %d from client", + entityHandlerRequest->method); + ehResult = OC_EH_ERROR; + } } else { - OC_LOG_V (INFO, TAG, "Received unsupported method %d from client", - entityHandlerRequest->method); - ehResult = OC_EH_ERROR; + OC_LOG_V (INFO, TAG, + "Invalid ResourceInterface Type & Name received from client for method: %d ", + entityHandlerRequest->method); } - // If the result isn't an error or forbidden, send response if (!((ehResult == OC_EH_ERROR) || (ehResult == OC_EH_FORBIDDEN))) { @@ -582,6 +643,12 @@ OCEntityHandlerCb (OCEntityHandlerFlag flag, 0, sizeof response.sendVendorSpecificHeaderOptions); memset(response.resourceUri, 0, sizeof response.resourceUri); + // Entity handler to check the validity of resourceTypeName and resource interfaces + // It is Entity handler's responsibility to keep track of the list of resources prior to call + // Requested method + + ehResult = ValidateQueryParams(entityHandlerRequest); + if (flag & OC_INIT_FLAG) { OC_LOG (INFO, TAG, "Flag includes OC_INIT_FLAG"); @@ -589,33 +656,44 @@ OCEntityHandlerCb (OCEntityHandlerFlag flag, if (flag & OC_REQUEST_FLAG) { OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG"); - if (OC_REST_GET == entityHandlerRequest->method) - { - OC_LOG (INFO, TAG, "Received OC_REST_GET from client"); - ehResult = ProcessGetRequest (entityHandlerRequest, payload, sizeof(payload) - 1); - } - else if (OC_REST_PUT == entityHandlerRequest->method) - { - OC_LOG (INFO, TAG, "Received OC_REST_PUT from client"); - ehResult = ProcessPutRequest (entityHandlerRequest, payload, sizeof(payload) - 1); - } - else if (OC_REST_POST == entityHandlerRequest->method) - { - OC_LOG (INFO, TAG, "Received OC_REST_POST from client"); - ehResult = ProcessPostRequest (entityHandlerRequest, - &response, payload, sizeof(payload) - 1); - } - else if (OC_REST_DELETE == entityHandlerRequest->method) + + // Entity handler to check the validity of resourceType and resource interface + // Entity handler to check the validity of resourceType and resource interface + if(ehResult == OC_EH_OK) { - OC_LOG (INFO, TAG, "Received OC_REST_DELETE from client"); - ehResult = ProcessDeleteRequest (entityHandlerRequest, payload, sizeof(payload) - 1); + if (OC_REST_GET == entityHandlerRequest->method) + { + OC_LOG (INFO, TAG, "Received OC_REST_GET from client"); + ehResult = ProcessGetRequest (entityHandlerRequest, payload, sizeof(payload) - 1); + } + else if (OC_REST_PUT == entityHandlerRequest->method) + { + OC_LOG (INFO, TAG, "Received OC_REST_PUT from client"); + ehResult = ProcessPutRequest (entityHandlerRequest, payload, sizeof(payload) - 1); + } + else if (OC_REST_POST == entityHandlerRequest->method) + { + OC_LOG (INFO, TAG, "Received OC_REST_POST from client"); + ehResult = ProcessPostRequest (entityHandlerRequest, &response, payload, sizeof(payload) - 1); + } + else if (OC_REST_DELETE == entityHandlerRequest->method) + { + OC_LOG (INFO, TAG, "Received OC_REST_DELETE from client"); + ehResult = ProcessDeleteRequest (entityHandlerRequest, payload, sizeof(payload) - 1); + } + else + { + OC_LOG_V (INFO, TAG, "Received unsupported method %d from client", + entityHandlerRequest->method); + ehResult = OC_EH_ERROR; + } } else { - OC_LOG_V (INFO, TAG, "Received unsupported method %d from client", - entityHandlerRequest->method); + OC_LOG_V (INFO, TAG, + "Invalid ResourceInterface Type & Name received from client for method: %d ", + entityHandlerRequest->method); } - // If the result isn't an error or forbidden, send response if (!((ehResult == OC_EH_ERROR) || (ehResult == OC_EH_FORBIDDEN))) { @@ -791,7 +869,7 @@ void *presenceNotificationGenerator(void *param) sleep(1); res = OCCreateResource(&presenceNotificationHandles[i], presenceNotificationResources.at(i).c_str(), - "oc.mi.def", + resourceInterface, presenceNotificationUris.at(i).c_str(), OCNOPEntityHandlerCb, OC_DISCOVERABLE|OC_OBSERVABLE); @@ -962,8 +1040,8 @@ int createLightResource (char *uri, LightResource *lightResource) lightResource->state = false; lightResource->power= 0; OCStackResult res = OCCreateResource(&(lightResource->handle), - "core.light", - "oc.mi.def", + resourceTypeName, + resourceInterface, uri, OCEntityHandlerCb, OC_DISCOVERABLE|OC_OBSERVABLE); diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.h b/resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.h index ea6ca50d6..e6d123e72 100644 --- a/resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.h +++ b/resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.h @@ -70,6 +70,11 @@ char* constructJsonResponse (OCEntityHandlerRequest *ehRequest); */ void *ChangeLightRepresentation (void *param); +/* This method check the validity of resourceTypeName and resource interfaces + * Entity Handler has to parse the query string in order to process it + */ +OCEntityHandlerResult ValidateQueryParams (OCEntityHandlerRequest *entityHandlerRequest); + /* Following methods process the PUT, GET, POST, Delete, * & Observe requests */ OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest, diff --git a/resource/examples/simpleserver.cpp b/resource/examples/simpleserver.cpp index f1a1e28df..4b04f3ac1 100644 --- a/resource/examples/simpleserver.cpp +++ b/resource/examples/simpleserver.cpp @@ -53,6 +53,11 @@ bool isSecure = false; /// Specifies whether Entity handler is going to do slow response or not bool isSlowResponse = false; +// Entity handler should check for resourceTypeName and ResourceInterface in order to GET +// the existence of a known resource +const std::string resourceTypeLight = "core.light"; +const std::string resourceInterfaceDefault = DEFAULT_INTERFACE; + // Forward declaring the entityHandler /// This class represents a single resource named 'lightResource'. This resource has @@ -90,9 +95,12 @@ public: /// This function internally calls registerResource API. void createResource() { - std::string resourceURI = m_lightUri; //URI of the resource - std::string resourceTypeName = "core.light"; //resource type name. In this case, it is light - std::string resourceInterface = DEFAULT_INTERFACE; // resource interface. + //URI of the resource + std::string resourceURI = m_lightUri; + //resource type name. In this case, it is light + std::string resourceTypeName = resourceTypeLight; + // resource interface. + std::string resourceInterface = resourceInterfaceDefault; // OCResourceProperty is defined ocstack.h uint8_t resourceProperty; @@ -119,9 +127,12 @@ public: OCStackResult createResource1() { - std::string resourceURI = "/a/light1"; // URI of the resource - std::string resourceTypeName = "core.light"; // resource type name. In this case, it is light - std::string resourceInterface = DEFAULT_INTERFACE; // resource interface. + // URI of the resource + std::string resourceURI = "/a/light1"; + // resource type name. In this case, it is light + std::string resourceTypeName = resourceTypeLight; + // resource interface. + std::string resourceInterface = resourceInterfaceDefault; // OCResourceProperty is defined ocstack.h uint8_t resourceProperty; @@ -259,7 +270,6 @@ OCEntityHandlerResult entityHandler(std::shared_ptr request) if(requestFlag & RequestHandlerFlag::InitFlag) { cout << "\t\trequestFlag : Init\n"; - // entity handler to perform resource initialization operations } if(requestFlag & RequestHandlerFlag::RequestFlag) @@ -269,8 +279,43 @@ OCEntityHandlerResult entityHandler(std::shared_ptr request) pResponse->setRequestHandle(request->getRequestHandle()); pResponse->setResourceHandle(request->getResourceHandle()); + // Check for query params (if any) + QueryParamsMap queryParamsMap = request->getQueryParameters(); + + // Entity handler to check the validity of resourceTypeName and resource interfaces + // It is Entity handler's responsibility to keep track of the list of resources prior to call + // Requested method + + std::string interfaceName; + std::string typeName; + + cout << "\t\t\tquery params: \n"; + + for(auto it : queryParamsMap) + { + cout << "\t\t\t\t" << it.first << ":" << it.second << endl; + std::string firstQuery = it.first; + if(firstQuery.find_first_of("if") == 0) + { + interfaceName = it.second; + } + else if(firstQuery.find_first_of("rt") == 0 ) + { + typeName = it.second; + } + } + if(typeName.compare(resourceTypeLight) == 0 && + interfaceName.compare(resourceInterfaceDefault) == 0) + { + ehResult = OC_EH_OK; + } + else + { + cout<< "\t\t Invalid ResourceInterface Type & Name received from Client"< request) } } } - else if(requestType == "PUT") + else if(requestType == "PUT" && ehResult == OC_EH_OK) { cout << "\t\t\trequestType : PUT\n"; OCRepresentation rep = request->getResourceRepresentation(); @@ -311,7 +356,7 @@ OCEntityHandlerResult entityHandler(std::shared_ptr request) ehResult = OC_EH_OK; } } - else if(requestType == "POST") + else if(requestType == "POST" && ehResult == OC_EH_OK) { cout << "\t\t\trequestType : POST\n"; @@ -336,7 +381,7 @@ OCEntityHandlerResult entityHandler(std::shared_ptr request) ehResult = OC_EH_OK; } } - else if(requestType == "DELETE") + else if(requestType == "DELETE" && ehResult == OC_EH_OK) { // DELETE request operations } @@ -551,4 +596,3 @@ int main(int argc, char* argv[]) return 0; } - -- 2.34.1