- IED server: added IedServer_ListObjectsAccessHandler callback to control LISTOBJECTS access rights (LIB61850-417)

v1.6_develop_417_rbac2
Michael Zillgith 2 years ago
parent 665501c9fa
commit 3c918ee4e3

@ -2007,6 +2007,26 @@ typedef bool
LIB61850_API void LIB61850_API void
IedServer_setDirectoryAccessHandler(IedServer self, IedServer_DirectoryAccessHandler handler, void* parameter); IedServer_setDirectoryAccessHandler(IedServer self, IedServer_DirectoryAccessHandler handler, void* parameter);
/**
* \brief Callback that is called when a client is invoking a list objects service
*
* \param parameter user provided parameter
* \param connection client connection that is involved
*
* \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);
/**
* \brief Set a handler to control which objects are return by the list objects services
*
* \param handler the callback handler to be used
* \param parameter a user provided parameter that is passed to the handler.
*/
LIB61850_API void
IedServer_setListObjectsAccessHandler(IedServer self, IedServer_ListObjectsAccessHandler handler, void* parameter);
/**@}*/ /**@}*/
/**@}*/ /**@}*/

@ -352,6 +352,9 @@ struct sMmsMapping {
IedServer_DirectoryAccessHandler directoryAccessHandler; IedServer_DirectoryAccessHandler directoryAccessHandler;
void* directoryAccessHandlerParameter; void* directoryAccessHandlerParameter;
IedServer_ListObjectsAccessHandler listObjectsAccessHandler;
void* listObjectsAccessHandlerParameter;
}; };
#endif /* MMS_MAPPING_INTERNAL_H_ */ #endif /* MMS_MAPPING_INTERNAL_H_ */

@ -1967,3 +1967,10 @@ IedServer_setDirectoryAccessHandler(IedServer self, IedServer_DirectoryAccessHan
self->mmsMapping->directoryAccessHandler = handler; self->mmsMapping->directoryAccessHandler = handler;
self->mmsMapping->directoryAccessHandlerParameter = parameter; self->mmsMapping->directoryAccessHandlerParameter = parameter;
} }
void
IedServer_setListObjectsAccessHandler(IedServer self, IedServer_ListObjectsAccessHandler handler, void* parameter)
{
self->mmsMapping->listObjectsAccessHandler = handler;
self->mmsMapping->listObjectsAccessHandlerParameter = parameter;
}

@ -3314,6 +3314,122 @@ mmsConnectionHandler(void* parameter, MmsServerConnection connection, MmsServerE
} }
} }
static bool
mmsListObjectsAccessHandler(void* parameter, MmsDomain* domain, char* variableId, MmsServerConnection connection)
{
MmsMapping* self = (MmsMapping*) parameter;
if (DEBUG_IED_SERVER)
printf("IED_SERVER: mmsListObjectsAccessHandler: Requested %s\n", variableId);
bool allowAccess = true;
if (self->listObjectsAccessHandler)
{
char* separator = strchr(variableId, '$');
#if (CONFIG_IEC61850_SETTING_GROUPS == 1)
if (separator) {
if (isFunctionalConstraint("SE", separator)) {
goto exit_function;
}
}
#endif /* (CONFIG_IEC61850_SETTING_GROUPS == 1) */
char* ldName = MmsDomain_getName(domain);
LogicalDevice* ld = IedModel_getDevice(self->model, ldName);
if (ld)
{
FunctionalConstraint fc = IEC61850_FC_NONE;
if (separator) {
fc = FunctionalConstraint_fromString(separator + 1);
if (fc == IEC61850_FC_BR || fc == IEC61850_FC_US ||
fc == IEC61850_FC_MS || fc == IEC61850_FC_RP ||
fc == IEC61850_FC_LG || fc == IEC61850_FC_GO)
{
goto exit_function;
}
else
{
char str[65];
StringUtils_createStringFromBufferInBuffer(str, (uint8_t*) variableId, separator - variableId);
LogicalNode* ln = LogicalDevice_getLogicalNode(ld, str);
if (ln != NULL)
{
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);
}
if (fc == IEC61850_FC_SP) {
if (!strcmp(str, "SGCB"))
goto exit_function;
}
ModelNode* dobj = ModelNode_getChild((ModelNode*) ln, str);
if (dobj != NULL) {
if (dobj->modelType == DataObjectModelType) {
ClientConnection clientConnection = private_IedServer_getClientConnectionByHandle(self->iedServer,
connection);
allowAccess = self->listObjectsAccessHandler(self->listObjectsAccessHandlerParameter, clientConnection, ld, ln, (DataObject*) dobj, fc);
}
}
}
else {
/* no data object but with FC specified */
ClientConnection clientConnection = private_IedServer_getClientConnectionByHandle(self->iedServer,
connection);
allowAccess = self->listObjectsAccessHandler(self->listObjectsAccessHandlerParameter, clientConnection, ld, ln, NULL, fc);
}
}
}
}
else {
LogicalNode* ln = LogicalDevice_getLogicalNode(ld, variableId);
if (ln) {
/* only LN, no FC specified */
ClientConnection clientConnection = private_IedServer_getClientConnectionByHandle(self->iedServer, connection);
allowAccess = self->listObjectsAccessHandler(self->listObjectsAccessHandlerParameter, clientConnection, ld, ln, NULL, fc);
}
}
}
else {
/* internal error ? - we should not end up here! */
}
}
exit_function:
return allowAccess;
}
static MmsDataAccessError static MmsDataAccessError
mmsReadAccessHandler (void* parameter, MmsDomain* domain, char* variableId, MmsServerConnection connection, bool isDirectAccess) mmsReadAccessHandler (void* parameter, MmsDomain* domain, char* variableId, MmsServerConnection connection, bool isDirectAccess)
{ {
@ -3350,11 +3466,9 @@ mmsReadAccessHandler (void* parameter, MmsDomain* domain, char* variableId, MmsS
LogicalDevice* ld = IedModel_getDevice(self->model, ldName); LogicalDevice* ld = IedModel_getDevice(self->model, ldName);
if (ld != NULL) { if (ld != NULL)
{
char str[65]; FunctionalConstraint fc = IEC61850_FC_NONE;
FunctionalConstraint fc;
if (separator != NULL) { if (separator != NULL) {
fc = FunctionalConstraint_fromString(separator + 1); fc = FunctionalConstraint_fromString(separator + 1);
@ -3367,6 +3481,8 @@ mmsReadAccessHandler (void* parameter, MmsDomain* domain, char* variableId, MmsS
} }
else else
{ {
char str[65];
StringUtils_createStringFromBufferInBuffer(str, (uint8_t*) variableId, separator - variableId); StringUtils_createStringFromBufferInBuffer(str, (uint8_t*) variableId, separator - variableId);
LogicalNode* ln = LogicalDevice_getLogicalNode(ld, str); LogicalNode* ln = LogicalDevice_getLogicalNode(ld, str);
@ -3417,6 +3533,16 @@ mmsReadAccessHandler (void* parameter, MmsDomain* domain, char* variableId, MmsS
} }
} }
} }
else {
LogicalNode* ln = LogicalDevice_getLogicalNode(ld, variableId);
if (ln != NULL) {
ClientConnection clientConnection = private_IedServer_getClientConnectionByHandle(self->iedServer, connection);
return self->readAccessHandler(ld, ln, NULL, fc, clientConnection,
self->readAccessHandlerParameter);
}
}
} }
return DATA_ACCESS_ERROR_OBJECT_ACCESS_UNSUPPORTED; return DATA_ACCESS_ERROR_OBJECT_ACCESS_UNSUPPORTED;
@ -3666,6 +3792,7 @@ MmsMapping_installHandlers(MmsMapping* self)
MmsServer_installReadHandler(self->mmsServer, mmsReadHandler, (void*) self); MmsServer_installReadHandler(self->mmsServer, mmsReadHandler, (void*) self);
MmsServer_installWriteHandler(self->mmsServer, mmsWriteHandler, (void*) self); MmsServer_installWriteHandler(self->mmsServer, mmsWriteHandler, (void*) self);
MmsServer_installReadAccessHandler(self->mmsServer, mmsReadAccessHandler, (void*) self); MmsServer_installReadAccessHandler(self->mmsServer, mmsReadAccessHandler, (void*) self);
MmsServer_installListAccessHandler(self->mmsServer, mmsListObjectsAccessHandler, (void*) self);
MmsServer_installConnectionHandler(self->mmsServer, mmsConnectionHandler, (void*) self); MmsServer_installConnectionHandler(self->mmsServer, mmsConnectionHandler, (void*) self);
MmsServer_installVariableListAccessHandler(self->mmsServer, variableListAccessHandler, (void*) self); MmsServer_installVariableListAccessHandler(self->mmsServer, variableListAccessHandler, (void*) self);
MmsServer_installGetNameListHandler(self->mmsServer, mmsGetNameListHandler, (void*) self); MmsServer_installGetNameListHandler(self->mmsServer, mmsGetNameListHandler, (void*) self);

@ -120,6 +120,9 @@ struct sMmsServer {
MmsWriteVariableHandler writeHandler; MmsWriteVariableHandler writeHandler;
void* writeHandlerParameter; void* writeHandlerParameter;
MmsListAccessHandler listAccessHandler;
void* listAccessHandlerParameter;
MmsConnectionHandler connectionHandler; MmsConnectionHandler connectionHandler;
void* connectionHandlerParameter; void* connectionHandlerParameter;
@ -422,6 +425,9 @@ mmsServer_setValue(MmsServer self, MmsDomain* domain, char* itemId, MmsValue* va
LIB61850_INTERNAL MmsValue* LIB61850_INTERNAL MmsValue*
mmsServer_getValue(MmsServer self, MmsDomain* domain, char* itemId, MmsServerConnection connection, bool isDirectAccess); 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);
LIB61850_INTERNAL void LIB61850_INTERNAL void
mmsServer_createMmsWriteResponse(MmsServerConnection connection, mmsServer_createMmsWriteResponse(MmsServerConnection connection,
uint32_t invokeId, ByteBuffer* response, int numberOfItems, MmsDataAccessError* accessResults); uint32_t invokeId, ByteBuffer* response, int numberOfItems, MmsDataAccessError* accessResults);

@ -37,6 +37,9 @@ typedef MmsDataAccessError (*MmsWriteVariableHandler)(void* parameter,
MmsDomain* domain, char* variableId, MmsValue* value, MmsDomain* domain, char* variableId, MmsValue* value,
MmsServerConnection connection); MmsServerConnection connection);
typedef bool (*MmsListAccessHandler) (void* parameter, MmsDomain* domain,
char* variableId, MmsServerConnection connection);
typedef void (*MmsConnectionHandler)(void* parameter, typedef void (*MmsConnectionHandler)(void* parameter,
MmsServerConnection connection, MmsServerEvent event); MmsServerConnection connection, MmsServerEvent event);
@ -63,6 +66,9 @@ LIB61850_INTERNAL void
MmsServer_installWriteHandler(MmsServer self, MmsWriteVariableHandler, MmsServer_installWriteHandler(MmsServer self, MmsWriteVariableHandler,
void* parameter); void* parameter);
LIB61850_INTERNAL void
MmsServer_installListAccessHandler(MmsServer self, MmsListAccessHandler listAccessHandler, void* parameter);
/** /**
* A connection handler will be invoked whenever a new client connection is opened or closed * A connection handler will be invoked whenever a new client connection is opened or closed
*/ */

@ -129,7 +129,7 @@ appendMmsSubVariable(char* name, char* child)
} }
static LinkedList static LinkedList
addSubNamedVaribleNamesToList(LinkedList nameList, char* prefix, MmsVariableSpecification* variable) addSubNamedVaribleNamesToList(MmsServerConnection connection, LinkedList nameList, MmsDomain* domain, char* prefix, MmsVariableSpecification* variable)
{ {
LinkedList listElement = nameList; LinkedList listElement = nameList;
@ -159,13 +159,19 @@ addSubNamedVaribleNamesToList(LinkedList nameList, char* prefix, MmsVariableSpec
if (variableName) if (variableName)
{ {
bool accessAllowed = mmsServer_checkListAccess(connection->server, domain, variableName, connection);
if (accessAllowed) {
listElement = LinkedList_insertAfter(listElement, variableName); listElement = LinkedList_insertAfter(listElement, variableName);
#if (CONFIG_MMS_SORT_NAME_LIST == 1) #if (CONFIG_MMS_SORT_NAME_LIST == 1)
listElement = addSubNamedVaribleNamesToList(listElement, variableName, variables[index[i]]); listElement = addSubNamedVaribleNamesToList(connection, listElement, domain, variableName, variables[index[i]]);
#else #else
listElement = addSubNamedVaribleNamesToList(listElement, variableName, variables[i]); listElement = addSubNamedVaribleNamesToList(connection, listElement, domain, variableName, variables[i]);
#endif /* (CONFIG_MMS_SORT_NAME_LIST == 1) */ #endif /* (CONFIG_MMS_SORT_NAME_LIST == 1) */
}
} }
} }
@ -233,7 +239,7 @@ getNameListDomainSpecific(MmsServerConnection connection, char* domainName)
bool allowAccess = true; bool allowAccess = true;
if (connection->server->getNameListHandler) { if (connection->server->getNameListHandler) {
allowAccess = connection->server->getNameListHandler(connection->server->getNameListHandlerParameter, MMS_GETNAMELIST_DATASETS, domain, connection); allowAccess = connection->server->getNameListHandler(connection->server->getNameListHandlerParameter, MMS_GETNAMELIST_DATA, domain, connection);
} }
if (allowAccess) { if (allowAccess) {
@ -255,6 +261,10 @@ getNameListDomainSpecific(MmsServerConnection connection, char* domainName)
for (i = 0; i < domain->namedVariablesCount; i++) { for (i = 0; i < domain->namedVariablesCount; i++) {
bool accessAllowed = mmsServer_checkListAccess(connection->server, domain, variables[index[i]]->name, connection);
if (accessAllowed) {
#if (CONFIG_MMS_SORT_NAME_LIST == 1) #if (CONFIG_MMS_SORT_NAME_LIST == 1)
element = LinkedList_insertAfter(element, StringUtils_copyString(variables[index[i]]->name)); element = LinkedList_insertAfter(element, StringUtils_copyString(variables[index[i]]->name));
#else #else
@ -264,15 +274,17 @@ getNameListDomainSpecific(MmsServerConnection connection, char* domainName)
#if (CONFIG_MMS_SUPPORT_FLATTED_NAME_SPACE == 1) #if (CONFIG_MMS_SUPPORT_FLATTED_NAME_SPACE == 1)
#if (CONFIG_MMS_SORT_NAME_LIST == 1) #if (CONFIG_MMS_SORT_NAME_LIST == 1)
char* prefix = variables[index[i]]->name; char* prefix = variables[index[i]]->name;
element = addSubNamedVaribleNamesToList(element, prefix, variables[index[i]]); element = addSubNamedVaribleNamesToList(connection, element, domain, prefix, variables[index[i]]);
#else #else
char* prefix = variables[i]->name; char* prefix = variables[i]->name;
element = addSubNamedVaribleNamesToList(element, prefix, variables[i]); element = addSubNamedVaribleNamesToList(connection, element, domain, prefix, variables[i]);
#endif /* (CONFIG_MMS_SORT_NAME_LIST == 1) */ #endif /* (CONFIG_MMS_SORT_NAME_LIST == 1) */
#endif /* (CONFIG_MMS_SUPPORT_FLATTED_NAME_SPACE == 1) */ #endif /* (CONFIG_MMS_SUPPORT_FLATTED_NAME_SPACE == 1) */
} }
}
#if (CONFIG_MMS_SORT_NAME_LIST == 1) #if (CONFIG_MMS_SORT_NAME_LIST == 1)
GLOBAL_FREEMEM(index); GLOBAL_FREEMEM(index);
#endif #endif

@ -351,6 +351,13 @@ MmsServer_installWriteHandler(MmsServer self, MmsWriteVariableHandler writeHandl
self->writeHandlerParameter = parameter; self->writeHandlerParameter = parameter;
} }
void
MmsServer_installListAccessHandler(MmsServer self, MmsListAccessHandler listAccessHandler, void* parameter)
{
self->listAccessHandler = listAccessHandler;
self->listAccessHandlerParameter = parameter;
}
void void
MmsServer_installConnectionHandler(MmsServer self, MmsConnectionHandler connectionHandler, void* parameter) MmsServer_installConnectionHandler(MmsServer self, MmsConnectionHandler connectionHandler, void* parameter)
{ {
@ -579,6 +586,34 @@ exit_function:
return value; return value;
} }
MmsDataAccessError
mmsServer_checkReadAccess(MmsServer self, MmsDomain* domain, char* itemId, MmsServerConnection connection, bool isDirectAccess)
{
MmsDataAccessError accessError = DATA_ACCESS_ERROR_SUCCESS;
printf("mmsServer_checkReadAccess(%s/%s)\n", domain->domainName, itemId);
if (self->readAccessHandler) {
accessError =
self->readAccessHandler(self->readAccessHandlerParameter, (domain == (MmsDomain*) self->device) ? NULL : domain,
itemId, connection, isDirectAccess);
}
return accessError;
}
bool
mmsServer_checkListAccess(MmsServer self, MmsDomain* domain, char* itemId, MmsServerConnection connection)
{
bool allowAccess = true;
if (self->listAccessHandler) {
allowAccess = self->listAccessHandler(self->listAccessHandlerParameter, domain, itemId, connection);
}
return allowAccess;
}
MmsDevice* MmsDevice*
MmsServer_getDevice(MmsServer self) MmsServer_getDevice(MmsServer self)
{ {

Loading…
Cancel
Save