- IED server: Added read/write access control to GoCBs/SVCBs with IedServer_ControlBlockAccessHandler (LIB61850-420)

v1.6_develop_417_rbac2
Michael Zillgith 2 years ago
parent 5e57b5d943
commit a397eeee85

@ -38,7 +38,7 @@ LIBIEC61850_SV_createSVControlBlocks(MmsMapping* self, MmsDomain* domain,
LogicalNode* logicalNode, int svCount, bool unicast);
LIB61850_INTERNAL MmsValue*
LIBIEC61850_SV_readAccessSampledValueControlBlock(MmsMapping* self, MmsDomain* domain, char* variableIdOrig);
LIBIEC61850_SV_readAccessSampledValueControlBlock(MmsMapping* self, MmsDomain* domain, char* variableIdOrig , MmsServerConnection connection);
LIB61850_INTERNAL MmsDataAccessError
LIBIEC61850_SV_writeAccessSVControlBlock(MmsMapping* self, MmsDomain* domain, char* variableIdOrig,

@ -395,7 +395,6 @@ updateLogStatusInLCB(LogControl* self)
}
}
static void
freeDynamicDataSet(LogControl* self)
{

@ -2345,7 +2345,7 @@ lookupGCB(MmsMapping* self, MmsDomain* domain, char* lnName, char* objectName)
static MmsDataAccessError
writeAccessGooseControlBlock(MmsMapping* self, MmsDomain* domain, char* variableIdOrig,
MmsValue* value)
MmsValue* value, MmsServerConnection connection)
{
char variableId[130];
@ -2377,6 +2377,20 @@ writeAccessGooseControlBlock(MmsMapping* self, MmsDomain* domain, char* variable
if (mmsGCB == NULL)
return DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
/* check if write access to GoCB is allowed on this connection */
if (self->controlBlockAccessHandler)
{
LogicalNode* ln = MmsGooseControlBlock_getLogicalNode(mmsGCB);
LogicalDevice* ld = (LogicalDevice*)ln->parent;
ClientConnection clientConnection = private_IedServer_getClientConnectionByHandle(self->iedServer, connection);
if (self->controlBlockAccessHandler(self->controlBlockAccessHandlerParameter, clientConnection, ACSI_CLASS_GoCB, ld, ln, MmsGooseControlBlock_getName(mmsGCB), varName, IEC61850_CB_ACCESS_TYPE_WRITE) == false) {
return DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
}
}
if (strcmp(varName, "GoEna") == 0) {
if (MmsValue_getType(value) != MMS_BOOLEAN)
return DATA_ACCESS_ERROR_TYPE_INCONSISTENT;
@ -2619,7 +2633,7 @@ mmsWriteHandler(void* parameter, MmsDomain* domain,
/* Goose control block - GO */
if (isGooseControlBlock(separator))
return writeAccessGooseControlBlock(self, domain, variableId, value);
return writeAccessGooseControlBlock(self, domain, variableId, value, connection);
#endif /* (CONFIG_INCLUDE_GOOSE_SUPPORT == 1) */
@ -3063,7 +3077,7 @@ MmsMapping_installReadAccessHandler(MmsMapping* self, ReadAccessHandler handler,
#if (CONFIG_INCLUDE_GOOSE_SUPPORT == 1)
static MmsValue*
readAccessGooseControlBlock(MmsMapping* self, MmsDomain* domain, char* variableIdOrig)
readAccessGooseControlBlock(MmsMapping* self, MmsDomain* domain, char* variableIdOrig, MmsServerConnection connection)
{
MmsValue* value = NULL;
@ -3087,13 +3101,28 @@ readAccessGooseControlBlock(MmsMapping* self, MmsDomain* domain, char* variableI
char* varName = MmsMapping_getNextNameElement(objectName);
if (varName != NULL)
if (varName)
*(varName - 1) = 0;
MmsGooseControlBlock mmsGCB = lookupGCB(self, domain, lnName, objectName);
if (mmsGCB != NULL) {
if (varName != NULL) {
if (mmsGCB) {
/* check if read access to GoCB is allowed on this connection */
if (self->controlBlockAccessHandler)
{
LogicalNode* ln = MmsGooseControlBlock_getLogicalNode(mmsGCB);
LogicalDevice* ld = (LogicalDevice*)ln->parent;
ClientConnection clientConnection = private_IedServer_getClientConnectionByHandle(self->iedServer, connection);
if (self->controlBlockAccessHandler(self->controlBlockAccessHandlerParameter, clientConnection, ACSI_CLASS_GoCB, ld, ln, MmsGooseControlBlock_getName(mmsGCB), varName, IEC61850_CB_ACCESS_TYPE_READ) == false) {
return &objectAccessDenied;
}
}
if (varName) {
value = MmsValue_getSubElement(MmsGooseControlBlock_getMmsValues(mmsGCB),
MmsGooseControlBlock_getVariableSpecification(mmsGCB), varName);
}
@ -3107,7 +3136,6 @@ readAccessGooseControlBlock(MmsMapping* self, MmsDomain* domain, char* variableI
#endif /* (CONFIG_INCLUDE_GOOSE_SUPPORT == 1) */
static MmsValue*
mmsReadHandler(void* parameter, MmsDomain* domain, char* variableId, MmsServerConnection connection, bool isDirectAccess)
{
@ -3137,7 +3165,7 @@ mmsReadHandler(void* parameter, MmsDomain* domain, char* variableId, MmsServerCo
#if (CONFIG_INCLUDE_GOOSE_SUPPORT == 1)
/* GOOSE control blocks - GO */
if (isGooseControlBlock(separator)) {
retValue = readAccessGooseControlBlock(self, domain, variableId);
retValue = readAccessGooseControlBlock(self, domain, variableId, connection);
goto exit_function;
}
#endif
@ -3145,7 +3173,7 @@ mmsReadHandler(void* parameter, MmsDomain* domain, char* variableId, MmsServerCo
#if (CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT == 1)
/* Sampled Value control blocks - MS/US */
if (isSampledValueControlBlock(separator)) {
retValue = LIBIEC61850_SV_readAccessSampledValueControlBlock(self, domain, variableId);
retValue = LIBIEC61850_SV_readAccessSampledValueControlBlock(self, domain, variableId, connection);
goto exit_function;
}
#endif
@ -3683,9 +3711,9 @@ mmsReadAccessHandler (void* parameter, MmsDomain* domain, char* variableId, MmsS
ClientConnection clientConnection = private_IedServer_getClientConnectionByHandle(self->iedServer,
connection);
if (self->controlBlockAccessHandler(self->controlBlockAccessHandlerParameter, clientConnection, ACSI_CLASS_SGCB, ld, ln, str, "", IEC61850_CB_ACCESS_TYPE_READ) == false) {
if (self->controlBlockAccessHandler(self->controlBlockAccessHandlerParameter, clientConnection, ACSI_CLASS_SGCB, ld, ln, str, "", IEC61850_CB_ACCESS_TYPE_READ) == false) {
return DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
}
}
}
return DATA_ACCESS_ERROR_SUCCESS;

@ -1,7 +1,7 @@
/*
* mms_sv.c
*
* Copyright 2015-2022 Michael Zillgith
* Copyright 2015-2023 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -32,6 +32,8 @@
#include "mms_sv.h"
#include "mms_mapping_internal.h"
#include "ied_server_private.h"
#include "mms_value_internal.h"
struct sMmsSampledValueControlBlock {
SVControlBlock* svcb;
@ -50,11 +52,12 @@ struct sMmsSampledValueControlBlock {
MmsValue* svEnaValue;
MmsValue* resvValue;
SVCBEventHandler eventHandler;
void* eventHandlerParameter;
};
static MmsValue objectAccessDenied = {MMS_DATA_ACCESS_ERROR, false, {DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED}};
MmsSampledValueControlBlock
MmsSampledValueControlBlock_create()
{
@ -63,7 +66,6 @@ MmsSampledValueControlBlock_create()
return self;
}
void
MmsSampledValueControlBlock_destroy(MmsSampledValueControlBlock self)
{
@ -105,7 +107,8 @@ MmsSampledValueControlBlock_enable(MmsSampledValueControlBlock self)
if (DEBUG_IED_SERVER)
printf("IED_SERVER: enable SVCB %s\n", self->svcb->name);
self->eventHandler(self->svcb, IEC61850_SVCB_EVENT_ENABLE, self->eventHandlerParameter);
if (self->eventHandler)
self->eventHandler(self->svcb, IEC61850_SVCB_EVENT_ENABLE, self->eventHandlerParameter);
}
static void
@ -117,7 +120,8 @@ MmsSampledValueControlBlock_disable(MmsSampledValueControlBlock self)
if (DEBUG_IED_SERVER)
printf("IED_SERVER: disable SVCB %s\n", self->svcb->name);
self->eventHandler(self->svcb, IEC61850_SVCB_EVENT_DISABLE, self->eventHandlerParameter);
if (self->eventHandler)
self->eventHandler(self->svcb, IEC61850_SVCB_EVENT_DISABLE, self->eventHandlerParameter);
}
static bool
@ -150,7 +154,7 @@ LIBIEC61850_SV_writeAccessSVControlBlock(MmsMapping* self, MmsDomain* domain, ch
char* varName = MmsMapping_getNextNameElement(objectName);
if (varName != NULL)
if (varName)
*(varName - 1) = 0;
else
return DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
@ -160,7 +164,28 @@ LIBIEC61850_SV_writeAccessSVControlBlock(MmsMapping* self, MmsDomain* domain, ch
if (mmsSVCB == NULL)
return DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
if (mmsSVCB->reservedByClient != NULL) {
/* check if write access to SVCB is allowed on this connection */
if (self->controlBlockAccessHandler)
{
ACSIClass acsiClass;
if (mmsSVCB->svcb->isUnicast)
acsiClass = ACSI_CLASS_USVCB;
else
acsiClass = ACSI_CLASS_MSVCB;
LogicalNode* ln = mmsSVCB->logicalNode;
LogicalDevice* ld = (LogicalDevice*)ln->parent;
ClientConnection clientConnection = private_IedServer_getClientConnectionByHandle(self->iedServer, connection);
if (self->controlBlockAccessHandler(self->controlBlockAccessHandlerParameter, clientConnection, acsiClass, ld, ln, mmsSVCB->svcb->name, varName, IEC61850_CB_ACCESS_TYPE_WRITE) == false) {
return DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
}
}
if (mmsSVCB->reservedByClient) {
if (mmsSVCB->reservedByClient != connection)
return DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE;
}
@ -209,7 +234,7 @@ LIBIEC61850_SV_writeAccessSVControlBlock(MmsMapping* self, MmsDomain* domain, ch
}
MmsValue*
LIBIEC61850_SV_readAccessSampledValueControlBlock(MmsMapping* self, MmsDomain* domain, char* variableIdOrig)
LIBIEC61850_SV_readAccessSampledValueControlBlock(MmsMapping* self, MmsDomain* domain, char* variableIdOrig, MmsServerConnection connection)
{
MmsValue* value = NULL;
@ -233,13 +258,35 @@ LIBIEC61850_SV_readAccessSampledValueControlBlock(MmsMapping* self, MmsDomain* d
char* varName = MmsMapping_getNextNameElement(objectName);
if (varName != NULL)
if (varName)
*(varName - 1) = 0;
MmsSampledValueControlBlock mmsSVCB = lookupSVCB(self, domain, lnName, objectName);
if (mmsSVCB != NULL) {
if (varName != NULL) {
if (mmsSVCB) {
/* check if read access to SVCB is allowed on this connection */
if (self->controlBlockAccessHandler)
{
ACSIClass acsiClass;
if (mmsSVCB->svcb->isUnicast)
acsiClass = ACSI_CLASS_USVCB;
else
acsiClass = ACSI_CLASS_MSVCB;
LogicalNode* ln = mmsSVCB->logicalNode;
LogicalDevice* ld = (LogicalDevice*)ln->parent;
ClientConnection clientConnection = private_IedServer_getClientConnectionByHandle(self->iedServer, connection);
if (self->controlBlockAccessHandler(self->controlBlockAccessHandlerParameter, clientConnection, acsiClass, ld, ln, mmsSVCB->svcb->name, varName, IEC61850_CB_ACCESS_TYPE_READ) == false) {
return &objectAccessDenied;
}
}
if (varName) {
value = MmsValue_getSubElement(mmsSVCB->mmsValue, mmsSVCB->mmsType, varName);
}
else {

Loading…
Cancel
Save