diff --git a/dotnet/IEC61850forCSharp/AcseAuthenticationParameter.cs b/dotnet/IEC61850forCSharp/AcseAuthenticationParameter.cs
new file mode 100644
index 00000000..1e5496b6
--- /dev/null
+++ b/dotnet/IEC61850forCSharp/AcseAuthenticationParameter.cs
@@ -0,0 +1,101 @@
+/*
+ * AcseAuthenticationParameter.cs
+ *
+ * Copyright 2014 Michael Zillgith
+ *
+ * This file is part of libIEC61850.
+ *
+ * libIEC61850 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * libIEC61850 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with libIEC61850. If not, see .
+ *
+ * See COPYING file for the complete license text.
+ */
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Text;
+
+// IEC 61850 API for the libiec61850 .NET wrapper library
+namespace IEC61850
+{
+ ///
+ /// Authentication mechanism used by AcseAuthenticator
+ ///
+ public enum AcseAuthenticationMechanism
+ {
+ /** Neither ACSE nor TLS authentication used */
+ ACSE_AUTH_NONE = 0,
+
+ /** Use ACSE password for client authentication */
+ ACSE_AUTH_PASSWORD = 1,
+
+ /** Use ACSE certificate for client authentication */
+ ACSE_AUTH_CERTIFICATE = 2,
+
+ /** Use TLS certificate for client authentication */
+ ACSE_AUTH_TLS = 3
+ }
+
+
+ public class AcseAuthenticationParameter
+ {
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern IntPtr AcseAuthenticationParameter_create();
+
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern void AcseAuthenticationParameter_setAuthMechanism(IntPtr self, int mechanism);
+
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern void AcseAuthenticationParameter_setPassword(IntPtr self, string password);
+
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern int AcseAuthenticationParameter_getAuthMechanism(IntPtr self);
+
+ private IntPtr self = IntPtr.Zero;
+
+ public AcseAuthenticationParameter()
+ {
+ self = AcseAuthenticationParameter_create();
+ }
+
+ public AcseAuthenticationParameter(IntPtr self)
+ {
+ this.self = self;
+ }
+
+ public void SetAuthMechanism(AcseAuthenticationMechanism acseAuthenticationMechanism)
+ {
+ AcseAuthenticationParameter_setAuthMechanism(self,(int)acseAuthenticationMechanism);
+ }
+
+ public void SetPassword(string password)
+ {
+ AcseAuthenticationParameter_setPassword(self, password);
+ }
+
+ public AcseAuthenticationMechanism GetAuthMechanism()
+ {
+ return (AcseAuthenticationMechanism)AcseAuthenticationParameter_getAuthMechanism(self);
+ }
+ }
+
+ public class IsoApplicationReference
+ {
+ private IntPtr self = IntPtr.Zero;
+
+ public IsoApplicationReference(IntPtr self)
+ {
+ this.self= self;
+ }
+ }
+}
diff --git a/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs b/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs
index 8f321fce..27cf390d 100644
--- a/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs
+++ b/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs
@@ -25,7 +25,10 @@ using IEC61850.Model;
using IEC61850.TLS;
using System;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Data.Common;
using System.Runtime.InteropServices;
+using System.Security.Principal;
// IEC 61850 API for the libiec61850 .NET wrapper library
namespace IEC61850
@@ -1749,6 +1752,9 @@ namespace IEC61850
public class ClientConnection : IDisposable
{
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern IntPtr ClientConnection_getSecurityToken(IntPtr self);
+
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientConnection_getPeerAddress(IntPtr self);
@@ -1772,6 +1778,31 @@ namespace IEC61850
this.self = ClientConnection_claimOwnership(self);
}
+ ///
+ /// Get the security token associated with this connection
+ /// The security token is an opaque handle that is associated with the connection.It is provided by the
+ /// authenticator (if one is present). If no security token is used then this function returns NULL
+ ///
+ /// the security token or NULL
+ public object GetSecurityToken()
+ {
+ lock (this)
+ {
+ if (self != IntPtr.Zero)
+ {
+ IntPtr token = ClientConnection_getSecurityToken(self);
+
+ if (token != IntPtr.Zero)
+ {
+ GCHandle handle = GCHandle.FromIntPtr(token);
+ return handle as object;
+ }
+ }
+ }
+
+ return null;
+ }
+
public string GetPeerAddress()
{
lock (this)
@@ -2611,6 +2642,29 @@ namespace IEC61850
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void IedServer_SVCBEventHandler(IntPtr svcb, int eventType, IntPtr parameter);
+ ///
+ /// set the authenticator for this server
+ /// This function sets a user specified authenticator that is used to identify and authenticate clients that
+ /// wants to connect.The authenticator is called on each connection attempt.Depending on the return value
+ /// connections are accepted.
+ ///
+ /// the instance of IedServer to operate on.
+ /// the user provided authenticator callback
+ /// user provided parameter that is passed to the authenticator
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern void IedServer_setAuthenticator(IntPtr self, IedServer_AcseAuthenticator authenticator, IntPtr authenticatorParameter);
+
+ ///
+ /// Callback function to authenticate a client
+ ///
+ /// user provided parameter - set when user registers the authenticator
+ /// the authentication parameters provided by the client
+ /// pointer where to store an application specific security token - can be ignored if not used.
+ /// ISO application reference (ap-title + ae-qualifier)
+ /// true if client connection is accepted, false otherwise
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ private delegate bool IedServer_AcseAuthenticator(IntPtr parameter, IntPtr authParameter, IntPtr securityToken, IntPtr appReference);
+
///
/// callback handler to control client read access to data attributes
/// User provided callback function to control MMS client read access to IEC 61850
@@ -3166,7 +3220,6 @@ namespace IEC61850
IedServer_setSVCBHandler(self, sampledValuesControlBlock.Self, internalSVCBEventHandler, GCHandle.ToIntPtr(info.handle));
}
-
private void InternalSVCBEventHandlerImplementation(IntPtr svcb, int eventType, IntPtr parameter)
{
GCHandle handle = GCHandle.FromIntPtr(parameter);
@@ -3177,6 +3230,38 @@ namespace IEC61850
info.sVCBEventHandler(info.sampledValuesControlBlock, (SMVEvent)eventType, info.svcHandlerParameter);
}
+ //TODO -> Add appReference
+ public delegate bool AcseAuthenticatorHandler(object parameter, AcseAuthenticationParameter authParameter, object securityToken, IsoApplicationReference isoApplicationReference);
+
+ private AcseAuthenticatorHandler acseAuthenticatorHandler = null;
+ private object acseAuthenticatorHandlerParameter = null;
+ private IedServer_AcseAuthenticator iedServer_AcseAuthenticator = null;
+
+ public void SetAuthenticator(AcseAuthenticatorHandler acseAuthenticatorHandler, object acseAuthenticatorHandlerParameter)
+ {
+ this.acseAuthenticatorHandler = acseAuthenticatorHandler;
+ this.acseAuthenticatorHandlerParameter= acseAuthenticatorHandlerParameter;
+
+ if(iedServer_AcseAuthenticator == null)
+ {
+ iedServer_AcseAuthenticator = new IedServer_AcseAuthenticator(InternalAcseAuthenticator);
+ IedServer_setAuthenticator(self, iedServer_AcseAuthenticator, IntPtr.Zero);
+ }
+ }
+
+ private bool InternalAcseAuthenticator(IntPtr parameter, IntPtr authParameter, IntPtr securityToken, IntPtr appReference)
+ {
+ if(acseAuthenticatorHandler != null && authParameter != IntPtr.Zero && appReference != IntPtr.Zero)
+ {
+ AcseAuthenticationParameter acseAuthenticationParameter = new AcseAuthenticationParameter(authParameter);
+ IsoApplicationReference isoApplicationReference = new IsoApplicationReference(appReference);
+ GCHandle token = GCHandle.FromIntPtr(securityToken);
+ return acseAuthenticatorHandler(acseAuthenticatorHandlerParameter, acseAuthenticationParameter, token as object, isoApplicationReference);
+ }
+
+ return false;
+ }
+
public delegate MmsDataAccessError ReadAccessHandler(LogicalDevice ld, LogicalNode ln, DataObject dataObject, FunctionalConstraint fc, ClientConnection connection, object parameter);
private ReadAccessHandler readAccessHandler = null;
diff --git a/dotnet/server_example_access_control/Program.cs b/dotnet/server_example_access_control/Program.cs
index 2e6784e1..ac67dbef 100644
--- a/dotnet/server_example_access_control/Program.cs
+++ b/dotnet/server_example_access_control/Program.cs
@@ -17,6 +17,7 @@ using IEC61850.Client;
using ReportControlBlock = IEC61850.Server.ReportControlBlock;
using IEC61850.Model;
using System.Data.Common;
+using IEC61850;
namespace server_access_control
{
@@ -142,12 +143,23 @@ namespace server_access_control
/* Install handler to control access to control blocks (RCBs, LCBs, GoCBs, SVCBs, SGCBs)*/
bool ControlBlockAccessCallBack(object parameter, ClientConnection connection, ACSIClass acsiClass, LogicalDevice ld, LogicalNode ln, string objectName, string subObjectName, ControlBlockAccessType accessType)
{
+ string password = parameter as string;
+ object securityToken = connection.GetSecurityToken();
+
+ if(securityToken != null)
+ {
+ if ((securityToken as string == password))
+ Console.WriteLine("Correct securityToken");
+ else
+ Console.WriteLine("Incorrect securityToken");
+ }
+
Console.WriteLine(acsiClass.ToString() + " "+ accessType.ToString() + " access " + ld.GetName() + ln.GetName() +"/"+ objectName + "." + subObjectName + "\n");
return true;
}
- iedServer.SetControlBlockAccessHandler(ControlBlockAccessCallBack, iedServer);
+ iedServer.SetControlBlockAccessHandler(ControlBlockAccessCallBack, "securityToken_password");
/* By default access to variables with FC=DC and FC=CF is not allowed.
* This allow to write to simpleIOGenericIO/GGIO1.NamPlt.vendor variable used
@@ -332,6 +344,22 @@ namespace server_access_control
iedServer.SetSVCBHandler(sVCBEventHandler, sampledValuesControlBlock_1, null);
iedServer.SetSVCBHandler(sVCBEventHandler, sampledValuesControlBlock_2, null);
+
+ bool clientAuthenticator (object parameter, AcseAuthenticationParameter authParameter, object securityToken, IsoApplicationReference isoApplicationReference)
+ {
+ Console.WriteLine("ACSE Authenticator:\n");
+
+ IEC61850.AcseAuthenticationMechanism acseAuthenticationMechanism = authParameter.GetAuthMechanism();
+
+ if (acseAuthenticationMechanism == IEC61850.AcseAuthenticationMechanism.ACSE_AUTH_PASSWORD)
+ {
+
+ }
+ return false;
+ }
+
+ iedServer.SetAuthenticator(clientAuthenticator, null);
+
iedServer.Start(102);
if (iedServer.IsRunning())
diff --git a/examples/iec61850_client_example5/client_example5.c b/examples/iec61850_client_example5/client_example5.c
index e5bb22b7..973057a7 100644
--- a/examples/iec61850_client_example5/client_example5.c
+++ b/examples/iec61850_client_example5/client_example5.c
@@ -84,6 +84,8 @@ main(int argc, char** argv)
printf("Failed to connect to %s:%i\n", hostname, tcpPort);
}
+ while (true);
+
IedConnection_destroy(con);
AcseAuthenticationParameter_destroy(auth);
diff --git a/src/mms/inc/iso_connection_parameters.h b/src/mms/inc/iso_connection_parameters.h
index cc443daf..af5a3db0 100644
--- a/src/mms/inc/iso_connection_parameters.h
+++ b/src/mms/inc/iso_connection_parameters.h
@@ -91,6 +91,9 @@ AcseAuthenticationParameter_destroy(AcseAuthenticationParameter self);
LIB61850_API void
AcseAuthenticationParameter_setAuthMechanism(AcseAuthenticationParameter self, AcseAuthenticationMechanism mechanism);
+LIB61850_API AcseAuthenticationMechanism
+AcseAuthenticationParameter_getAuthMechanism(AcseAuthenticationParameter self);
+
LIB61850_API void
AcseAuthenticationParameter_setPassword(AcseAuthenticationParameter self, char* password);
diff --git a/src/mms/iso_common/iso_connection_parameters.c b/src/mms/iso_common/iso_connection_parameters.c
index 858def8d..2478db6e 100644
--- a/src/mms/iso_common/iso_connection_parameters.c
+++ b/src/mms/iso_common/iso_connection_parameters.c
@@ -63,6 +63,12 @@ AcseAuthenticationParameter_setAuthMechanism(AcseAuthenticationParameter self, A
self->mechanism = mechanism;
}
+AcseAuthenticationMechanism
+AcseAuthenticationParameter_getAuthMechanism(AcseAuthenticationParameter self)
+{
+ return self->mechanism;
+}
+
IsoConnectionParameters
IsoConnectionParameters_create()
{