diff --git a/src/iec61850/inc/iec61850_server.h b/src/iec61850/inc/iec61850_server.h index 2288b207..ad88b369 100644 --- a/src/iec61850/inc/iec61850_server.h +++ b/src/iec61850/inc/iec61850_server.h @@ -2035,6 +2035,17 @@ typedef bool LIB61850_API void IedServer_setListObjectsAccessHandler(IedServer self, IedServer_ListObjectsAccessHandler handler, void* parameter); +typedef enum { + IEC61850_CB_ACCESS_TYPE_READ, + IEC61850_CB_ACCESS_TYPE_WRITE +} IedServer_ControlBlockAccessType; + +typedef bool +(*IedServer_ControlBlockAccessHandler)(void* parameter, ClientConnection connection, ACSIClass acsiClass, LogicalDevice* ld, LogicalNode* ln, const char* objectName, const char* subObjectName, IedServer_ControlBlockAccessType accessType); + +LIB61850_API void +IedServer_setControlBlockAccessHandler(IedServer self, IedServer_ControlBlockAccessHandler handler, void* parameter); + /**@}*/ /**@}*/ diff --git a/src/iec61850/inc_private/mms_mapping_internal.h b/src/iec61850/inc_private/mms_mapping_internal.h index 6e3edb52..4a27db2c 100644 --- a/src/iec61850/inc_private/mms_mapping_internal.h +++ b/src/iec61850/inc_private/mms_mapping_internal.h @@ -355,6 +355,9 @@ struct sMmsMapping { IedServer_ListObjectsAccessHandler listObjectsAccessHandler; void* listObjectsAccessHandlerParameter; + + IedServer_ControlBlockAccessHandler controlBlockAccessHandler; + void* controlBlockAccessHandlerParameter; }; #endif /* MMS_MAPPING_INTERNAL_H_ */ diff --git a/src/iec61850/server/impl/ied_server.c b/src/iec61850/server/impl/ied_server.c index aa8e84cd..0ad910eb 100644 --- a/src/iec61850/server/impl/ied_server.c +++ b/src/iec61850/server/impl/ied_server.c @@ -1974,3 +1974,10 @@ IedServer_setListObjectsAccessHandler(IedServer self, IedServer_ListObjectsAcces self->mmsMapping->listObjectsAccessHandler = handler; self->mmsMapping->listObjectsAccessHandlerParameter = parameter; } + +void +IedServer_setControlBlockAccessHandler(IedServer self, IedServer_ControlBlockAccessHandler handler, void* parameter) +{ + self->mmsMapping->controlBlockAccessHandler = handler; + self->mmsMapping->controlBlockAccessHandlerParameter = parameter; +} diff --git a/src/iec61850/server/mms_mapping/logging.c b/src/iec61850/server/mms_mapping/logging.c index c55a1ff4..0e682f72 100644 --- a/src/iec61850/server/mms_mapping/logging.c +++ b/src/iec61850/server/mms_mapping/logging.c @@ -524,6 +524,7 @@ LIBIEC61850_LOG_SVC_writeAccessLogControlBlock(MmsMapping* self, MmsDomain* doma } else { + //TODO RBAC2 remove!? if (self->lcbAccessHandler) { ClientConnection clientConnection = private_IedServer_getClientConnectionByHandle(self->iedServer, connection); @@ -534,6 +535,32 @@ LIBIEC61850_LOG_SVC_writeAccessLogControlBlock(MmsMapping* self, MmsDomain* doma goto exit_function; } } + + if (self->controlBlockAccessHandler) { + ClientConnection clientConnection = private_IedServer_getClientConnectionByHandle(self->iedServer, connection); + + LogicalDevice* ld = IedModel_getDevice(self->model, domain->domainName); + + if (ld) { + LogicalNode* ln = LogicalDevice_getLogicalNode(ld, lnName); + + if (ln) { + if (self->controlBlockAccessHandler(self->controlBlockAccessHandlerParameter, clientConnection, ACSI_CLASS_LCB, ld, ln, logControl->name, varName, IEC61850_CB_ACCESS_TYPE_WRITE) == false) { + retVal = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED; + } + } + else { + retVal = DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT; + } + } + else { + retVal = DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT; + } + + if (retVal != DATA_ACCESS_ERROR_SUCCESS) { + goto exit_function; + } + } } if (strcmp(varName, "LogEna") == 0) { @@ -747,6 +774,7 @@ LIBIEC61850_LOG_SVC_readAccessControlBlock(MmsMapping* self, MmsDomain* domain, { bool allowAccess = true; + //TODO RBAC2 remove?! if (self->lcbAccessHandler) { ClientConnection clientConnection = private_IedServer_getClientConnectionByHandle(self->iedServer, connection); @@ -758,6 +786,24 @@ LIBIEC61850_LOG_SVC_readAccessControlBlock(MmsMapping* self, MmsDomain* domain, } } + if (self->controlBlockAccessHandler) { + ClientConnection clientConnection = private_IedServer_getClientConnectionByHandle(self->iedServer, connection); + + LogicalDevice* ld = IedModel_getDevice(self->model, domain->domainName); + + if (ld) { + LogicalNode* ln = LogicalDevice_getLogicalNode(ld, lnName); + + if (ln) { + if (self->controlBlockAccessHandler(self->controlBlockAccessHandlerParameter, clientConnection, ACSI_CLASS_LCB, ld, ln, logControl->name, varName, IEC61850_CB_ACCESS_TYPE_READ) == false) { + allowAccess = false; + + value = &objectAccessDenied; + } + } + } + } + if (allowAccess) { updateLogStatusInLCB(logControl); diff --git a/src/iec61850/server/mms_mapping/mms_mapping.c b/src/iec61850/server/mms_mapping/mms_mapping.c index 9b37a81b..9aaeea3b 100644 --- a/src/iec61850/server/mms_mapping/mms_mapping.c +++ b/src/iec61850/server/mms_mapping/mms_mapping.c @@ -2701,6 +2701,42 @@ mmsWriteHandler(void* parameter, MmsDomain* domain, char* nameId = nextSep + 1; + /* check access permissions */ + if (self->controlBlockAccessHandler) + { + MmsDataAccessError retVal = DATA_ACCESS_ERROR_SUCCESS; + + ClientConnection clientConnection = private_IedServer_getClientConnectionByHandle(self->iedServer, + connection); + + LogicalDevice* ld = IedModel_getDevice(self->model, domain->domainName); + + if (ld) { + char lnName[65]; + strncpy(lnName, variableId, 64); + lnName[64] = 0; + lnName[lnNameLength] = 0; + + LogicalNode* ln = LogicalDevice_getLogicalNode(ld, lnName); + + if (ln) { + if (self->controlBlockAccessHandler(self->controlBlockAccessHandlerParameter, clientConnection, ACSI_CLASS_SGCB, ld, ln, "SGCB", nameId, IEC61850_CB_ACCESS_TYPE_WRITE) == false) { + retVal = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED; + } + } + else { + retVal = DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT; + } + } + else { + retVal = DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT; + } + + if (retVal != DATA_ACCESS_ERROR_SUCCESS) { + return retVal; + } + } + if (strcmp(nameId, "ActSG") == 0) { SettingGroup* sg = getSettingGroupByMmsDomain(self, domain); MmsDataAccessError retVal = DATA_ACCESS_ERROR_SUCCESS; @@ -2709,6 +2745,7 @@ mmsWriteHandler(void* parameter, MmsDomain* domain, uint32_t val = MmsValue_toUint32(value); if ((val > 0) && (val <= sg->sgcb->numOfSGs)) { + if (val != sg->sgcb->actSG) { if (sg->actSgChangedHandler) { @@ -3640,8 +3677,17 @@ mmsReadAccessHandler (void* parameter, MmsDomain* domain, char* variableId, MmsS } if (fc == IEC61850_FC_SP) { - if (!strcmp(str, "SGCB")) { - //TODO RBAC2 add callback + if (!strcmp(str, "SGCB")) + { + if (self->controlBlockAccessHandler) { + 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) { + return DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED; + } + } + return DATA_ACCESS_ERROR_SUCCESS; } } diff --git a/src/iec61850/server/mms_mapping/reporting.c b/src/iec61850/server/mms_mapping/reporting.c index 9cbbb4f2..2ad84048 100644 --- a/src/iec61850/server/mms_mapping/reporting.c +++ b/src/iec61850/server/mms_mapping/reporting.c @@ -1781,6 +1781,26 @@ ReportControl_readAccess(ReportControl* rc, MmsMapping* mmsMapping, MmsServerCon clientConnection = private_IedServer_getClientConnectionByHandle(mmsMapping->iedServer, connection); } + if (mmsMapping->controlBlockAccessHandler) + { + ACSIClass acsiClass; + + if (rc->rcb->buffered) + acsiClass = ACSI_CLASS_BRCB; + else + acsiClass = ACSI_CLASS_URCB; + + LogicalNode* ln = rc->rcb->parent; + + LogicalDevice* ld = (LogicalDevice*)ln->parent; + + if (mmsMapping->controlBlockAccessHandler(mmsMapping->controlBlockAccessHandlerParameter, clientConnection, acsiClass, ld, ln, rc->name, elementName, IEC61850_CB_ACCESS_TYPE_READ) == false) { + accessError = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED; + accessAllowed = false; + } + } + + //TODO RBAC2 remove? if (mmsMapping->rcbAccessHandler) { if (mmsMapping->rcbAccessHandler(mmsMapping->rcbAccessHandlerParameter, rc->rcb, clientConnection, RCB_EVENT_GET_PARAMETER) == false) { accessError = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED; @@ -1890,7 +1910,7 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme ClientConnection clientConnection = private_IedServer_getClientConnectionByHandle(self->iedServer, connection); - /* check if write access to RCB is allowed on this connection */ + //TODO RBAC2 remove? if (self->rcbAccessHandler) { if (self->rcbAccessHandler(self->rcbAccessHandlerParameter, rc->rcb, clientConnection, RCB_EVENT_SET_PARAMETER) == false) { retVal = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED; @@ -1899,6 +1919,27 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme } } + /* check if write access to RCB is allowed on this connection */ + if (self->controlBlockAccessHandler) + { + ACSIClass acsiClass; + + if (rc->rcb->buffered) + acsiClass = ACSI_CLASS_BRCB; + else + acsiClass = ACSI_CLASS_URCB; + + LogicalNode* ln = rc->rcb->parent; + + LogicalDevice* ld = (LogicalDevice*)ln->parent; + + if (self->controlBlockAccessHandler(self->controlBlockAccessHandlerParameter, clientConnection, acsiClass, ld, ln, rc->name, elementName, IEC61850_CB_ACCESS_TYPE_WRITE) == false) { + retVal = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED; + + goto exit_function_only_tracking; + } + } + /* check reservation timeout for buffered RCBs */ if (rc->buffered) {