Commit 86e07ef0 authored by Sachin Agrawal's avatar Sachin Agrawal

Implemented oic.sec.svc resource in SRM

Updated SRM source code to add support for SVC resource.
Also, added unit test to exercise JSON-Bin marshalling code.

Change-Id: I8d56e33252d51e4e430b355e58c6b2592cb06ee6
Signed-off-by: default avatarSachin Agrawal <sachin.agrawal@intel.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/1386Tested-by: default avatarjenkins-iotivity <jenkins-iotivity@opendaylight.org>
parent 2eb24011
......@@ -89,6 +89,7 @@ libocsrm_src = [
OCSRM_SRC + 'pstatresource.c',
OCSRM_SRC + 'doxmresource.c',
OCSRM_SRC + 'credresource.c',
OCSRM_SRC + 'svcresource.c',
OCSRM_SRC + 'policyengine.c',
OCSRM_SRC + 'psinterface.c',
OCSRM_SRC + 'srmresourcestrings.c',
......
File mode changed from 100755 to 100644
......@@ -58,6 +58,11 @@ extern const char * OIC_RSRC_TYPE_SEC_CRED;
extern const char * OIC_RSRC_CRED_URI;
extern const char * OIC_JSON_CRED_NAME;
//SVC
extern const char * OIC_RSRC_TYPE_SEC_SVC;
extern const char * OIC_RSRC_SVC_URI;
extern const char * OIC_JSON_SVC_NAME;
extern const char * OIC_JSON_SUBJECT_NAME;
extern const char * OIC_JSON_RESOURCES_NAME;
extern const char * OIC_JSON_AMSS_NAME;
......@@ -82,6 +87,8 @@ extern const char * OIC_JSON_CM_NAME;
extern const char * OIC_JSON_TM_NAME;
extern const char * OIC_JSON_OM_NAME;
extern const char * OIC_JSON_SM_NAME;
extern const char * OIC_JSON_SERVICE_DEVICE_ID;
extern const char * OIC_JSON_SERVICE_TYPE;
extern OicUuid_t WILDCARD_SUBJECT_ID;
extern size_t WILDCARD_SUBJECT_ID_LEN;
......
//******************************************************************
//
// Copyright 2015 Intel Mobile Communications GmbH 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_SVCR_H
#define IOTVT_SRM_SVCR_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* Initialize SVC resource by loading data from persistent storage.
*
* @retval OC_STACK_OK for Success, otherwise some error value
*/
OCStackResult InitSVCResource();
/**
* Perform cleanup for SVC resources.
*
* @retval none
*/
void DeInitSVCResource();
/**
* This function converts SVC data into JSON format.
* Caller needs to invoke 'free' when done using
* returned string.
* @param svc instance of OicSecSvc_t structure.
*
* @retval pointer to SVC in json format.
*/
char* BinToSvcJSON(const OicSecSvc_t * svc);
#ifdef __cplusplus
}
#endif
#endif //IOTVT_SRM_SVCR_H
......@@ -208,6 +208,13 @@ typedef enum OicSecDpom
SINGLE_SERVICE_CLIENT_DRIVEN = 0x3,
} OicSecDpom_t;
typedef enum OicSecSvcType
{
SERVICE_UNKNOWN = 0x0,
ACCESS_MGMT_SERVICE = 0x1, //urn:oic.sec.ams
} OicSecSvcType_t;
//TODO: Need more clarification on deviceIDFormat field type.
#if 0
typedef enum
......@@ -409,7 +416,11 @@ struct OicSecSacl
struct OicSecSvc
{
// <Attribute ID>:<Read/Write>:<Multiple/Single>:<Mandatory?>:<Type>
//TODO fill in from OIC Security Spec
OicUuid_t svcdid; //0:R:S:Y:oic.uuid
OicSecSvcType_t svct; //1:R:M:Y:OIC Service Type
size_t ownersLen; //2:the number of elts in Owners
OicUuid_t *owners; //3:R:M:Y:oic.uuid
OicSecSvc_t *next;
};
#ifdef __cplusplus
......
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
......@@ -24,6 +24,7 @@
#include "pstatresource.h"
#include "doxmresource.h"
#include "credresource.h"
#include "svcresource.h"
#include "amaclresource.h"
#include "oic_malloc.h"
#include "logger.h"
......@@ -90,6 +91,10 @@ OCStackResult InitSecureResources( )
}
if(OC_STACK_OK == ret)
{
ret = InitSVCResource();
}
if(OC_STACK_OK == ret)
{
ret = InitAmaclResource();
}
if(OC_STACK_OK != ret)
......
......@@ -55,6 +55,12 @@ const char * OIC_RSRC_TYPE_SEC_CRED = "oic.sec.cred";
const char * OIC_RSRC_CRED_URI = "/oic/sec/cred";
const char * OIC_JSON_CRED_NAME = "cred";
//svc
const char * OIC_RSRC_TYPE_SEC_SVC = "oic.sec.svc";
const char * OIC_RSRC_SVC_URI = "/oic/sec/svc";
const char * OIC_JSON_SVC_NAME = "svc";
const char * OIC_JSON_SUBJECT_NAME = "sub";
const char * OIC_JSON_RESOURCES_NAME = "rsrc";
const char * OIC_JSON_AMSS_NAME = "amss";
......@@ -80,6 +86,8 @@ const char * OIC_JSON_CREDTYPE_NAME = "credtyp";
const char * OIC_JSON_PUBLICDATA_NAME = "pbdata";
const char * OIC_JSON_PRIVATEDATA_NAME = "pvdata";
const char * OIC_JSON_PERIOD_NAME = "period";
const char * OIC_JSON_SERVICE_DEVICE_ID = "svcdid";
const char * OIC_JSON_SERVICE_TYPE = "svct";
OicUuid_t WILDCARD_SUBJECT_ID = {"*"};
size_t WILDCARD_SUBJECT_ID_LEN = 1;
......
//******************************************************************
//
// Copyright 2015 Intel Mobile Communications GmbH 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 "ocstack.h"
#include "logger.h"
#include "oic_malloc.h"
#include "cJSON.h"
#include "base64.h"
#include "resourcemanager.h"
#include "psinterface.h"
#include "svcresource.h"
#include "utlist.h"
#include "srmresourcestrings.h"
#include "srmutility.h"
#include <stdlib.h>
#include <string.h>
#define TAG PCF("SRM-SVC")
OicSecSvc_t *gSvc = NULL;
static OCResourceHandle gSvcHandle = NULL;
void DeleteSVCList(OicSecSvc_t* svc)
{
if (svc)
{
OicSecSvc_t *svcTmp1 = NULL, *svcTmp2 = NULL;
LL_FOREACH_SAFE(svc, svcTmp1, svcTmp2)
{
LL_DELETE(svc, svcTmp1);
// Clean Owners
OICFree(svcTmp1->owners);
// Clean SVC node itself
OICFree(svcTmp1);
}
}
}
/*
* This internal method converts SVC data into JSON format.
*
* Note: Caller needs to invoke 'free' when finished done using
* return string.
*/
char * BinToSvcJSON(const OicSecSvc_t * svc)
{
cJSON *jsonRoot = NULL;
char *jsonStr = NULL;
if (svc)
{
jsonRoot = cJSON_CreateObject();
VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
cJSON *jsonSvcArray = NULL;
cJSON_AddItemToObject (jsonRoot, OIC_JSON_SVC_NAME, jsonSvcArray = cJSON_CreateArray());
VERIFY_NON_NULL(TAG, jsonSvcArray, ERROR);
while(svc)
{
char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {};
uint32_t outLen = 0;
B64Result b64Ret = B64_OK;
cJSON *jsonSvc = cJSON_CreateObject();
// Service Device Identity
outLen = 0;
b64Ret = b64Encode(svc->svcdid.id, sizeof(OicUuid_t), base64Buff,
sizeof(base64Buff), &outLen);
VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
cJSON_AddStringToObject(jsonSvc, OIC_JSON_SERVICE_DEVICE_ID, base64Buff );
// Service Type
cJSON_AddNumberToObject (jsonSvc, OIC_JSON_SERVICE_TYPE, svc->svct);
// Owners
cJSON *jsonOwnrArray = NULL;
cJSON_AddItemToObject (jsonSvc, OIC_JSON_OWNERS_NAME, jsonOwnrArray = cJSON_CreateArray());
VERIFY_NON_NULL(TAG, jsonOwnrArray, ERROR);
for (int i = 0; i < svc->ownersLen; i++)
{
outLen = 0;
b64Ret = b64Encode(svc->owners[i].id, sizeof(((OicUuid_t*)0)->id), base64Buff,
sizeof(base64Buff), &outLen);
VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
cJSON_AddItemToArray (jsonOwnrArray, cJSON_CreateString(base64Buff));
}
// Attach current svc node to Svc Array
cJSON_AddItemToArray(jsonSvcArray, jsonSvc);
svc = svc->next;
}
jsonStr = cJSON_PrintUnformatted(jsonRoot);
}
exit:
if (jsonRoot)
{
cJSON_Delete(jsonRoot);
}
return jsonStr;
}
/*
* This internal method converts JSON SVC into binary SVC.
*/
OicSecSvc_t * JSONToSvcBin(const char * jsonStr)
{
OCStackResult ret = OC_STACK_ERROR;
OicSecSvc_t * headSvc = NULL;
OicSecSvc_t * prevSvc = NULL;
cJSON *jsonRoot = NULL;
cJSON *jsonSvcArray = NULL;
VERIFY_NON_NULL(TAG, jsonStr, ERROR);
jsonRoot = cJSON_Parse(jsonStr);
VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
jsonSvcArray = cJSON_GetObjectItem(jsonRoot, OIC_JSON_SVC_NAME);
VERIFY_NON_NULL(TAG, jsonSvcArray, ERROR);
if (cJSON_Array == jsonSvcArray->type)
{
int numSvc = cJSON_GetArraySize(jsonSvcArray);
int idx = 0;
VERIFY_SUCCESS(TAG, numSvc > 0, INFO);
do
{
cJSON *jsonSvc = cJSON_GetArrayItem(jsonSvcArray, idx);
VERIFY_NON_NULL(TAG, jsonSvc, ERROR);
OicSecSvc_t *svc = (OicSecSvc_t*)OICCalloc(1, sizeof(OicSecSvc_t));
VERIFY_NON_NULL(TAG, svc, ERROR);
headSvc = (headSvc) ? headSvc : svc;
if (prevSvc)
{
prevSvc->next = svc;
}
cJSON *jsonObj = NULL;
unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
uint32_t outLen = 0;
B64Result b64Ret = B64_OK;
// Service Device Identity
jsonObj = cJSON_GetObjectItem(jsonSvc, OIC_JSON_SERVICE_DEVICE_ID);
VERIFY_NON_NULL(TAG, jsonObj, ERROR);
VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR);
outLen = 0;
b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring), base64Buff,
sizeof(base64Buff), &outLen);
VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(svc->svcdid.id)), ERROR);
memcpy(svc->svcdid.id, base64Buff, outLen);
// Service Type
jsonObj = cJSON_GetObjectItem(jsonSvc, OIC_JSON_SERVICE_TYPE);
VERIFY_NON_NULL(TAG, jsonObj, ERROR);
VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
svc->svct = (OicSecSvcType_t)jsonObj->valueint;
// Resource Owners
jsonObj = cJSON_GetObjectItem(jsonSvc, OIC_JSON_OWNERS_NAME);
VERIFY_NON_NULL(TAG, jsonObj, ERROR);
VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR);
svc->ownersLen = cJSON_GetArraySize(jsonObj);
VERIFY_SUCCESS(TAG, svc->ownersLen > 0, ERROR);
svc->owners = (OicUuid_t*)OICCalloc(svc->ownersLen, sizeof(OicUuid_t));
VERIFY_NON_NULL(TAG, (svc->owners), ERROR);
int idxx = 0;
do
{
cJSON *jsonOwnr = cJSON_GetArrayItem(jsonObj, idxx);
VERIFY_NON_NULL(TAG, jsonOwnr, ERROR);
VERIFY_SUCCESS(TAG, cJSON_String == jsonOwnr->type, ERROR);
outLen = 0;
b64Ret = b64Decode(jsonOwnr->valuestring, strlen(jsonOwnr->valuestring), base64Buff,
sizeof(base64Buff), &outLen);
VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(svc->owners[idxx].id)),
ERROR);
memcpy(svc->owners[idxx].id, base64Buff, outLen);
} while ( ++idxx < svc->ownersLen);
prevSvc = svc;
} while( ++idx < numSvc);
}
ret = OC_STACK_OK;
exit:
cJSON_Delete(jsonRoot);
if (OC_STACK_OK != ret)
{
DeleteSVCList(headSvc);
headSvc = NULL;
}
return headSvc;
}
static OCEntityHandlerResult HandleSVCGetRequest (const OCEntityHandlerRequest * ehRequest)
{
// Convert SVC data into JSON for transmission
char* jsonStr = BinToSvcJSON(gSvc);
OCEntityHandlerResult ehRet = (jsonStr ? OC_EH_OK : OC_EH_ERROR);
// Send response payload to request originator
SendSRMResponse(ehRequest, ehRet, jsonStr);
OICFree(jsonStr);
OC_LOG_V (INFO, TAG, PCF("%s RetVal %d"), __func__ , ehRet);
return ehRet;
}
static OCEntityHandlerResult HandleSVCPostRequest (const OCEntityHandlerRequest * ehRequest)
{
OCEntityHandlerResult ehRet = OC_EH_ERROR;
// Convert JSON SVC data into binary. This will also validate the SVC data received.
OicSecSvc_t* newSvc = JSONToSvcBin((char *)(ehRequest->reqJSONPayload));
if (newSvc)
{
// Append the new SVC to existing SVC
LL_APPEND(gSvc, newSvc);
// Convert SVC data into JSON for update to persistent storage
char *jsonStr = BinToSvcJSON(gSvc);
if (jsonStr)
{
cJSON *jsonSvc = cJSON_Parse(jsonStr);
OICFree(jsonStr);
if ((jsonSvc) &&
(OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_SVC_NAME, jsonSvc)))
{
ehRet = OC_EH_RESOURCE_CREATED;
}
cJSON_Delete(jsonSvc);
}
}
// Send payload to request originator
SendSRMResponse(ehRequest, ehRet, NULL);
OC_LOG_V (INFO, TAG, PCF("%s RetVal %d"), __func__ , ehRet);
return ehRet;
}
/*
* This internal method is the entity handler for SVC resources and
* will handle REST request (GET/PUT/POST/DEL) for them.
*/
OCEntityHandlerResult SVCEntityHandler (OCEntityHandlerFlag flag,
OCEntityHandlerRequest * ehRequest,
void* callbackParameter)
{
OCEntityHandlerResult ehRet = OC_EH_ERROR;
if (!ehRequest)
{
return ehRet;
}
if (flag & OC_REQUEST_FLAG)
{
switch (ehRequest->method)
{
case OC_REST_GET:
ehRet = HandleSVCGetRequest(ehRequest);
break;
case OC_REST_POST:
ehRet = HandleSVCPostRequest(ehRequest);
break;
default:
ehRet = OC_EH_ERROR;
SendSRMResponse(ehRequest, ehRet, NULL);
}
}
return ehRet;
}
/*
* This internal method is used to create '/oic/sec/svc' resource.
*/
OCStackResult CreateSVCResource()
{
OCStackResult ret;
ret = OCCreateResource(&gSvcHandle,
OIC_RSRC_TYPE_SEC_SVC,
OIC_MI_DEF,
OIC_RSRC_SVC_URI,
SVCEntityHandler,
NULL,
OC_OBSERVABLE);
if (OC_STACK_OK != ret)
{
OC_LOG (FATAL, TAG, PCF("Unable to instantiate SVC resource"));
DeInitSVCResource();
}
return ret;
}
OCStackResult InitSVCResource()
{
OCStackResult ret = OC_STACK_ERROR;
OC_LOG_V (INFO, TAG, PCF("Begin %s "), __func__ );
// Read SVC resource from PS
char* jsonSVRDatabase = GetSVRDatabase();
if (jsonSVRDatabase)
{
// Convert JSON SVC into binary format
gSvc = JSONToSvcBin(jsonSVRDatabase);
OICFree(jsonSVRDatabase);
}
// Instantiate 'oic.sec.svc'
ret = CreateSVCResource();
if (OC_STACK_OK != ret)
{
DeInitSVCResource();
}
OC_LOG_V (INFO, TAG, PCF("%s RetVal %d"), __func__ , ret);
return ret;
}
/**
* Perform cleanup for SVC resources.
*
* @retval none
*/
void DeInitSVCResource()
{
OCDeleteResource(gSvcHandle);
gSvcHandle = NULL;
DeleteSVCList(gSvc);
gSvc = NULL;
}
......@@ -75,7 +75,9 @@ unittest = srmtest_env.Program('unittest', ['aclresourcetest.cpp',
'securityresourcemanager.cpp',
'credentialresource.cpp',
'srmutility.cpp',
'base64tests.cpp'])
'base64tests.cpp',
'svcresourcetest.cpp',
'srmtestcommon.cpp'])
Alias("test", [unittest])
......
......@@ -31,6 +31,7 @@
#include "securevirtualresourcetypes.h"
#include "srmresourcestrings.h"
#include "aclresource.h"
#include "srmtestcommon.h"
using namespace std;
......@@ -39,7 +40,6 @@ extern "C" {
#endif
extern char * BinToAclJSON(const OicSecAcl_t * acl);
extern OicSecAcl_t * JSONToAclBin(const char * jsonStr);
char* ReadFile(const char* filename);
extern void DeleteACLList(OicSecAcl_t* acl);
OCStackResult GetDefaultACL(OicSecAcl_t** defaultAcl);
OCEntityHandlerResult ACLEntityHandler (OCEntityHandlerFlag flag,
......@@ -54,37 +54,6 @@ const char* ACL1_JSON_FILE_NAME = "oic_unittest_acl1.json";
#define NUM_ACE_FOR_WILDCARD_IN_ACL1_JSON (2)
char* ReadFile(const char* filename)
{
FILE *fp = NULL;
char *data = NULL;
struct stat st;
// TODO: Find the location of the executable and concatenate the SVR file name
// before opening it.
fp = fopen(filename, "r");
if (fp)
{
if (stat(filename, &st) == 0)
{
data = (char*)OICMalloc(st.st_size);
if (data)
{
if (fread(data, 1, st.st_size, fp) != (size_t)st.st_size)
{
printf("Error in reading file %s", filename);
}
}
}
fclose(fp);
}
else
{
printf("Unable to open %s file", filename);
}
return data;
}
void SetPersistentHandler(OCPersistentStorage *ps, bool set)
{
......
......@@ -56,5 +56,22 @@
"MjIyMjIyMjIyMjIyMjIyMg=="
]
}
],
"svc": [
{
"svcdid": "NTU1NTU1NTU1NTU1NTU1NQ==",
"svct": 1,
"ownrs" : [
"OTk5OTk5OTk5OTk5OTk5OQ=="
]
},
{
"svcdid": "NjY2NjY2NjY2NjY2NjY2Ng==",
"svct": 1,
"ownrs" : [
"OTk5OTk5OTk5OTk5OTk5OQ=="
]
}