- extended ListObjectHandler to support different ACSI classes (LIB61850-417)

v1.6_develop_417_rbac2
Michael Zillgith 2 years ago
parent 98c04dfeda
commit bbe23b4b00

@ -23,6 +23,38 @@ sigint_handler(int signalId)
running = 0;
}
static const char*
ACSIClassToStr(ACSIClass acsiClass)
{
switch (acsiClass)
{
case ACSI_CLASS_BRCB:
return "BRCB";
case ACSI_CLASS_URCB:
return "URCB";
case ACSI_CLASS_GoCB:
return "GoCB";
case ACSI_CLASS_SGCB:
return "SGCB";
case ACSI_CLASS_LCB:
return "LCB";
case ACSI_CLASS_GsCB:
return "GsCB";
case ACSI_CLASS_LOG:
return "log";
case ACSI_CLASS_DATA_SET:
return "dataset";
case ACSI_CLASS_DATA_OBJECT:
return "data-object";
case ACSI_CLASS_MSVCB:
return "MSVCB";
case ACSI_CLASS_USVCB:
return "USVCB";
default:
return "unknown";
}
}
static ControlHandlerResult
controlHandlerForBinaryOutput(ControlAction action, void* parameter, MmsValue* value, bool test)
{
@ -65,7 +97,6 @@ controlHandlerForBinaryOutput(ControlAction action, void* parameter, MmsValue* v
return CONTROL_RESULT_OK;
}
static void
connectionHandler (IedServer self, ClientConnection connection, bool connected, void* parameter)
{
@ -137,25 +168,35 @@ dataSetAccessHandler(void* parameter, ClientConnection connection, IedServer_Dat
static MmsDataAccessError
readAccessHandler(LogicalDevice* ld, LogicalNode* ln, DataObject* dataObject, FunctionalConstraint fc, ClientConnection connection, void* parameter)
{
printf("Read access to %s/%s.%s\n", ld->name, ln->name, dataObject->name);
printf("Read access to %s/%s.%s\n", ld->name, ln->name, dataObject ? dataObject->name : "-");
if (dataObject == NULL) {
if (!strcmp(ln->name, "GGIO1")) {
return DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
}
}
else {
if (!strcmp(ln->name, "GGIO1") && !strcmp(dataObject->name, "AnIn1")) {
return DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
}
}
return DATA_ACCESS_ERROR_SUCCESS;
}
static bool
listObjectsAccessHandler(void* parameter, ClientConnection connection, LogicalDevice* ld, LogicalNode* ln, DataObject* dataObject, FunctionalConstraint fc)
listObjectsAccessHandler(void* parameter, ClientConnection connection, ACSIClass acsiClass, LogicalDevice* ld, LogicalNode* ln, const char* objectName, const char* subObjectName, FunctionalConstraint fc)
{
printf("list objects access to %s/%s.%s[%s]\n", ld->name, ln->name, dataObject ? dataObject->name : "-", FunctionalConstraint_toString(fc));
if (subObjectName)
printf("list objects access[2] to %s/%s.%s.%s [acsi-class: %s(%i)] [FC=%s]\n", ld->name, ln ? ln->name : "-", objectName, subObjectName, ACSIClassToStr(acsiClass), acsiClass, FunctionalConstraint_toString(fc));
else
printf("list objects access[2] to %s/%s.%s [acsi-class: %s(%i)] [FC=%s]\n", ld->name, ln ? ln->name : "-", objectName, ACSIClassToStr(acsiClass), acsiClass, FunctionalConstraint_toString(fc));
if (!strcmp(ln->name, "GGIO1")) {
if (dataObject && !strcmp(dataObject->name, "AnIn1")) {
return false;
}
}
// if (acsiClass == ACSI_CLASS_BRCB) {
// return true;
// }
// return false;
return true;
}

@ -1,7 +1,7 @@
/*
* static_model.c
*
* automatically generated from simpleIO_direct_control.cid
* automatically generated from ../../examples/server_example_basic_io/simpleIO_direct_control.cid
*/
#include "static_model.h"
@ -2169,7 +2169,15 @@ ReportControlBlock iedModel_GenericIO_LLN0_report9 = {&iedModel_GenericIO_LLN0,
extern LogControlBlock iedModel_GenericIO_LLN0_lcb0;
extern LogControlBlock iedModel_GenericIO_LLN0_lcb1;
LogControlBlock iedModel_GenericIO_LLN0_lcb0 = {&iedModel_GenericIO_LLN0, "EventLog", "Events", "GenericIO/LLN0$EventLog", 3, 0, true, true, &iedModel_GenericIO_LLN0_lcb1};
LogControlBlock iedModel_GenericIO_LLN0_lcb1 = {&iedModel_GenericIO_LLN0, "GeneralLog", NULL, NULL, 3, 0, true, true, NULL};
extern Log iedModel_GenericIO_LLN0_log0;
extern Log iedModel_GenericIO_LLN0_log1;
Log iedModel_GenericIO_LLN0_log0 = {&iedModel_GenericIO_LLN0, "GeneralLog", &iedModel_GenericIO_LLN0_log1};
Log iedModel_GenericIO_LLN0_log1 = {&iedModel_GenericIO_LLN0, "EventLog", NULL};
IedModel iedModel = {
@ -2180,8 +2188,8 @@ IedModel iedModel = {
NULL,
NULL,
NULL,
NULL,
NULL,
&iedModel_GenericIO_LLN0_lcb0,
&iedModel_GenericIO_LLN0_log0,
initializeValues
};

@ -2467,20 +2467,6 @@ IedConnection_getServerDirectory(IedConnection self, IedClientError* error, bool
LIB61850_API LinkedList /*<char*>*/
IedConnection_getLogicalDeviceDirectory(IedConnection self, IedClientError* error, const char* logicalDeviceName);
typedef enum {
ACSI_CLASS_DATA_OBJECT,
ACSI_CLASS_DATA_SET,
ACSI_CLASS_BRCB,
ACSI_CLASS_URCB,
ACSI_CLASS_LCB,
ACSI_CLASS_LOG,
ACSI_CLASS_SGCB,
ACSI_CLASS_GoCB,
ACSI_CLASS_GsCB,
ACSI_CLASS_MSVCB,
ACSI_CLASS_USVCB
} ACSIClass;
/**
* \brief returns a list of all MMS variables that are children of the given logical node
*

@ -55,6 +55,21 @@ typedef struct {
uint8_t dstAddress[6];
} PhyComAddress;
/** IEC 61850 ACSI classes */
typedef enum {
ACSI_CLASS_DATA_OBJECT,
ACSI_CLASS_DATA_SET,
ACSI_CLASS_BRCB,
ACSI_CLASS_URCB,
ACSI_CLASS_LCB,
ACSI_CLASS_LOG,
ACSI_CLASS_SGCB,
ACSI_CLASS_GoCB,
ACSI_CLASS_GsCB,
ACSI_CLASS_MSVCB,
ACSI_CLASS_USVCB
} ACSIClass;
/**
* \brief Control model (represented by "ctlModel" attribute)
*/

@ -2010,13 +2010,21 @@ IedServer_setDirectoryAccessHandler(IedServer self, IedServer_DirectoryAccessHan
/**
* \brief Callback that is called when a client is invoking a list objects service
*
* This callback can be used to control the list object access to specific objects and is called for each object that are subject to a client request.
*
* \param parameter user provided parameter
* \param connection client connection that is involved
* \param acsiClass the ACSI class of the object
* \param ld the logical device of the object
* \param ln the logical node of the object
* \param objectName the name of the object (e.g. data object name, data set name, log name, RCB name, ...)
* \param subObjectName the name of a sub element of an object or NULL
* \param fc the functional constraint of the object of IEC61850_FC_NONE when the object has no FC.
*
* \return true to include the object in the service response, otherwise false
*/
typedef bool
(*IedServer_ListObjectsAccessHandler) (void* parameter, ClientConnection connection, LogicalDevice* ld, LogicalNode* ln, DataObject* dataObject, FunctionalConstraint fc);
(*IedServer_ListObjectsAccessHandler)(void* parameter, ClientConnection connection, ACSIClass acsiClass, LogicalDevice* ld, LogicalNode* ln, const char* objectName, const char* subObjectName, FunctionalConstraint fc);
/**
* \brief Set a handler to control which objects are return by the list objects services

@ -3315,7 +3315,7 @@ mmsConnectionHandler(void* parameter, MmsServerConnection connection, MmsServerE
}
static bool
mmsListObjectsAccessHandler(void* parameter, MmsDomain* domain, char* variableId, MmsServerConnection connection)
mmsListObjectsAccessHandler(void* parameter, MmsGetNameListType listType, MmsDomain* domain, char* variableId, MmsServerConnection connection)
{
MmsMapping* self = (MmsMapping*) parameter;
@ -3324,20 +3324,75 @@ mmsListObjectsAccessHandler(void* parameter, MmsDomain* domain, char* variableId
bool allowAccess = true;
if (self->listObjectsAccessHandler)
if (listType == MMS_GETNAMELIST_DATASETS)
{
if (self->listObjectsAccessHandler) {
char str[65];
char* ldName = MmsDomain_getName(domain);
LogicalDevice* ld = IedModel_getDevice(self->model, ldName);
LogicalNode* ln = NULL;
char* objectName = variableId;
char* separator = strchr(variableId, '$');
#if (CONFIG_IEC61850_SETTING_GROUPS == 1)
if (separator) {
StringUtils_createStringFromBufferInBuffer(str, (uint8_t*) variableId, separator - variableId);
ln = LogicalDevice_getLogicalNode(ld, str);
if (ln) {
objectName = separator + 1;
}
}
ClientConnection clientConnection = private_IedServer_getClientConnectionByHandle(self->iedServer, connection);
allowAccess = self->listObjectsAccessHandler(self->listObjectsAccessHandlerParameter, clientConnection, ACSI_CLASS_DATA_SET, ld, ln, objectName, NULL, IEC61850_FC_NONE);
}
return allowAccess;
}
else if (listType == MMS_GETNAMELIST_JOURNALS)
{
if (self->listObjectsAccessHandler) {
char str[65];
char* ldName = MmsDomain_getName(domain);
char* objectName = variableId;
LogicalDevice* ld = IedModel_getDevice(self->model, ldName);
LogicalNode* ln = NULL;
char* separator = strchr(variableId, '$');
if (separator) {
if (isFunctionalConstraint("SE", separator)) {
goto exit_function;
StringUtils_createStringFromBufferInBuffer(str, (uint8_t*) variableId, separator - variableId);
ln = LogicalDevice_getLogicalNode(ld, str);
if (ln) {
objectName = separator + 1;
}
}
#endif /* (CONFIG_IEC61850_SETTING_GROUPS == 1) */
ClientConnection clientConnection = private_IedServer_getClientConnectionByHandle(self->iedServer, connection);
allowAccess = self->listObjectsAccessHandler(self->listObjectsAccessHandlerParameter, clientConnection, ACSI_CLASS_LOG, ld, ln, objectName, NULL, IEC61850_FC_NONE);
}
return allowAccess;
}
if (self->listObjectsAccessHandler)
{
char* separator = strchr(variableId, '$');
char* ldName = MmsDomain_getName(domain);
LogicalDevice* ld = IedModel_getDevice(self->model, ldName);
@ -3353,11 +3408,76 @@ mmsListObjectsAccessHandler(void* parameter, MmsDomain* domain, char* variableId
fc == IEC61850_FC_MS || fc == IEC61850_FC_RP ||
fc == IEC61850_FC_LG || fc == IEC61850_FC_GO)
{
char* subObjectName = NULL;
char str[65];
char subObjectBuf[65];
StringUtils_createStringFromBufferInBuffer(str, (uint8_t*) variableId, separator - variableId);
LogicalNode* ln = LogicalDevice_getLogicalNode(ld, str);
if (ln) {
char* doStart = strchr(separator + 1, '$');
if (doStart != NULL) {
char* doEnd = strchr(doStart + 1, '$');
if (doEnd == NULL) {
StringUtils_copyStringToBuffer(doStart + 1, str);
}
else {
doEnd--;
StringUtils_createStringFromBufferInBuffer(str, (uint8_t*) (doStart + 1), doEnd - doStart);
subObjectName = StringUtils_copyStringToBuffer(doEnd + 2, subObjectBuf);
}
}
}
ACSIClass acsiClass = ACSI_CLASS_USVCB;
switch (fc)
{
case IEC61850_FC_BR:
acsiClass = ACSI_CLASS_BRCB;
break;
case IEC61850_FC_RP:
acsiClass = ACSI_CLASS_URCB;
break;
case IEC61850_FC_GO:
acsiClass = ACSI_CLASS_GoCB;
break;
case IEC61850_FC_LG:
acsiClass = ACSI_CLASS_LCB;
break;
case IEC61850_FC_MS:
acsiClass = ACSI_CLASS_MSVCB;
break;
default:
break;
}
if (self->listObjectsAccessHandler) {
ClientConnection clientConnection = private_IedServer_getClientConnectionByHandle(self->iedServer, connection);
allowAccess = self->listObjectsAccessHandler(self->listObjectsAccessHandlerParameter, clientConnection, acsiClass, ld, ln, str, subObjectName, fc);
}
goto exit_function;
}
else
{
char str[65];
char* subObjectName = NULL;
char subObjectBuf[65];
StringUtils_createStringFromBufferInBuffer(str, (uint8_t*) variableId, separator - variableId);
@ -3378,12 +3498,21 @@ mmsListObjectsAccessHandler(void* parameter, MmsDomain* domain, char* variableId
doEnd--;
StringUtils_createStringFromBufferInBuffer(str, (uint8_t*) (doStart + 1), doEnd - doStart);
subObjectName = StringUtils_copyStringToBuffer(doEnd + 2, subObjectBuf);
}
if (fc == IEC61850_FC_SP) {
if (!strcmp(str, "SGCB"))
if (!strcmp(str, "SGCB")) {
ClientConnection clientConnection = private_IedServer_getClientConnectionByHandle(self->iedServer,
connection);
allowAccess = self->listObjectsAccessHandler(self->listObjectsAccessHandlerParameter, clientConnection, ACSI_CLASS_SGCB, ld, ln, str, subObjectName, fc);
goto exit_function;
}
}
ModelNode* dobj = ModelNode_getChild((ModelNode*) ln, str);
@ -3394,7 +3523,9 @@ mmsListObjectsAccessHandler(void* parameter, MmsDomain* domain, char* variableId
ClientConnection clientConnection = private_IedServer_getClientConnectionByHandle(self->iedServer,
connection);
allowAccess = self->listObjectsAccessHandler(self->listObjectsAccessHandlerParameter, clientConnection, ld, ln, (DataObject*) dobj, fc);
if (self->listObjectsAccessHandler) {
allowAccess = self->listObjectsAccessHandler(self->listObjectsAccessHandlerParameter, clientConnection, ACSI_CLASS_DATA_OBJECT, ld, ln, dobj->name, subObjectName, fc);
}
}
}
}
@ -3404,7 +3535,9 @@ mmsListObjectsAccessHandler(void* parameter, MmsDomain* domain, char* variableId
ClientConnection clientConnection = private_IedServer_getClientConnectionByHandle(self->iedServer,
connection);
allowAccess = self->listObjectsAccessHandler(self->listObjectsAccessHandlerParameter, clientConnection, ld, ln, NULL, fc);
if (self->listObjectsAccessHandler) {
allowAccess = self->listObjectsAccessHandler(self->listObjectsAccessHandlerParameter, clientConnection, ACSI_CLASS_DATA_OBJECT, ld, ln, NULL, NULL, fc);
}
}
}
}
@ -3417,7 +3550,9 @@ mmsListObjectsAccessHandler(void* parameter, MmsDomain* domain, char* variableId
ClientConnection clientConnection = private_IedServer_getClientConnectionByHandle(self->iedServer, connection);
allowAccess = self->listObjectsAccessHandler(self->listObjectsAccessHandlerParameter, clientConnection, ld, ln, NULL, fc);
if (self->listObjectsAccessHandler) {
allowAccess = self->listObjectsAccessHandler(self->listObjectsAccessHandlerParameter, clientConnection, ACSI_CLASS_DATA_OBJECT, ld, ln, NULL, NULL, fc);
}
}
}
}
@ -3505,9 +3640,11 @@ mmsReadAccessHandler (void* parameter, MmsDomain* domain, char* variableId, MmsS
}
if (fc == IEC61850_FC_SP) {
if (!strcmp(str, "SGCB"))
if (!strcmp(str, "SGCB")) {
//TODO RBAC2 add callback
return DATA_ACCESS_ERROR_SUCCESS;
}
}
ModelNode* dobj = ModelNode_getChild((ModelNode*) ln, str);

@ -426,7 +426,7 @@ LIB61850_INTERNAL MmsValue*
mmsServer_getValue(MmsServer self, MmsDomain* domain, char* itemId, MmsServerConnection connection, bool isDirectAccess);
LIB61850_INTERNAL bool
mmsServer_checkListAccess(MmsServer self, MmsDomain* domain, char* itemId, MmsServerConnection connection);
mmsServer_checkListAccess(MmsServer self, MmsGetNameListType listType, MmsDomain* domain, char* itemId, MmsServerConnection connection);
LIB61850_INTERNAL void
mmsServer_createMmsWriteResponse(MmsServerConnection connection,

@ -37,7 +37,7 @@ typedef MmsDataAccessError (*MmsWriteVariableHandler)(void* parameter,
MmsDomain* domain, char* variableId, MmsValue* value,
MmsServerConnection connection);
typedef bool (*MmsListAccessHandler) (void* parameter, MmsDomain* domain,
typedef bool (*MmsListAccessHandler) (void* parameter, MmsGetNameListType listType, MmsDomain* domain,
char* variableId, MmsServerConnection connection);
typedef void (*MmsConnectionHandler)(void* parameter,

@ -159,7 +159,7 @@ addSubNamedVaribleNamesToList(MmsServerConnection connection, LinkedList nameLis
if (variableName)
{
bool accessAllowed = mmsServer_checkListAccess(connection->server, domain, variableName, connection);
bool accessAllowed = mmsServer_checkListAccess(connection->server, MMS_GETNAMELIST_DATA, domain, variableName, connection);
if (accessAllowed) {
@ -218,8 +218,12 @@ getJournalListDomainSpecific(MmsServerConnection connection, char* domainName)
MmsJournal journal = (MmsJournal) LinkedList_getData(journalList);
allowAccess = mmsServer_checkListAccess(connection->server, MMS_GETNAMELIST_JOURNALS, domain, journal->name, connection);
if (allowAccess) {
LinkedList_add(nameList, (void*) journal->name);
}
}
}
}
@ -264,7 +268,7 @@ getNameListDomainSpecific(MmsServerConnection connection, char* domainName)
for (i = 0; i < domain->namedVariablesCount; i++) {
bool accessAllowed = mmsServer_checkListAccess(connection->server, domain, variables[index[i]]->name, connection);
bool accessAllowed = mmsServer_checkListAccess(connection->server, MMS_GETNAMELIST_DATA, domain, variables[index[i]]->name, connection);
if (accessAllowed) {
@ -301,7 +305,7 @@ getNameListDomainSpecific(MmsServerConnection connection, char* domainName)
#if (MMS_DATA_SET_SERVICE == 1)
static LinkedList
createStringsFromNamedVariableList(LinkedList variableLists)
createStringsFromNamedVariableList(LinkedList variableLists, MmsServerConnection connection, MmsDomain* domain)
{
LinkedList nameList = LinkedList_create();
LinkedList variableListsElement = LinkedList_getNext(variableLists);
@ -310,8 +314,14 @@ createStringsFromNamedVariableList(LinkedList variableLists)
MmsNamedVariableList variableList =
(MmsNamedVariableList) variableListsElement->data;
printf("createStringsFromNamedVariableList: %s\n", MmsNamedVariableList_getName(variableList));
bool accessAllowed = mmsServer_checkListAccess(connection->server, MMS_GETNAMELIST_DATASETS, domain, variableList->name, connection);
if (accessAllowed) {
LinkedList_add(nameList,
StringUtils_copyString(MmsNamedVariableList_getName(variableList)));
}
variableListsElement = LinkedList_getNext(variableListsElement);
}
@ -338,7 +348,7 @@ getNamedVariableListsDomainSpecific(MmsServerConnection connection, char* domain
if (allowAccess) {
LinkedList variableLists = MmsDomain_getNamedVariableLists(domain);
nameList = createStringsFromNamedVariableList(variableLists);
nameList = createStringsFromNamedVariableList(variableLists, connection, domain);
}
}
@ -354,7 +364,7 @@ getNamedVariableListsVMDSpecific(MmsServerConnection connection)
LinkedList variableLists = MmsDevice_getNamedVariableLists(device);
nameList = createStringsFromNamedVariableList(variableLists);
nameList = createStringsFromNamedVariableList(variableLists, connection, NULL);
return nameList;
}
@ -367,7 +377,7 @@ getNamedVariableListAssociationSpecific(MmsServerConnection connection)
LinkedList variableLists = MmsServerConnection_getNamedVariableLists(connection);
nameList = createStringsFromNamedVariableList(variableLists);
nameList = createStringsFromNamedVariableList(variableLists, connection, NULL);
return nameList;
}

@ -245,7 +245,7 @@ createVariableAccessAttributesResponse(
goto exit_function;
}
bool accessAllowed = mmsServer_checkListAccess(connection->server, domain, nameId, connection);
bool accessAllowed = mmsServer_checkListAccess(connection->server, MMS_GETNAMELIST_DATA, domain, nameId, connection);
if (!accessAllowed) {
if (DEBUG_MMS_SERVER)

@ -603,12 +603,12 @@ mmsServer_checkReadAccess(MmsServer self, MmsDomain* domain, char* itemId, MmsSe
}
bool
mmsServer_checkListAccess(MmsServer self, MmsDomain* domain, char* itemId, MmsServerConnection connection)
mmsServer_checkListAccess(MmsServer self, MmsGetNameListType listType, MmsDomain* domain, char* itemId, MmsServerConnection connection)
{
bool allowAccess = true;
if (self->listAccessHandler) {
allowAccess = self->listAccessHandler(self->listAccessHandlerParameter, domain, itemId, connection);
allowAccess = self->listAccessHandler(self->listAccessHandlerParameter, listType, domain, itemId, connection);
}
return allowAccess;

Loading…
Cancel
Save