Commit 273312fa authored by js126.lee's avatar js126.lee Committed by Randeep

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: default avatarJongsung Lee <js126.lee@samsung.com>
Signed-off-by: default avatarChul Lee <chuls.lee@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/6105Reviewed-by: default avatarYonggoo Kang <ygace.kang@samsung.com>
Tested-by: default avatarjenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Randeep's avatarRandeep Singh <randeep.s@samsung.com>
parent d86a86eb
......@@ -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',
......
......@@ -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;
......
/* *****************************************************************
*
* 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
......@@ -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
{
// <Attribute ID>:<Read/Write>:<Multiple/Single>:<Mandatory?>:<Type>
char secv[MAX_VERSION_LEN]; // 0:R:S:Y:String
OicUuid_t deviceID; // 1:R:S:Y:oic.uuid
};
#ifdef __cplusplus
}
#endif
......
......@@ -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.
*/
......
......@@ -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;
......
{
"acl": {
"acl": {
"aclist": {
"aces": [
{
......@@ -79,6 +79,18 @@
}
],
"permission": 6
},
{
"subjectuuid": "*",
"resources": [
{
"href": "/oic/sec/ver",
"rel": "",
"rt": "",
"if": ""
}
],
"permission": 2
}
]
},
......
{
"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
}
......@@ -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.
*/
......
......@@ -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);
}
......@@ -152,6 +213,37 @@ OCStackResult UpdateSecurePortOfDevice(OCProvisionDev_t **ppDevicesList, const c
return OC_STACK_OK;
}
/**
* 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
*
......@@ -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);