From: js126.lee Date: Thu, 24 Mar 2016 11:38:07 +0000 (+0900) Subject: Add security version resource X-Git-Tag: 1.2.0+RC1~355^2^2~125 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=273312fa74d646320386fb97254599eb06f42292;p=platform%2Fupstream%2Fiotivity.git Add security version resource -Patch 1: To check security version, oic.sec.ver is created. -Patch 2: Add commit description -Patch 3.4: Apply Randeep's comment -Patch 5: Rebase -Patch 6-7: Fixed build error on Arduino -Patch 8: Modify version data type of provisioningmanager -Patch 9: Rebase -Patch 10: Update device type -Patch 11: 1) Modify to start version discovery in succession after secure port discovery 2) Separate each discovery(secureport, version) process as internal function. -Patch 12: Add null check and remove unnecessary local variables. -Patch 13: Modify the API description according to patch 11. -Patch 14: Update according to SVACE report -Patch 15: Rebase It is clone https://gerrit.iotivity.org/gerrit/#/c/6059/ of security-cbor-conv-1.1 branch after resolved conflict. Change-Id: I0de72d8cc35acb048acfb7136769f3c84c72c152 Signed-off-by: Jongsung Lee Signed-off-by: Chul Lee Reviewed-on: https://gerrit.iotivity.org/gerrit/6105 Reviewed-by: Yonggoo Kang Tested-by: jenkins-iotivity Reviewed-by: Randeep Singh --- diff --git a/resource/csdk/security/SConscript b/resource/csdk/security/SConscript index f5d2616..ccfcda0 100644 --- a/resource/csdk/security/SConscript +++ b/resource/csdk/security/SConscript @@ -100,6 +100,7 @@ if env.get('SECURED') == '1': OCSRM_SRC + 'svcresource.c', OCSRM_SRC + 'pconfresource.c', OCSRM_SRC + 'dpairingresource.c', + OCSRM_SRC + 'verresource.c', OCSRM_SRC + 'policyengine.c', OCSRM_SRC + 'psinterface.c', OCSRM_SRC + 'srmresourcestrings.c', @@ -126,6 +127,7 @@ else: OCSRM_SRC + 'pconfresource.c', OCSRM_SRC + 'dpairingresource.c', OCSRM_SRC + 'policyengine.c', + OCSRM_SRC + 'verresource.c', OCSRM_SRC + 'psinterface.c', OCSRM_SRC + 'srmresourcestrings.c', OCSRM_SRC + 'srmutility.c', diff --git a/resource/csdk/security/include/internal/srmresourcestrings.h b/resource/csdk/security/include/internal/srmresourcestrings.h old mode 100755 new mode 100644 index 6c47d87..cbc8e82 --- a/resource/csdk/security/include/internal/srmresourcestrings.h +++ b/resource/csdk/security/include/internal/srmresourcestrings.h @@ -81,6 +81,11 @@ extern const char * OIC_RSRC_TYPE_SEC_DPAIRING; extern const char * OIC_RSRC_DPAIRING_URI; extern const char * OIC_JSON_DPAIRING_NAME; +//version +extern const char * OIC_RSRC_TYPE_SEC_VER; +extern const char * OIC_RSRC_VER_URI; +extern const char * OIC_JSON_VER_NAME; + extern const char * OIC_JSON_SUBJECT_NAME; extern const char * OIC_JSON_SUBJECTID_NAME; extern const char * OIC_JSON_RESOURCES_NAME; @@ -135,6 +140,7 @@ extern const char * OIC_JSON_IF_NAME; extern const char * OIC_JSON_ROWNERID_NAME; extern const char * OIC_JSON_ENCODING_NAME; extern const char * OIC_JSON_DATA_NAME; +extern const char * OIC_JSON_SEC_V_NAME; extern const char * OIC_JSON_EMPTY_STRING; diff --git a/resource/csdk/security/include/internal/verresource.h b/resource/csdk/security/include/internal/verresource.h new file mode 100644 index 0000000..18fa03d --- /dev/null +++ b/resource/csdk/security/include/internal/verresource.h @@ -0,0 +1,98 @@ +/* ***************************************************************** + * + * Copyright 2016 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * *****************************************************************/ + +#ifndef IOTVT_SRM_VER_H +#define IOTVT_SRM_VER_H + +#include "octypes.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Initialize VER resource by loading data from persistent storage. + * + * @return ::OC_STACK_OK for Success, otherwise some error value. + */ +OCStackResult InitVerResource(); + +/** + * Perform cleanup for VER resources. + * + * @return ::OC_STACK_OK for Success, otherwise some error value. + */ +OCStackResult DeInitVerResource(); + +/** + * This method is used by SRM to retrieve VER resource data.. + * + * @return reference to @ref OicSecDoxm_t, binary format of Doxm resource data. + */ +const OicSecVer_t* GetVerResourceData(); + +/** + * This method converts CBOR VER into binary VER. + * The CBOR VER can be from persistent database or + * or received as PUT/POST request. + * + * @param cborPayload is a ver data in cbor. + * @note Caller needs to invoke OCFree after done using the return pointer. + * @param doxm is the pointer to @ref OicSecVer_t. + * @param size of the cborPayload. In case value is 0, CBOR_SIZE value is assigned. + * + * @return ::OC_STACK_OK for Success, otherwise some error value. + */ +OCStackResult CBORPayloadToVer(const uint8_t *cborPayload, size_t size, + OicSecVer_t **ver); + +/** + * This method converts VER data into CBOR format. + * Caller needs to invoke 'free' when finished done using + * return string. + * + * @param ver Pointer to @ref OicSecVer_t. + * @note Caller needs to invoke OCFree after done using the return pointer. + * @param cborPayload is the payload of the cbor. + * @param cborSize is the size of the cbor payload. Passed parameter should not be NULL. + * + * @return ::OC_STACK_OK for Success, otherwise some error value. + */ +OCStackResult VerToCBORPayload(const OicSecVer_t * ver, uint8_t **cborPayload, + size_t *cborSize); + +/** + * Get the security version. + * + * @return the version string of security. + */ +const char* GetSecVersion(); + +/** This function deallocates the memory for OicSecVer_t . + * + * @param ver is the pointer to @ref OicSecVer_t. + */ +void DeleteVerBinData(OicSecVer_t* ver); + +#ifdef __cplusplus +} +#endif + +#endif //IOTVT_SRM_VER_H \ No newline at end of file diff --git a/resource/csdk/security/include/securevirtualresourcetypes.h b/resource/csdk/security/include/securevirtualresourcetypes.h index fee8d0d..816b53a 100644 --- a/resource/csdk/security/include/securevirtualresourcetypes.h +++ b/resource/csdk/security/include/securevirtualresourcetypes.h @@ -551,6 +551,23 @@ struct OicSecDpairing OicUuid_t rowner; // 2:R:S:Y:oic.uuid }; +#define MAX_VERSION_LEN 16 // Security Version length. i.e., 00.00.000 + reserved space + +/** + * @brief security version data type + */ +typedef struct OicSecVer OicSecVer_t; + +/** + * @brief /oic/sec/ver (Security Version) data type + */ +struct OicSecVer +{ + // :::: + char secv[MAX_VERSION_LEN]; // 0:R:S:Y:String + OicUuid_t deviceID; // 1:R:S:Y:oic.uuid +}; + #ifdef __cplusplus } #endif diff --git a/resource/csdk/security/provisioning/include/ocprovisioningmanager.h b/resource/csdk/security/provisioning/include/ocprovisioningmanager.h index 54a5267..7f3dbf6 100644 --- a/resource/csdk/security/provisioning/include/ocprovisioningmanager.h +++ b/resource/csdk/security/provisioning/include/ocprovisioningmanager.h @@ -47,7 +47,7 @@ OCStackResult OCInitPM(const char* dbPath); * OCMode. * * @param[in] timeout Timeout in seconds, value till which function will listen to responses from - * client before returning the list of devices. + * server before returning the list of devices. * @param[out] ppList List of candidate devices to be provisioned * @return OTM_SUCCESS in case of success and other value otherwise. */ @@ -79,7 +79,7 @@ OCStackResult OCSetOwnerTransferCallbackData(OicSecOxm_t oxm, OTMCallbackData_t* * all the device in subnet which are owned by calling provisioning client. * * @param[in] timeout Timeout in seconds, value till which function will listen to responses from - * client before returning the list of devices. + * server before returning the list of devices. * @param[out] ppList List of device owned by provisioning tool. * @return OTM_SUCCESS in case of success and other value otherwise. */ diff --git a/resource/csdk/security/provisioning/include/pmtypes.h b/resource/csdk/security/provisioning/include/pmtypes.h index 2f23125..eede02d 100644 --- a/resource/csdk/security/provisioning/include/pmtypes.h +++ b/resource/csdk/security/provisioning/include/pmtypes.h @@ -67,6 +67,7 @@ typedef struct OCProvisionDev OicSecDoxm_t *doxm; /**< Pointer to target's doxm resource. **/ OCConnectivityType connType; /**< Connectivity type of endpoint */ uint16_t securePort; /**< secure port **/ + char secVer[MAX_VERSION_LEN]; /**< security version **/ DeviceStatus devStatus; /**< status of device **/ struct OCProvisionDev *next; /**< Next pointer. **/ }OCProvisionDev_t; diff --git a/resource/csdk/security/provisioning/sample/oic_svr_db_server_justworks.dat b/resource/csdk/security/provisioning/sample/oic_svr_db_server_justworks.dat index 97393e9..097a938 100644 Binary files a/resource/csdk/security/provisioning/sample/oic_svr_db_server_justworks.dat and b/resource/csdk/security/provisioning/sample/oic_svr_db_server_justworks.dat differ diff --git a/resource/csdk/security/provisioning/sample/oic_svr_db_server_justworks.json b/resource/csdk/security/provisioning/sample/oic_svr_db_server_justworks.json index 7f19ee7..c7e20f1 100644 --- a/resource/csdk/security/provisioning/sample/oic_svr_db_server_justworks.json +++ b/resource/csdk/security/provisioning/sample/oic_svr_db_server_justworks.json @@ -1,5 +1,5 @@ { - "acl": { + "acl": { "aclist": { "aces": [ { @@ -79,6 +79,18 @@ } ], "permission": 6 + }, + { + "subjectuuid": "*", + "resources": [ + { + "href": "/oic/sec/ver", + "rel": "", + "rt": "", + "if": "" + } + ], + "permission": 2 } ] }, diff --git a/resource/csdk/security/provisioning/sample/oic_svr_db_server_randompin.dat b/resource/csdk/security/provisioning/sample/oic_svr_db_server_randompin.dat index 344f2c4..ef473a3 100644 Binary files a/resource/csdk/security/provisioning/sample/oic_svr_db_server_randompin.dat and b/resource/csdk/security/provisioning/sample/oic_svr_db_server_randompin.dat differ diff --git a/resource/csdk/security/provisioning/sample/oic_svr_db_server_randompin.json b/resource/csdk/security/provisioning/sample/oic_svr_db_server_randompin.json index 7c6156f..7191503 100644 --- a/resource/csdk/security/provisioning/sample/oic_svr_db_server_randompin.json +++ b/resource/csdk/security/provisioning/sample/oic_svr_db_server_randompin.json @@ -1,5 +1,5 @@ { - "acl": { + "acl": { "aclist": { "aces": [ { @@ -79,6 +79,18 @@ } ], "permission": 6 + }, + { + "subjectuuid": "*", + "resources": [ + { + "href": "/oic/sec/ver", + "rel": "", + "rt": "", + "if": "" + } + ], + "permission": 2 } ] }, @@ -103,4 +115,4 @@ "rowneruuid": "72616E64-5069-6E44-6576-557569643030", "dpc": true } -} \ No newline at end of file +} diff --git a/resource/csdk/security/provisioning/src/ocprovisioningmanager.c b/resource/csdk/security/provisioning/src/ocprovisioningmanager.c index d50fc36..b5d4bed 100644 --- a/resource/csdk/security/provisioning/src/ocprovisioningmanager.c +++ b/resource/csdk/security/provisioning/src/ocprovisioningmanager.c @@ -70,7 +70,7 @@ OCStackResult OCInitPM(const char* dbPath) * OCMode. * * @param[in] timeout Timeout in seconds, value till which function will listen to responses from - * client before returning the list of devices. + * server before returning the list of devices. * @param[out] ppList List of candidate devices to be provisioned * @return OTM_SUCCESS in case of success and other value otherwise. */ @@ -89,7 +89,7 @@ OCStackResult OCDiscoverUnownedDevices(unsigned short timeout, OCProvisionDev_t * all the device in subnet which are owned by calling provisioning client. * * @param[in] timeout Timeout in seconds, value till which function will listen to responses from - * client before returning the list of devices. + * server before returning the list of devices. * @param[out] ppList List of device owned by provisioning tool. * @return OTM_SUCCESS in case of success and other value otherwise. */ diff --git a/resource/csdk/security/provisioning/src/pmutility.c b/resource/csdk/security/provisioning/src/pmutility.c index 648ca05..c03d4ce 100644 --- a/resource/csdk/security/provisioning/src/pmutility.c +++ b/resource/csdk/security/provisioning/src/pmutility.c @@ -38,6 +38,7 @@ #include "srmresourcestrings.h" //@note: SRM's internal header #include "doxmresource.h" //@note: SRM's internal header #include "pstatresource.h" //@note: SRM's internal header +#include "verresource.h" //@note: SRM's internal header #include "pmtypes.h" #include "pmutility.h" @@ -51,6 +52,65 @@ typedef struct _DiscoveryInfo{ bool isOwnedDiscovery; } DiscoveryInfo; +/* + * Function to discover secre port information through unicast + * + * @param[in] discoveryInfo The pointer of discovery information to matain result of discovery + * @param[in] clientResponse Response information(It will contain payload) + * + * @return OC_STACK_OK on success otherwise error. + */ +static OCStackResult SecurePortDiscovery(DiscoveryInfo* discoveryInfo, + const OCClientResponse *clientResponse); + +/* + * Function to discover security version information through unicast + * + * @param[in] discoveryInfo The pointer of discovery information to matain result of discovery + * @param[in] clientResponse Response information(It will contain payload) + * + * @return OC_STACK_OK on success otherwise error. + */ +static OCStackResult SecurityVersionDiscovery(DiscoveryInfo* discoveryInfo, + const OCClientResponse *clientResponse); + +/** + * Callback handler for PMDeviceDiscovery API. + * + * @param[in] ctx User context + * @param[in] handle Handler for response + * @param[in] clientResponse Response information (It will contain payload) + * @return OC_STACK_KEEP_TRANSACTION to keep transaction and + * OC_STACK_DELETE_TRANSACTION to delete it. + */ +static OCStackApplicationResult DeviceDiscoveryHandler(void *ctx, OCDoHandle UNUSED, + OCClientResponse *clientResponse); + +/** + * Callback handler for getting secure port information using /oic/res discovery. + * + * @param[in] ctx user context + * @param[in] handle Handle for response + * @param[in] clientResponse Response information(It will contain payload) + * + * @return OC_STACK_KEEP_TRANSACTION to keep transaction and + * OC_STACK_DELETE_TRANSACTION to delete it. + */ +static OCStackApplicationResult SecurePortDiscoveryHandler(void *ctx, OCDoHandle UNUSED, + OCClientResponse *clientResponse); + +/** + * Callback handler for security version discovery. + * + * @param[in] ctx User context + * @param[in] handle Handler for response + * @param[in] clientResponse Response information (It will contain payload) + * @return OC_STACK_KEEP_TRANSACTION to keep transaction and + * OC_STACK_DELETE_TRANSACTION to delete it. + */ +static OCStackApplicationResult SecVersionDiscoveryHandler(void *ctx, OCDoHandle UNUSED, + OCClientResponse *clientResponse); + /** * Function to search node in linked list that matches given IP and port. * @@ -119,6 +179,7 @@ OCStackResult AddDevice(OCProvisionDev_t **ppDevicesList, const char* addr, cons ptr->next = NULL; ptr->connType = connType; ptr->devStatus = DEV_STATUS_ON; //AddDevice is called when discovery(=alive) + OICStrcpy(ptr->secVer, strlen("0.0.0"), "0.0.0"); // version initialization LL_PREPEND(*ppDevicesList, ptr); } @@ -153,6 +214,37 @@ OCStackResult UpdateSecurePortOfDevice(OCProvisionDev_t **ppDevicesList, const c } /** + * Function to set security version information from the given list of devices. + * + * @param[in] pList List of OCProvisionDev_t. + * @param[in] addr address of target device. + * @param[in] port port of remote server. + * @param[in] secVer security version information. + * + * @return OC_STACK_OK for success and errorcode otherwise. + */ +OCStackResult UpdateSecVersionOfDevice(OCProvisionDev_t **ppDevicesList, const char *addr, + uint16_t port, const char* secVer) +{ + if (NULL == secVer) + { + return OC_STACK_INVALID_PARAM; + } + + OCProvisionDev_t *ptr = GetDevice(ppDevicesList, addr, port); + + if(!ptr) + { + OIC_LOG(ERROR, TAG, "Can not find device information in the discovery device list"); + return OC_STACK_ERROR; + } + + OICStrcpy(ptr->secVer, strlen(secVer), secVer); + + return OC_STACK_OK; +} + +/** * This function deletes list of provision target devices * * @param[in] pDevicesList List of OCProvisionDev_t. @@ -210,6 +302,15 @@ OCProvisionDev_t* PMCloneOCProvisionDev(const OCProvisionDev_t* src) newDev->doxm->oxm = NULL; } + if (0 == strlen(src->secVer)) + { + OICStrcpy(newDev->secVer, strlen("0.0.0"), "0.0.0"); + } + else + { + OICStrcpy(newDev->secVer, strlen(src->secVer), src->secVer); + } + newDev->securePort = src->securePort; newDev->devStatus = src->devStatus; newDev->connType = src->connType; @@ -384,16 +485,80 @@ bool PMGenerateQuery(bool isSecure, return true; } -/** - * Callback handler for getting secure port information using /oic/res discovery. - * - * @param[in] ctx user context - * @param[in] handle Handle for response - * @param[in] clientResponse Response information(It will contain payload) - * - * @return OC_STACK_KEEP_TRANSACTION to keep transaction and - * OC_STACK_DELETE_TRANSACTION to delete it. - */ +static OCStackApplicationResult SecurityVersionDiscoveryHandler(void *ctx, OCDoHandle UNUSED, + OCClientResponse *clientResponse) +{ + if (ctx == NULL) + { + OIC_LOG(ERROR, TAG, "Lost List of device information"); + return OC_STACK_KEEP_TRANSACTION; + } + (void)UNUSED; + if (clientResponse) + { + if (NULL == clientResponse->payload) + { + OIC_LOG(INFO, TAG, "Skiping Null payload"); + return OC_STACK_KEEP_TRANSACTION; + } + if (OC_STACK_OK != clientResponse->result) + { + OIC_LOG(INFO, TAG, "Error in response"); + return OC_STACK_KEEP_TRANSACTION; + } + else + { + if (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type) + { + OIC_LOG(INFO, TAG, "Unknown payload type"); + return OC_STACK_KEEP_TRANSACTION; + } + + OicSecVer_t *ptrVer = NULL; + uint8_t *payload = ((OCSecurityPayload*)clientResponse->payload)->securityData1; + size_t size = ((OCSecurityPayload*)clientResponse->payload)->payloadSize; + OCStackResult res = CBORPayloadToVer(payload, size, &ptrVer); + if ((NULL == ptrVer) && (OC_STACK_OK != res)) + { + OIC_LOG(INFO, TAG, "Ignoring malformed CBOR"); + return OC_STACK_KEEP_TRANSACTION; + } + else + { + OIC_LOG(DEBUG, TAG, "Successfully converted ver cbor to bin."); + + //If this is owend device discovery we have to filter out the responses. + DiscoveryInfo* pDInfo = (DiscoveryInfo*)ctx; + res = UpdateSecVersionOfDevice(pDInfo->ppDevicesList, clientResponse->devAddr.addr, + clientResponse->devAddr.port, ptrVer->secv); + if (OC_STACK_OK != res) + { + OIC_LOG(ERROR, TAG, "Error while getting security version."); + DeleteVerBinData(ptrVer); + return OC_STACK_KEEP_TRANSACTION; + } + + OIC_LOG(INFO, TAG, "= Discovered security version ="); + OIC_LOG_V(DEBUG, TAG, "IP %s", clientResponse->devAddr.addr); + OIC_LOG_V(DEBUG, TAG, "PORT %d", clientResponse->devAddr.port); + OIC_LOG_V(DEBUG, TAG, "VERSION %s", ptrVer->secv); + + OIC_LOG(INFO, TAG, "Exiting SecVersionDiscoveryHandler."); + DeleteVerBinData(ptrVer); + } + + return OC_STACK_KEEP_TRANSACTION; + } + } + else + { + OIC_LOG(INFO, TAG, "Skiping Null response"); + return OC_STACK_KEEP_TRANSACTION; + } + + return OC_STACK_DELETE_TRANSACTION; +} + static OCStackApplicationResult SecurePortDiscoveryHandler(void *ctx, OCDoHandle UNUSED, OCClientResponse *clientResponse) { @@ -431,15 +596,22 @@ static OCStackApplicationResult SecurePortDiscoveryHandler(void *ctx, OCDoHandle } DiscoveryInfo* pDInfo = (DiscoveryInfo*)ctx; - OCProvisionDev_t **ppDevicesList = pDInfo->ppDevicesList; - - OCStackResult res = UpdateSecurePortOfDevice(ppDevicesList, clientResponse->devAddr.addr, + OCStackResult res = UpdateSecurePortOfDevice(pDInfo->ppDevicesList, + clientResponse->devAddr.addr, clientResponse->devAddr.port, securePort); if (OC_STACK_OK != res) { OIC_LOG(ERROR, TAG, "Error while getting secure port."); return OC_STACK_DELETE_TRANSACTION; } + + res = SecurityVersionDiscovery(pDInfo, clientResponse); + if(OC_STACK_OK != res) + { + OIC_LOG(ERROR, TAG, "Failed to SecurityVersionDiscovery"); + return OC_STACK_DELETE_TRANSACTION; + } + OIC_LOG(INFO, TAG, "Exiting SecurePortDiscoveryHandler."); } @@ -449,18 +621,10 @@ static OCStackApplicationResult SecurePortDiscoveryHandler(void *ctx, OCDoHandle { OIC_LOG(INFO, TAG, "Skiping Null response"); } + return OC_STACK_DELETE_TRANSACTION; } -/** - * Callback handler for PMDeviceDiscovery API. - * - * @param[in] ctx User context - * @param[in] handle Handler for response - * @param[in] clientResponse Response information (It will contain payload) - * @return OC_STACK_KEEP_TRANSACTION to keep transaction and - * OC_STACK_DELETE_TRANSACTION to delete it. - */ static OCStackApplicationResult DeviceDiscoveryHandler(void *ctx, OCDoHandle UNUSED, OCClientResponse *clientResponse) { @@ -537,42 +701,15 @@ static OCStackApplicationResult DeviceDiscoveryHandler(void *ctx, OCDoHandle UNU DeleteDoxmBinData(ptrDoxm); return OC_STACK_KEEP_TRANSACTION; } - char rsrc_uri[MAX_URI_LENGTH+1] = {0}; - int wr_len = snprintf(rsrc_uri, sizeof(rsrc_uri), "%s?%s=%s", - OC_RSRVD_WELL_KNOWN_URI, OC_RSRVD_RESOURCE_TYPE, OIC_RSRC_TYPE_SEC_DOXM); - if(wr_len <= 0 || (size_t)wr_len >= sizeof(rsrc_uri)) - { - OIC_LOG(ERROR, TAG, "rsrc_uri_string_print failed"); - return OC_STACK_ERROR; - } - //Try to the unicast discovery to getting secure port - char query[MAX_URI_LENGTH+MAX_QUERY_LENGTH+1] = {0}; - if(!PMGenerateQuery(false, - clientResponse->devAddr.addr, clientResponse->devAddr.port, - clientResponse->connType, - query, sizeof(query), rsrc_uri)) - { - OIC_LOG(ERROR, TAG, "DeviceDiscoveryHandler : Failed to generate query"); - return OC_STACK_KEEP_TRANSACTION; - } - OIC_LOG_V(DEBUG, TAG, "Query=%s", query); - - OCCallbackData cbData; - cbData.cb = &SecurePortDiscoveryHandler; - cbData.context = ctx; - cbData.cd = NULL; - OCStackResult ret = OCDoResource(NULL, OC_REST_DISCOVER, query, 0, 0, - clientResponse->connType, OC_LOW_QOS, &cbData, NULL, 0); - // TODO: Should we use the default secure port in case of error? - if(OC_STACK_OK != ret) + + res = SecurePortDiscovery(pDInfo, clientResponse); + if(OC_STACK_OK != res) { - OIC_LOG(ERROR, TAG, "Failed to Secure Port Discovery"); + OIC_LOG(ERROR, TAG, "Failed to SecurePortDiscovery"); + DeleteDoxmBinData(ptrDoxm); return OC_STACK_KEEP_TRANSACTION; } - else - { - OIC_LOG_V(INFO, TAG, "OCDoResource with [%s] Success", query); - } + OIC_LOG(INFO, TAG, "Exiting ProvisionDiscoveryHandler."); } @@ -664,6 +801,100 @@ OCStackResult PMDeviceDiscovery(unsigned short waittime, bool isOwned, OCProvisi return res; } +static OCStackResult SecurePortDiscovery(DiscoveryInfo* discoveryInfo, + const OCClientResponse *clientResponse) +{ + OIC_LOG(DEBUG, TAG, "IN SecurePortDiscovery"); + + if(NULL == discoveryInfo || NULL == clientResponse) + { + return OC_STACK_INVALID_PARAM; + } + + char rsrc_uri[MAX_URI_LENGTH+1] = {0}; + int wr_len = snprintf(rsrc_uri, sizeof(rsrc_uri), "%s?%s=%s", + OC_RSRVD_WELL_KNOWN_URI, OC_RSRVD_RESOURCE_TYPE, OIC_RSRC_TYPE_SEC_DOXM); + if(wr_len <= 0 || (size_t)wr_len >= sizeof(rsrc_uri)) + { + OIC_LOG(ERROR, TAG, "rsrc_uri_string_print failed"); + return OC_STACK_ERROR; + } + //Try to the unicast discovery to getting secure port + char query[MAX_URI_LENGTH+MAX_QUERY_LENGTH+1] = {0}; + if(!PMGenerateQuery(false, + clientResponse->devAddr.addr, clientResponse->devAddr.port, + clientResponse->connType, + query, sizeof(query), rsrc_uri)) + { + OIC_LOG(ERROR, TAG, "SecurePortDiscovery : Failed to generate query"); + return OC_STACK_ERROR; + } + OIC_LOG_V(DEBUG, TAG, "Query=%s", query); + + OCCallbackData cbData; + cbData.cb = &SecurePortDiscoveryHandler; + cbData.context = (void*)discoveryInfo; + cbData.cd = NULL; + OCStackResult ret = OCDoResource(NULL, OC_REST_DISCOVER, query, 0, 0, + clientResponse->connType, OC_LOW_QOS, &cbData, NULL, 0); + if(OC_STACK_OK != ret) + { + OIC_LOG(ERROR, TAG, "Failed to Secure Port Discovery"); + return ret; + } + else + { + OIC_LOG_V(INFO, TAG, "OCDoResource with [%s] Success", query); + } + + OIC_LOG(DEBUG, TAG, "OUT SecurePortDiscovery"); + + return ret; +} + +static OCStackResult SecurityVersionDiscovery(DiscoveryInfo* discoveryInfo, + const OCClientResponse *clientResponse) +{ + OIC_LOG(DEBUG, TAG, "IN SecurityVersionDiscovery"); + + if(NULL == discoveryInfo || NULL == clientResponse) + { + return OC_STACK_INVALID_PARAM; + } + + //Try to the unicast discovery to getting security version + char query[MAX_URI_LENGTH+MAX_QUERY_LENGTH+1] = {0}; + if(!PMGenerateQuery(false, + clientResponse->devAddr.addr, clientResponse->devAddr.port, + clientResponse->connType, + query, sizeof(query), OIC_RSRC_VER_URI)) + { + OIC_LOG(ERROR, TAG, "SecurityVersionDiscovery : Failed to generate query"); + return OC_STACK_ERROR; + } + OIC_LOG_V(DEBUG, TAG, "Query=%s", query); + + OCCallbackData cbData; + cbData.cb = &SecurityVersionDiscoveryHandler; + cbData.context = (void*)discoveryInfo; + cbData.cd = NULL; + OCStackResult ret = OCDoResource(NULL, OC_REST_DISCOVER, query, 0, 0, + clientResponse->connType, OC_LOW_QOS, &cbData, NULL, 0); + if(OC_STACK_OK != ret) + { + OIC_LOG(ERROR, TAG, "Failed to Security Version Discovery"); + return ret; + } + else + { + OIC_LOG_V(INFO, TAG, "OCDoResource with [%s] Success", query); + } + + OIC_LOG(DEBUG, TAG, "OUT SecurityVersionDiscovery"); + + return ret; +} + /** * Function to print OCProvisionDev_t for debug purpose. * diff --git a/resource/csdk/security/src/resourcemanager.c b/resource/csdk/security/src/resourcemanager.c index 90a4583..14f586d 100644 --- a/resource/csdk/security/src/resourcemanager.c +++ b/resource/csdk/security/src/resourcemanager.c @@ -36,6 +36,7 @@ #include "pconfresource.h" #include "dpairingresource.h" //#endif // DIRECT_PAIRING +#include "verresource.h" #define TAG "SRM-RM" @@ -137,6 +138,10 @@ OCStackResult InitSecureResources( ) ret = InitDpairingResource(); } //#endif // DIRECT_PAIRING + if(OC_STACK_OK == ret) + { + ret = InitVerResource(); + } if(OC_STACK_OK != ret) { //TODO: Update the default behavior if one of the SVR fails @@ -160,6 +165,7 @@ OCStackResult DestroySecureResources( ) DeInitPconfResource(); DeInitDpairingResource(); //#endif // DIRECT_PAIRING + DeInitVerResource(); return OC_STACK_OK; } diff --git a/resource/csdk/security/src/secureresourcemanager.c b/resource/csdk/security/src/secureresourcemanager.c index 6e2feb2..26a9277 100644 --- a/resource/csdk/security/src/secureresourcemanager.c +++ b/resource/csdk/security/src/secureresourcemanager.c @@ -362,6 +362,7 @@ bool SRMIsSecurityResourceURI(const char* uri) OIC_RSRC_PSTAT_URI, OIC_RSRC_PCONF_URI, OIC_RSRC_DPAIRING_URI, + OIC_RSRC_VER_URI, }; // Remove query from Uri for resource string comparison diff --git a/resource/csdk/security/src/srmresourcestrings.c b/resource/csdk/security/src/srmresourcestrings.c index 611f6bb..e8b8165 100644 --- a/resource/csdk/security/src/srmresourcestrings.c +++ b/resource/csdk/security/src/srmresourcestrings.c @@ -78,6 +78,10 @@ const char * OIC_RSRC_TYPE_SEC_DPAIRING = "oic.sec.dpairing"; const char * OIC_RSRC_DPAIRING_URI = "/oic/sec/dpairing"; const char * OIC_JSON_DPAIRING_NAME = "dpairing"; +//version +const char * OIC_RSRC_TYPE_SEC_VER = "oic.sec.ver"; +const char * OIC_RSRC_VER_URI = "/oic/sec/ver"; +const char * OIC_JSON_VER_NAME = "ver"; const char * OIC_JSON_SUBJECT_NAME = "subject"; const char * OIC_JSON_RESOURCES_NAME = "resources"; @@ -133,6 +137,7 @@ const char * OIC_JSON_IF_NAME = "if"; const char * OIC_JSON_ROWNERID_NAME = "rowneruuid"; const char * OIC_JSON_ENCODING_NAME = "encoding"; const char * OIC_JSON_DATA_NAME = "data"; +const char * OIC_JSON_SEC_V_NAME = "secv"; const char * OIC_JSON_EMPTY_STRING = ""; diff --git a/resource/csdk/security/src/verresource.c b/resource/csdk/security/src/verresource.c new file mode 100644 index 0000000..4f0b2d8 --- /dev/null +++ b/resource/csdk/security/src/verresource.c @@ -0,0 +1,354 @@ +/* ***************************************************************** + * + * Copyright 2016 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * *****************************************************************/ + +#include +#include + +#if HAVE_STRINGS_H +#include +#endif + +#include "ocstack.h" +#include "oic_malloc.h" +#include "oic_string.h" +#include "logger.h" +#include "payload_logging.h" +#include "ocpayload.h" +#include "cainterface.h" +#include "ocserverrequest.h" +#include "resourcemanager.h" +#include "verresource.h" +#include "doxmresource.h" +#include "psinterface.h" +#include "srmresourcestrings.h" +#include "securevirtualresourcetypes.h" +#include "srmutility.h" + +#define TAG "SEC-VER" + +/** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory. + * The value of payload size is increased until reaching belox max cbor size. */ +static const uint8_t CBOR_SIZE = 255; + +/** Max cbor size payload. */ +static const uint16_t CBOR_MAX_SIZE = 4400; + +/** VER Map size - Number of mandatory items. */ +static const uint8_t VER_MAP_SIZE = 2; + +static OCResourceHandle gVerHandle = NULL; + +/** Security version is mapped with iotivity release version */ +const char* SECURITY_VERSION = IOTIVITY_VERSION; + +static OicSecVer_t gVer = +{ + {0}, /* char *secv */ + {.id = {0}}, /* OicUuid_t deviceID */ +}; + +void DeleteVerBinData(OicSecVer_t* ver) +{ + if (ver) + { + //Clean ver itself + OICFree(ver); + } +} + +OCStackResult VerToCBORPayload(const OicSecVer_t *ver, uint8_t **payload, size_t *size) +{ + if (NULL == ver || NULL == payload || NULL != *payload || NULL == size) + { + return OC_STACK_INVALID_PARAM; + } + size_t cborLen = *size; + if (0 == cborLen) + { + cborLen = CBOR_SIZE; + } + *payload = NULL; + *size = 0; + + OCStackResult ret = OC_STACK_ERROR; + + CborEncoder encoder = { {.ptr = NULL }, .end = 0 }; + CborEncoder verMap = { {.ptr = NULL }, .end = 0 }; + + int64_t cborEncoderResult = CborNoError; + uint8_t mapSize = VER_MAP_SIZE; + char* strUuid = NULL; + + uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen); + VERIFY_NON_NULL(TAG, outPayload, ERROR); + cbor_encoder_init(&encoder, outPayload, cborLen, 0); + + cborEncoderResult |= cbor_encoder_create_map(&encoder, &verMap, mapSize); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Ver Map."); + + //SecV -- Mandatory + cborEncoderResult |= cbor_encode_text_string(&verMap, OIC_JSON_SEC_V_NAME, + strlen(OIC_JSON_SEC_V_NAME)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SecV Tag."); + cborEncoderResult |= cbor_encode_text_string(&verMap, ver->secv, strlen(ver->secv)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SecV Value."); + + //DeviceId -- Mandatory + cborEncoderResult = cbor_encode_text_string(&verMap, OIC_JSON_DEVICE_ID_NAME, + strlen(OIC_JSON_DEVICE_ID_NAME)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Id Tag."); + ret = ConvertUuidToStr(&ver->deviceID, &strUuid); + VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR); + cborEncoderResult = cbor_encode_text_string(&verMap, strUuid, strlen(strUuid)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Id Value."); + OICFree(strUuid); + strUuid = NULL; + + + // Close ver(first) container + cborEncoderResult |= cbor_encoder_close_container(&encoder, &verMap); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing VerMap."); + + if (CborNoError == cborEncoderResult) + { + *size = encoder.ptr - outPayload; + *payload = outPayload; + ret = OC_STACK_OK; + } +exit: + if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE)) + { + OIC_LOG(DEBUG, TAG, "Memory getting reallocated."); + // reallocate and try again! + OICFree(outPayload); + // Since the allocated initial memory failed, double the memory. + cborLen += encoder.ptr - encoder.end; + OIC_LOG_V(DEBUG, TAG, "Ver reallocation size : %zd.", cborLen); + cborEncoderResult = CborNoError; + ret = VerToCBORPayload(ver, payload, &cborLen); + *size = cborLen; + } + + if ((CborNoError != cborEncoderResult) || (OC_STACK_OK != ret)) + { + OICFree(outPayload); + outPayload = NULL; + *payload = NULL; + *size = 0; + ret = OC_STACK_ERROR; + } + + return ret; +} + +OCStackResult CBORPayloadToVer(const uint8_t *cborPayload, size_t size, + OicSecVer_t **secVer) +{ + if (NULL == cborPayload || NULL == secVer || NULL != *secVer) + { + return OC_STACK_INVALID_PARAM; + } + + OCStackResult ret = OC_STACK_ERROR; + *secVer = NULL; + char *strUuid = NULL; + + CborParser parser = { .end = NULL}; + CborError cborFindResult = CborNoError; + int cborLen = (size == 0) ? CBOR_SIZE : size; + size_t len = 0; + CborValue verCbor = { .parser = NULL }; + cbor_parser_init(cborPayload, cborLen, 0, &parser, &verCbor); + CborValue verMap = { .parser = NULL }; + OicSecVer_t *ver = (OicSecVer_t *)OICCalloc(1, sizeof(OicSecVer_t)); + VERIFY_NON_NULL(TAG, ver, ERROR); + + + cborFindResult = cbor_value_map_find_value(&verCbor, OIC_JSON_SEC_V_NAME, &verMap); + if (CborNoError == cborFindResult && cbor_value_is_text_string(&verMap)) + { + char *version = NULL; + cborFindResult = cbor_value_dup_text_string(&verMap, &version, &len, NULL); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Security Version Value."); + memcpy(ver->secv, version, len); + OICFree(version); + } + + cborFindResult = cbor_value_map_find_value(&verCbor, OIC_JSON_DEVICE_ID_NAME, &verMap); + if (CborNoError == cborFindResult && cbor_value_is_text_string(&verMap)) + { + cborFindResult = cbor_value_dup_text_string(&verMap, &strUuid , &len, NULL); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Device Id Value."); + ret = ConvertStrToUuid(strUuid , &ver->deviceID); + VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR); + OICFree(strUuid ); + strUuid = NULL; + } + + *secVer = ver; + ret = OC_STACK_OK; + +exit: + if (CborNoError != cborFindResult) + { + OIC_LOG (ERROR, TAG, "CBORPayloadToVer failed!!!"); + DeleteVerBinData(ver); + ret = OC_STACK_ERROR; + } + return ret; +} + +static OCEntityHandlerResult HandleVerGetRequest (const OCEntityHandlerRequest * ehRequest) +{ + OCEntityHandlerResult ehRet = OC_EH_OK; + + OIC_LOG(DEBUG, TAG, "Ver EntityHandle processing GET request"); + + /* + * For GET request return ver resource CBOR payload. + * For non-valid query return NULL json payload. + * The version is static built-in information, so VerToCBORPayload will + * return valid ver resource json. + */ + uint8_t *payload = NULL; + size_t size = 0; + if (OC_STACK_OK != VerToCBORPayload(&gVer, &payload, &size)) + { + payload = NULL; + } + + // Send response payload to request originator + if (OC_STACK_OK != SendSRMCBORResponse(ehRequest, ehRet, payload, size)) + { + OIC_LOG(ERROR, TAG, "SendSRMCBORResponse failed in HandleVerGetRequest"); + } + + OICFree(payload); + + return ehRet; +} + +OCEntityHandlerResult VerEntityHandler(OCEntityHandlerFlag flag, + OCEntityHandlerRequest * ehRequest, + void* callbackParam) +{ + (void)callbackParam; + OCEntityHandlerResult ehRet = OC_EH_ERROR; + + if(NULL == ehRequest) + { + return ehRet; + } + + if (flag & OC_REQUEST_FLAG) + { + OIC_LOG(DEBUG, TAG, "Flag includes OC_REQUEST_FLAG"); + + switch (ehRequest->method) + { + case OC_REST_GET: + ehRet = HandleVerGetRequest(ehRequest); + break; + + default: + ehRet = OC_EH_ERROR; + SendSRMCBORResponse(ehRequest, ehRet, NULL, 0); + break; + } + } + + return ehRet; +} + +OCStackResult CreateVerResource() +{ + OCStackResult ret = OCCreateResource(&gVerHandle, + OIC_RSRC_TYPE_SEC_VER, + OIC_MI_DEF, + OIC_RSRC_VER_URI, + VerEntityHandler, + NULL, + OC_SECURE); + + if (OC_STACK_OK != ret) + { + OIC_LOG (FATAL, TAG, "Unable to instantiate Ver resource"); + DeInitVerResource(); + } + return ret; +} + +/** + * Get the security version. + * + * @return the version string of security. + */ +const char* GetSecVersion() +{ + OIC_LOG(DEBUG, TAG, "GetSecVersion"); + return gVer.secv; +} + +const OicSecVer_t* GetVerResourceData() +{ + return &gVer; +} + +OCStackResult InitVerResource() +{ + OCStackResult ret = OC_STACK_ERROR; + + OICStrcpy(gVer.secv, strlen(SECURITY_VERSION)+1, SECURITY_VERSION); + + //Read device id from doxm + OicUuid_t deviceID = {.id={0}}; + ret = GetDoxmDeviceID(&deviceID); + if (OC_STACK_OK != ret) + { + OIC_LOG(ERROR, TAG, "Error while retrieving doxm device ID"); + return ret; + } + memcpy(&gVer.deviceID, &deviceID, sizeof(OicUuid_t)); + + //Instantiate 'oic.sec.ver' + ret = CreateVerResource(); + if (OC_STACK_OK != ret) + { + OIC_LOG(ERROR, TAG, "Error while creating VER resource"); + } + + return ret; +} + +OCStackResult DeInitVerResource() +{ + OCStackResult ret = OCDeleteResource(gVerHandle); + + memset(&gVer, 0, sizeof(gVer)); + + if (OC_STACK_OK == ret) + { + return OC_STACK_OK; + } + else + { + return OC_STACK_ERROR; + } +} diff --git a/resource/include/OCProvisioningManager.h b/resource/include/OCProvisioningManager.h old mode 100755 new mode 100644 index aecee19..0a949e3 --- a/resource/include/OCProvisioningManager.h +++ b/resource/include/OCProvisioningManager.h @@ -124,7 +124,7 @@ namespace OC * all the device in subnet which are not yet owned. * * @param timeout Timeout in seconds, time until which function will listen to - * responses from client before returning the list of devices. + * responses from server before returning the list of devices. * @param list List of candidate devices to be provisioned. * @return ::OC_STACK_OK in case of success and other value otherwise. */ @@ -136,7 +136,7 @@ namespace OC * all the device in subnet which are already owned by calling provisioning client. * * @param timeout Timeout in seconds, time until which function will listen to - * responses from client before returning the list of devices. + * responses from server before returning the list of devices. * @param list List of owned devices. * @return ::OC_STACK_OK in case of success and other value otherwise. */