- IED server: check user permissions on data set when enabling RCB or changing RCB data sets (LIB61850-393)

v1.6_develop_387
Michael Zillgith 2 years ago
parent 7e3b7991d5
commit a4a58e4250

@ -87,7 +87,8 @@ rcbAccessHandler(void* parameter, ReportControlBlock* rcb, ClientConnection conn
return true;
}
else {
return false;
/* change to false to disallow write access to control block */
return true;
}
}
@ -133,6 +134,18 @@ dataSetAccessHandler(void* parameter, ClientConnection connection, IedServer_Dat
return true;
}
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);
if (!strcmp(ln->name, "GGIO1") && !strcmp(dataObject->name, "AnIn1")) {
return DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
}
return DATA_ACCESS_ERROR_SUCCESS;
}
int
main(int argc, char** argv)
{
@ -196,10 +209,13 @@ main(int argc, char** argv)
IedServer_setConnectionIndicationHandler(iedServer, (IedConnectionIndicationHandler) connectionHandler, NULL);
/* Install handler to perform access control on RCB */
IedServer_setRCBAccessHandler(iedServer, rcbAccessHandler, NULL);
/* Install handler to perform access control on LCB */
IedServer_setLCBAccessHandler(iedServer, lcbAccessHandler, NULL);
/* Install handler to log RCB events */
IedServer_setRCBEventHandler(iedServer, rcbEventHandler, NULL);
/* By default access to variables with FC=DC and FC=CF is not allowed.
@ -208,8 +224,16 @@ main(int argc, char** argv)
*/
IedServer_setWriteAccessPolicy(iedServer, IEC61850_FC_DC, ACCESS_POLICY_ALLOW);
/* Install handler to perform access control on datasets */
IedServer_setDataSetAccessHandler(iedServer, dataSetAccessHandler, NULL);
/* Install handler to perform read access control on data model elements
* NOTE: when read access to a data model element is blocked this will also prevent the client
* to read the data model element in a data set or enable a RCB instance that uses a dataset
* containing the restricted data model element.
*/
IedServer_setReadAccessHandler(iedServer, readAccessHandler, NULL);
/* MMS server will be instructed to start listening for client connections. */
IedServer_start(iedServer, tcpPort);

@ -1,7 +1,7 @@
/*
* reporting.c
*
* Copyright 2013-2022 Michael Zillgith
* Copyright 2013-2023 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -673,6 +673,43 @@ createDataSetValuesShadowBuffer(ReportControl* rc)
}
}
static bool
checkIfClientHasAccessToDataSetEntries(MmsMapping* mapping, MmsServerConnection connection, MmsNamedVariableList mmsVariableList)
{
bool accessAllowed = true;
if (connection) {
LinkedList entryElem = LinkedList_getNext(mmsVariableList->listOfVariables);
while (entryElem) {
MmsNamedVariableListEntry entry = (MmsNamedVariableListEntry)LinkedList_getData(entryElem);
MmsValue* entryValue = mmsServer_getValue(mapping->mmsServer, entry->domain, entry->variableName, connection, true);
if (entryValue) {
if (MmsValue_getType(entryValue) == MMS_DATA_ACCESS_ERROR) {
accessAllowed = false;
}
MmsValue_deleteConditional(entryValue);
}
else {
accessAllowed = false;
}
if (accessAllowed == false)
break;
entryElem = LinkedList_getNext(entryElem);
}
}
return accessAllowed;
}
static bool
updateReportDataset(MmsMapping* mapping, ReportControl* rc, MmsValue* newDatSet, MmsServerConnection connection)
{
@ -760,11 +797,32 @@ updateReportDataset(MmsMapping* mapping, ReportControl* rc, MmsValue* newDatSet,
}
}
if (dataSetValue && dataSetChanged) {
if (dataSetValue) {
const char* dataSetName = MmsValue_toString(dataSetValue);
DataSet* dataSet = IedModel_lookupDataSet(mapping->model, dataSetName);
if (dataSet) {
char domainNameBuf[130];
MmsMapping_getMmsDomainFromObjectReference(dataSetName, domainNameBuf);
MmsDomain* dsDomain = MmsDevice_getDomain(mapping->mmsDevice, domainNameBuf);
if (dsDomain) {
MmsNamedVariableList namedVariableList = MmsDomain_getNamedVariableList(dsDomain, dataSet->name);
if (namedVariableList) {
if (checkIfClientHasAccessToDataSetEntries(mapping, connection, namedVariableList) == false) {
goto exit_function;
}
}
}
}
#if (MMS_DYNAMIC_DATA_SETS == 1)
if (dataSet == NULL) {
dataSet = MmsMapping_getDomainSpecificDataSet(mapping, dataSetName);
@ -779,19 +837,28 @@ updateReportDataset(MmsMapping* mapping, ReportControl* rc, MmsValue* newDatSet,
MmsNamedVariableList mmsVariableList
= MmsServerConnection_getNamedVariableList(connection, dataSetName + 1);
if (mmsVariableList != NULL)
if (mmsVariableList) {
if (checkIfClientHasAccessToDataSetEntries(mapping, connection, mmsVariableList) == false) {
goto exit_function;
}
dataSet = MmsMapping_createDataSetByNamedVariableList(mapping, mmsVariableList);
}
}
}
}
/* check for VMD specific data set */
else if (dataSetName[0] == '/') {
MmsNamedVariableList mmsVariableList = MmsDevice_getNamedVariableListWithName(mapping->mmsDevice, dataSetName + 1);
if (mmsVariableList != NULL)
if (mmsVariableList) {
if (checkIfClientHasAccessToDataSetEntries(mapping, connection, mmsVariableList) == false) {
goto exit_function;
}
dataSet = MmsMapping_createDataSetByNamedVariableList(mapping, mmsVariableList);
}
}
}
@ -810,7 +877,7 @@ updateReportDataset(MmsMapping* mapping, ReportControl* rc, MmsValue* newDatSet,
#endif /* (MMS_DYNAMIC_DATA_SETS == 1) */
if (dataSetChanged == true) {
if (dataSetChanged) {
/* delete pending event and create buffer for new data set */
deleteDataSetValuesShadowBuffer(rc);
@ -830,7 +897,6 @@ updateReportDataset(MmsMapping* mapping, ReportControl* rc, MmsValue* newDatSet,
GLOBAL_FREEMEM(rc->inclusionFlags);
rc->inclusionFlags = (uint8_t*) GLOBAL_CALLOC(dataSet->elementCount, sizeof(uint8_t));
}
success = true;
@ -862,7 +928,6 @@ createDataSetReferenceForDefaultDataSet(ReportControlBlock* rcb, ReportControl*
return dataSetReference;
}
static MmsValue*
createOptFlds(ReportControlBlock* reportControlBlock)
{

@ -1,7 +1,7 @@
/*
* mms_read_service.c
*
* Copyright 2013-2022 Michael Zillgith
* Copyright 2013-2023 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -695,13 +695,9 @@ createNamedVariableListResponse(MmsServerConnection connection, MmsNamedVariable
LinkedList /*<MmsValue>*/ values = LinkedList_create();
LinkedList variables = MmsNamedVariableList_getVariableList(namedList);
int variableCount = LinkedList_size(variables);
int i;
LinkedList variable = LinkedList_getNext(variables);
for (i = 0; i < variableCount; i++) {
while (variable) {
MmsNamedVariableListEntry variableListEntry = (MmsNamedVariableListEntry) variable->data;

@ -572,7 +572,6 @@ exit_function:
return value;
}
MmsDevice*
MmsServer_getDevice(MmsServer self)
{

@ -391,7 +391,7 @@ mmsServer_getNamedVariableListWithName(LinkedList namedVariableLists, const char
LinkedList element = LinkedList_getNext(namedVariableLists);
while (element != NULL) {
while (element) {
MmsNamedVariableList varList = (MmsNamedVariableList) element->data;
if (strcmp(MmsNamedVariableList_getName(varList), variableListName) == 0) {
@ -405,14 +405,13 @@ mmsServer_getNamedVariableListWithName(LinkedList namedVariableLists, const char
return variableList;
}
void
mmsServer_deleteVariableList(LinkedList namedVariableLists, char* variableListName)
{
LinkedList previousElement = namedVariableLists;
LinkedList element = LinkedList_getNext(namedVariableLists);
while (element != NULL ) {
while (element) {
MmsNamedVariableList varList = (MmsNamedVariableList) element->data;
if (strcmp(MmsNamedVariableList_getName(varList), variableListName)
@ -428,5 +427,3 @@ mmsServer_deleteVariableList(LinkedList namedVariableLists, char* variableListNa
element = LinkedList_getNext(element);
}
}

Loading…
Cancel
Save