Authentifizierung, Aushandlung der unterstützten Dienste und optionale Kommunikationsparameter

Dieses Beispiel zeigt, wie ein Klartext-Kennwort zur Authentifizierung der Verbindung in einer TwinCAT IEC 61850 Client- oder Server-Applikation aktiviert und konfiguriert werden kann. Außerdem wird in diesem Beispiel gezeigt, wie die Server-Applikation den Authentifizierungsvorgang selbst, zur Laufzeit steuern kann. D.h. in Abhängigkeit von dem empfangenen Kennwort kann die Applikation die Verbindung akzeptieren oder ablehnen. Ferner wird in diesem Beispiel gezeigt wie die vom IEC 61850 Server unterstützten Dienste und Parameter in der TwinCAT Client- und Server-Applikation aktiviert und konfiguriert werden. Das Beispiel zeigt auch wie der Server die Aushandlung der unterstützten Dienste und Parameter selbst zur Laufzeit steuern kann. Die TwinCAT IEC 61850 Server-Applikation kann z.B. abhängig vom empfangenen Kennwort die vom Client vorgeschlagenen Dienste und/oder Parameter ablehnen und so den Zugriff auf diese Dienste oder Parameter für bestimmte Verbindungen oder Benutzer einschränken. Wenn Sie eine ältere Version des TwinCAT IEC 61850 Telecontrol Configurators verwenden, dann werden dort, die in diesem Beispiel vorgestellten Funktionalitäten möglicherweise noch nicht unterstützt. Um dieses Beispiel fehlerfrei übersetzen und testen zu können benötigen Sie eine neuere Version des TF6510 IEC 61850 Telecontrol.

Systemvoraussetzung

TF6510 IEC 61850 Telecontrol v3.2.98.0 oder neuer

Download TwinCAT XAE Project (*.zip): Sample31.zip

Allgemeine Information zu diesem Beispielprojekt

Das Beispiel besteht aus zwei separaten TwinCAT IEC 61850 Projekten. Nach dem Auspacken des Zip-Archives finden Sie im Unterordner \Client\Sample31 ein TwinCAT IEC 61850 Client-Projekt und im Unterordner \Server\Sample31 ein TwinCAT IEC 61850 Server-Projekt. Beide Projekte sind aufeinander abgestimmt, nur die IP-Adresse des Servers muss im Code der beiden Projekte angepasst werden. Der Client wird zum Server eine Verbindung aufbauen, wenn Sie die Projekte auf zwei per LAN verbundene TwinCAT-Zielsysteme runterladen, aktivieren und starten.

Das Client – Basis Beispielprojekt und Server – Basis Beispielprojekt dienen als Grundlage für das Beispielprojekt.

Aktivierung und Konfiguration der Authentifizierungsfunktion im TwinCAT Telecontrol Configurator

In der einfachsten Variante kann die Authentifizierungsfunktion bereits im TwinCAT Telecontrol Configurator aktiviert werden. Die dafür nötigen Einstellungen befinden sich auf dem Konfigurationsdialog des IED-Gerätes. Stellen Sie bitte wie im Bild unten bei dem Parameter: Authentication mode den Wert: Password ein.

Authentifizierung, Aushandlung der unterstützten Dienste und optionale Kommunikationsparameter 1:

Die IEC 61850 Client- bzw. Server-Projekt-Codegenerierung erzeugt den nötigen Code zur Aktivierung der Authentifizierungsfunktion und konfiguriert dort ein Standard-Kennwort mit dem Wert: „PASSWORD“ und einen Standard-Mechanismus mit dem Namen: „2.2.3.1“. Das Bit 0 der Protokolleinstellung: „nRequirements“ aktiviert die Authentifizierungsfunktion.

Standard-Authentifizierungsparameter im generierten TwinCAT IEC 61850 Projekt

Namensraum: TcTelecontrol

Typ: Globale Variablenliste (GVL)

Client-Projekt:

Authentifizierung, Aushandlung der unterstützten Dienste und optionale Kommunikationsparameter 2:

Server-Projekt:

Authentifizierung, Aushandlung der unterstützten Dienste und optionale Kommunikationsparameter 3:

Die Standardwerte können nur im generierten SPS-Code und nicht im TwinCAT Telecontrol Configurator angepasst werden, da das Authentifizierungs-Kennwort und der Mechanismus-Name in der SCL-Datei nicht gespeichert werden können. Zurzeit unterstützt die TwinCAT IEC 61850 Implementierung nur die in der SCL definierte Authentifizierungsmethode „Password“. Andere Authentifizierungsmethoden „weak“, „strong“ oder „certificate“ werden nicht unterstützt. Sie können aber mithilfe von TLS die komplette Client-Server-Kommunikation verschlüsseln. Das Beispiel hierzu finden Sie hier: TLS - Sichere Client-Server-Kommunikation mit Hilfe von Zertifikaten oder PSK.

Unilateraler vs. mutualer Authentifizierungsmodus

Der unilateraler Authentifizierungsmodus (Ein-Weg-Authentifizierung) ist der Standard-Modus bei der IEC 61850 Authentifizierung und wird auch von den meisten Geräten unterstützt. Der mutuale Authentifizierungsmodus (Zwei-Weg-Authentifizierung) ist eher unüblich. Bei der unilateralen Authentifizierung wird das Kennwort nur in eine Richtung, vom Client zum Server gesendet. Der Server verifiziert das Kennwort und bei Erfolg wird die Verbindung erhalten (akzeptiert) oder bei Fehler geschlossen (abgelehnt). Bei der mutualen Authentifizierung verifizieren beide Kommunikationspartner jeweils das Kennwort des anderen. Zuerst verifiziert der Server das empfangene Kennwort des Clients. Bei Erfolg sendet der Server ebenfalls ein Kennwort als Antwort zum Client zurück. Der Client verifiziert auch das vom Server empfangene Kennwort und bei Erfolg bleibt die Verbindung erhalten (akzeptiert) oder bei Fehler geschlossen (abgelehnt). Der unilaterale Authentifizierungsmodus ist in der TwinCAT IEC 61850 Implementierung standardmäßig konfiguriert.

Konfiguration der optionalen Client- und Server-Kommunikationsparameter

Bei einigen Kommunikationsparametern in den Protokolleinstellungen handelt es sich um optionale Parameter. Es ist nicht unbedingt erforderlich, dass diese Parameterwerte übertragen werden. Trotzdem kann es vorkommen, dass fehlende optionale Kommunikationsparameter zum Verbindungsabbruch oder Kommunikationsfehler führen. Oft wird auch wegen fehlender optionaler Parameter der Verbindungswunsch von dem anderen Kommunikationspartner abgelehnt. Es gibt auch Geräte, die auf den Empfang der optionalen Parameter mit einem Verbindungsabbruch reagieren. In solchen Fällen können Sie die Protokolleinstellungen anpassen und die Übertagung der optionalen Kommunikationsparameter entsprechend den Anforderungen aktivieren oder deaktivieren. Passen Sie die Protokolleinstellungen in der globalen Variablenliste „TcTelecontrol“ des Server- oder Client-Projekts an. In den hier beschriebenen Beispielprojekten (Server und Client) wird die Übertragung folgender optionaler Parameter aktiviert:

Der Wert: 0 (null) ist bei diesen Parametern ein gültiger Wert und dieser Wert wird auch übertragen. Der Wert: 16#FFFFFFFF konfiguriert einen Parameter als optional und in diesem Fall wird kein Wert übertragen.

Einfache Authentifizierung mit einem Hauptkennwort

In der einfachsten Variante der Authentifizierung akzeptiert der Server nur ein einzelnes Authentifizierungs-Kennwort. In diesem Fall müssen Sie nur das bereits generierte Standard-Kennwort: „PASSWORD“ in der erstellten Server- bzw. Client-Applikation anpassen. Für diese Funktionalität werden erstmal keine weiteren Änderungen oder Erweiterungen des generierten SPS-Codes benötigt.

Dieses eine Kennwort kann auch als Hauptkennwort bezeichnet werden. Jeder Client, der dieses Kennwort verwendet, kann sich mit dem Server erfolgreich verbinden. Wenn Ihre Server-Implementierung mehrere Verbindungen zulässt, dann können auch mehrere Clients mit demselben Hauptkennwort eine Verbindung zum Server aufbauen. Im dokumentierten Server-Beispiel lautet das Hauptkennwort: „GeneralPass“. Dieses Kennwort kann über die Protokolleinstellungen des Servers konfiguriert werden. Im Beispielcode finden Sie den Parameterwert in der globalen Variablenliste: „TcTelecontrol“ (siehe Bild unten). Die wichtigen/relevanten Codeabschnitte sind in Fettschrift hervorgehoben.

Namensraum: TcTelecontrol

Typ: Globale Variablenliste (GVL)

VAR_GLOBAL

    (*…*)

    (* IED data model *)
    fbIED: FB_IED_IED;
    bMutual: BOOL:=FALSE;
    (* Server container *)
    fbIEDServer: FB_iec61850ServerClass:=(
        ipIED:=fbIED,
        settings:=( bEnable:=TRUE,
                    sLocalHost:='127.0.0.1',
                    sAuthent_Value:='GeneralPass',
                    sMechanism_Name:='2.2.3.1',
                    nRequirements:=16#01,
                    eAcse_Authent:=SEL(bMutual, E_AcseAuthentication.Unilateral, E_AcseAuthentication.Mutual),
                    sResponding_Value:='RespondingPass',
                    nCalled_AP_InvID:=0,
                    nCalled_AE_InvID:=0,
                    nCalling_AP_InvID:=0,
                    nCalling_AE_InvID:=0
));
    (* Server connections *)
    fbIEDServerSession1: FB_IEDServerSession:=(
        fbConnection:=(
            ipServer:=fbIEDServer,
            settings:=( bEnable:=TRUE,
                        sAuthent_Value:='Session1Pass')));

    (*…*)

END_VAR

Authentifizierung mit einem verbindungsspezifischen Kennwort

In der TwinCAT IEC 61850 Server-Implementierung kann optional, neben dem Hauptkennwort, zur jeder verfügbaren Server-Verbindung noch ein zusätzliches verbindungsspezifisches Kennwort konfiguriert werden. Dieses Kennwort kann über die Konfigurationseinstellungen der Server-Verbindung (z. B. „fbIEDServerSession1.fbConnection.settings“) konfiguriert werden. Der Server in unserem oberen Beispiel akzeptiert nur eine Verbindung. Das konfigurierte verbindungsspezifische Kennwort lautet „Session1Pass“. Der Server akzeptiert die Server-Verbindung nur dann, wenn der Client über diese Server-Verbindung entweder das Hauptkennwort oder das konfigurierte verbindungsspezifische Kennwort sendet (im Beispiel oben „GeneralPass“ oder „Session1Pass“). Beim Server mit nur einer konfigurierten (zulässigen) Server-Verbindung können Sie auf diese Weise ein zweites, dem Hauptkennwort gleichwertiges Kennwort zuweisen und wie ein Hauptkennwort verwenden.

Während des Verbindungsaufbaus auf der TCP/IP-Ebene wird im Standardfall einem Client, der sich mit dem Server verbinden möchte, eine freie (nicht belegte) Server-Verbindungsinstanz zugewiesen. Es gibt aber die Möglichkeit, einen Client an eine bestimmte Server-Verbindung über die IP-Adresse des Clients zu binden. Im unteren Beispiel binden wir einen Client mit der IP-Adresse „192.168.10.140“ an die Verbindungsinstanz „fbIEDServerSession1“ und einen weiteren Client mit der IP-Adresse „192.168.10.160“ an die Verbindungsinstanz „fbIEDServerSession2“.

Ein Client mit der IP-Adresse: „192.168.10.140“ kann sich nur mit der Instanz „fbIEDServerSession1“ verbinden, wenn er das Hauptkennwort oder das Kennwort „Session1Pass“ sendet. Der Client mit der IP-Adresse „192.168.10.160“ kann sich nur mit der Instanz „fbIEDServerSession2“ verbinden, wenn er das Hauptkennwort oder das Kennwort „Session2Pass“ sendet.

Namensraum: TcTelecontrol

Typ: Globale Variablenliste (GVL)

VAR_GLOBAL

    (*…*)

    fbIEDServerSession1: FB_IEDServerSession:=(
        fbConnection:=(
            ipServer:=fbIEDServer,
            settings:=(bEnable:=TRUE,
                       sAuthent_Value:='Session1Pass',
                       sAcceptHost:='192.168.10.140',
                       eAccept:=E_SocketAcceptMode.eACCEPT_SEL_HOST
)));

    fbIEDServerSession2: FB_IEDServerSession:=(
        fbConnection:=(
            ipServer:=fbIEDServer,
            settings:=(bEnable:=TRUE,
                       sAuthent_Value:='Session2Pass',
                       sAcceptHost:='192.168.10.160',
                       eAccept:=E_SocketAcceptMode.eACCEPT_SEL_HOST
)));

    (*…*)

END_VAR

Authentifizierung mit mehreren weiteren Kennwörtern

Wenn der Server mehrere Kennwörter akzeptieren, oder der Client nicht nur mit einem Kennwort, sondern mit mehreren unterschiedlichen Kennwörtern (mal mit dem einen mal mit dem anderen) die Verbindung zum Server aufbauen soll dann müssen Sie den generierten Code um einige wenige Zeilen selbst erweitern.

Um die unterschiedlichen Möglichkeiten der Authentifizierung präsentieren zu können wurden in der Array-Variablen „passList“ des Client-Beispielprojekts sechs verschiedene Beispielkennwörter definiert:

Die Variable „passIndex“ selektiert das Kennwort, welches der Client beim nächsten Verbindungsaufbau verwenden soll (siehe weiter unten). Die globale Variable „bMutual“ kann verwendet werden, um zwischen den zwei Authentifizierungsmodi unilateral und mutual zu wechseln. Standardmäßig ist im Beispiel der Authentifizierungsmodus unilateral konfiguriert.

Namensraum: TcTelecontrol

Typ: Globale Variablenliste (GVL)

VAR_GLOBAL

    (*…*)

    (* IED data model *)
    fbIED: FB_IED_IED;
    bMutual: BOOL:=FALSE;
    passIndex: DINT(0..5):=0;
    (* Authentication passwords *)
    passList: ARRAY[0..5] OF STRING:=['GeneralPass',
                                    'Session1Pass',
                                    'AnotherPass',
                                    'MorePass',
                                    'FurtherPass',
                                    'UnknownPass'];
    (* Client connection *)
    fbIEDClient : FB_IEDClient:=(
        fbConnection:=( ipIED:=fbIED,
                        settings:=( sRemoteHost:='127.0.0.1',
                                    sAuthent_Value:=passList[LIMIT(0, passIndex, 5)],
                                    sMechanism_Name:='2.2.3.1',
                                    nRequirements:=16#01,
                                    eAcse_Authent:=SEL(bMutual, E_AcseAuthentication.Unilateral, E_AcseAuthentication.Mutual),
                                    sResponding_Value:='RespondingPass',
                                    nCalled_AP_InvID:=0,
                                    nCalled_AE_InvID:=0,
                                    nCalling_AP_InvID:=0,
                                    nCalling_AE_InvID:=0)));


    (*…*)

END_VAR

Sowohl in der Client-, als auch in der Server-Beispielapplikation finden Sie einige zusätzliche Variablen. Diese Variablen, wie z. B. „bAccepted“, „eAareResult“, „eAareDiagnostic“ oder „sPassword“ können zur optischen Kontrolle im Online-Mode oder zu Diagnosezwecken verwendet werden. Die Werte dieser Variablen werden z. B. beim Client-Beispielprojekt in dem Implementierungscode der Ereignisbehandlungsroutine „OnAssociateCnf“ des Funktionsbausteins „FB_IEDClient“ gesetzt. Im Server-Beispielprojekt werden diese Werte im Implementierungscode der Ereignisbehandlungsroutine „OnAssociateInd“ des Funktionsbausteins „FB_IEDServerSession“ gesetzt.

FUNCTION_BLOCK FB_IEDClient IMPLEMENTS I_ScsmAbortIndEventSink,
                    I_ScsmAssociateCnfEventSink,
                    I_ScsmGetServerDirectoryCnfEventSink,
                    I_ScsmGetLogicalDeviceDirectoryCnfEventSink,
                    I_ScsmGetLogicalNodeDirectoryCnfEventSink,
                    I_ScsmGetDataValuesCnfEventSink,
                    I_ScsmSetDataValuesCnfEventSink,
                    I_ScsmReportIndEventSink,
                    I_ScsmControlCnfEventSink,
                    I_ScsmLastApplErrorIndEventSink,
                    I_ScsmCommandTerminationIndEventSink
VAR_INPUT
    fbConnection : FB_iec61850ClientClass:=(ipAbortInd:=THIS^,
                        ipAssociateCnf:=THIS^,
                        ipGetServerDirectoryCnf:=THIS^,
                        ipGetLogicalDeviceDirectoryCnf:=THIS^,
                        ipGetLogicalNodeDirectoryCnf:=THIS^,
                        ipGetDataValuesCnf:=THIS^,
                        ipSetDataValuesCnf:=THIS^,
                        ipReportInd:=THIS^,
                        ipControlCnf:=THIS^,
                        ipLastApplErrorInd:=THIS^,
                        ipCommandTerminationInd:=THIS^);
END_VAR
VAR

    (*…*)

    bAccepted       : BOOL:=FALSE;
    sPassword       : STRING:='';
    sMechanismName  : STRING:='';
    sRespondingPass : STRING:='';
    eAareResult     : E_ACSE_AareResult:=E_ACSE_AareResult.Accepted;
    eAareDiagnostic : E_ACSE_AareDiagnostic:=E_ACSE_AareDiagnostic.Null;
    eAbrtDiagnostic : E_ACSE_AbrtDiagnostic:=E_ACSE_AbrtDiagnostic.Null;

    (*…*)

END_VAR

    (*…*)

CASE state OF
    0:
        IF _bAbort THEN
            _bAbort:= FALSE;
            bSuccess:= fbConnection.AbortReq(ipReason:=fbAbortReason, ipSink:=0, ipResult=>ipResult);
            state:= SEL(bSuccess, 100, 1);
        ELSIF eState = E_AsyncEnvironmentState.Idle AND (_bConnect OR _bReconnect) THEN
            _bConnect:= FALSE;
            bGetAllServerValues:= SEL(_bReadAllData, bGetAllServerValues, TRUE);

            fbConnection.settings.eAcse_Authent:= SEL(TcTelecontrol.bMutual, E_AcseAuthentication.Unilateral, E_AcseAuthentication.Mutual);
            fbConnection.settings.sAuthent_Value:= TcTelecontrol.passList[LIMIT(0, passIndex, 5)];

            bSuccess:= fbConnection.AssociateReq(ipSink:=0, ipResult=>ipResult);
            state:= SEL(bSuccess, 100, 1);

    (*…*)

END_CASE

Steuerung des Authentifizierungsprozesses in der Server-Applikation

Der Server in der Standardimplementierung verifiziert intern automatisch den Mechanismus-Namen und das empfangene Kennwort. Bei einem positiven Ergebnis dieser Überprüfung wird die Verbindung vom Server akzeptiert (behalten) und bei einem negativen Ergebnis abgewiesen (geschlossen). Diese Funktionalität benötigt keine besonderen Erweiterungen des automatisch generierten SPS-Codes. Es gibt aber auch die Möglichkeit den Authentifizierungsprozess zur Laufzeit in der Server-Applikation aktiv zu steuern. D.h. der Server kann selbst (spontan) entscheiden, ob eine Verbindung akzeptiert oder abgewiesen wird. In diesem Fall, wenn die Bedingungen es zulassen, kann eine, durch interne Verifizierung abgewiesene Verbindung trotzdem akzeptiert und eine intern akzeptierte Verbindung doch noch abgewiesen werden.

Als Beispiel für den unilateralen Authentifizierungsmodus mit weiteren Kennwörtern ist in dem Server-Beispiel folgendes Verhalten implementiert:

Durch einen zusätzlichen SPS-Code in der Ereignisbehandlungsroutine „OnAssciateInd“ kann die Server-Applikation das Ergebnis der internen Verifizierung nachträglich verändern, dieses wird im Server-Beispiel genutzt. Die Werte der zusätzlichen lokalen Variablen des Funktionsbausteins „FB_IEDServerSession“ werden in dem Implementierungscode der Ereignisbehandlungsroutine: „OnAssociateInd“ gesetzt.

FUNCTION_BLOCK FB_IEDServerSession IMPLEMENTS I_ScsmAbortIndEventSink, I_ScsmAssociateIndEventSink, I_ScsmReleaseIndEventSink
VAR_INPUT
    fbConnection : FB_iec61850ConnectionClass:=(ipAbortInd:=THIS^,
                                        ipAssociateInd:=THIS^,
                                        ipReleaseInd:=THIS^);
END_VAR
VAR

    (*…*)

    bAccepted       : BOOL:=FALSE;
    sPassword       : STRING:='';
    sMechanismName  : STRING:='';
    sRespondingPass : STRING:='';
    eAareResult     : E_ACSE_AareResult:=E_ACSE_AareResult.Accepted;
    eAareDiagnostic : E_ACSE_AareDiagnostic:=E_ACSE_AareDiagnostic.Null;
    eAbrtDiagnostic : E_ACSE_AbrtDiagnostic:=E_ACSE_AbrtDiagnostic.Null;


    (*…*)

END_VAR

Die boolesche Variable „bAccepted“ wird „TRUE“ sein, wenn die interne Verifizierung die Authentifizierungsdaten und damit auch die Verbindung akzeptiert. Diese Variable wird aber auch „TRUE“ sein, wenn die Server-Authentifizierungsfunktion in den Protokolleinstellungen nicht aktiviert wurde.

Benutzerdefinierte OnAssociateInd-Ereignisbehandlungsroutine des Servers

Das Ergebnis der internen Verifizierung kann nachträglich nur beeinflusst werden, wenn die Authentifizierungsfunktion der beiden Kommunikationspartner aktiv ist und alle anderen Rahmenbedingungen (Kommunikationsparameter wie z. B. Mechanismus-Name und Kennwort) korrekt konfiguriert oder empfangen wurden. Die Server-Applikation kann über die Eingangsvariable „ipAA“ der Ereignisbehandlungsroutine „OnAssociateInd“ auf den Schnittstellenzeiger „ipAuthentication“ vom Typ I_ScsmAuthenticationClass zugreifen. Der Schnittstellenzeiger gehört zum Authentifizierungsobjekt, der auch intern die Verifizierung durchführt. Die interne Verifizierung wird vom Server bereits vor dem Aufruf der Ereignisbehandlungsroutine „OnAssociateInd“ durchgeführt. Zum Zeitpunkt des Methodenaufrufs steht das erste Ergebnis bereits fest. Der Schnittstellenzeiger „ipAuthentication“ bietet der Applikation Methoden an mit deren Hilfe das Ergebnis der Verifizierung abgefragt, eine durch die interne Verifizierung abgewiesene Verbindung trotzdem akzeptiert oder eine akzeptierte Verbindung doch abgelehnt werden kann. Eine durch interne Verifizierung bereits abgewiesene Verbindung kann nicht nochmal abgewiesen werden und eine durch interne Verifizierung akzeptierte Verbindung kann nicht erneut akzeptiert werden. Die Methodenaufrufe von „Accept“ oder „Reject“ werden in diesem Fall einen Rückgabewert „FALSE“ (Fehler) liefern.

METHOD OnAssociateInd : BOOL
VAR_INPUT
    ipAA     : I_ScsmAssociationClass;
END_VAR
VAR_OUTPUT
    ipResult : I_AsyncServiceResultClass;
END_VAR

(*…*)

bAccepted:= FALSE;
sMechanismName:= '';
sPassword:= '';
sRespondingPass:= '';
eAareResult:= E_ACSE_AareResult.Accepted;
eAareDiagnostic:= E_ACSE_AareDiagnostic.Null;
eAbrtDiagnostic:= E_ACSE_AbrtDiagnostic.Null;
IF (ipAA <> 0) AND_THEN (ipAA.ipAuthentication <> 0) THEN
    IF ipAA.ipAuthentication.GetVerifyResult(bAccepted=>bAccepted,
                            sMechanismName=>sMechanismName,
                            sPassword=>sPassword,
                            sRespondingPass=>sRespondingPass,
                            eResult=>eAareResult,
                            eDiagnostic=>eAareDiagnostic,
                            eAbrtDiagnostic=>eAbrtDiagnostic)
    THEN
        IF bAccepted THEN
            IF (sPassword = 'GeneralPass') THEN
                ;
            ELSIF (sPassword = 'Session1Pass') THEN
                bSuccess:= ipAA.ipAuthentication.Reject();
            ELSE
                ;
            END_IF
        ELSE
            IF (sPassword = 'AnotherPass') OR_ELSE (sPassword = 'MorePass') THEN
                bSuccess:= ipAA.ipAuthentication.Accept(sRespondingPass:='RespondingPass');
            ELSIF (sPassword = 'FurtherPass') THEN
                bSuccess:= ipAA.ipAuthentication.Accept(sRespondingPass:='InvalidRespondingPass');
            ELSIF (sPassword = 'UnknownPass') THEN
                ;
            ELSE
                ;
            END_IF
        END_IF
        ipAA.ipAuthentication.GetVerifyResult(bAccepted=>bAccepted,
                            sMechanismName=>sMechanismName,
                            sPassword=>sPassword,
                            sRespondingPass=>sRespondingPass,
                            eResult=>eAareResult,
                            eDiagnostic=>eAareDiagnostic,
                            eAbrtDiagnostic=>eAbrtDiagnostic);
    END_IF

    (* Negotiation example of max. number of outgoing called and calling services: *)
    ipAA.ipAuthentication.nNegotiatedMaxServOutCalled:= 5; (* Default: 10 *)
    ipAA.ipAuthentication.nNegotiatedMaxServOutCalling:= 5; (* Default: 10 *)

    (* Example of supported services negotiation: *)
    IF ipAA.ipAuthentication.ipNegotiatedServicesSupported <> 0 THEN
        (* Disable support for file services *)
        ipAA.ipAuthentication.ipNegotiatedServicesSupported.bFileClose:= FALSE;
        ipAA.ipAuthentication.ipNegotiatedServicesSupported.bFileDelete:= FALSE;
        ipAA.ipAuthentication.ipNegotiatedServicesSupported.bFileDirectory:= FALSE;
        ipAA.ipAuthentication.ipNegotiatedServicesSupported.bFileOpen:= FALSE;
        ipAA.ipAuthentication.ipNegotiatedServicesSupported.bFileRead:= FALSE;
        ipAA.ipAuthentication.ipNegotiatedServicesSupported.bFileRename:= FALSE;
        ipAA.ipAuthentication.ipNegotiatedServicesSupported.bObtainFile:= FALSE;
    END_IF
END_IF

(*…*)

OnAssociateInd:= fbConnection.AssociateRsp(ipResult=>ipResult);

In diesem Server-Beispiel wird mit dem Methodenaufruf „GetVerifyResult“ zuerst das Ergebnis der internen Verifizierung und einige Diagnoseinformationen ausgelesen. Danach wird die intern bereits akzeptierte Verbindung mit dem Kennwort „Session1Pass“ mit dem Methodenaufruf „Reject“ abgewiesen und die intern bereits abgelehnten Verbindungen mit den Kennwörtern „AnotherPass“, „MorePass“ und „FurtherPass“ mit dem Methodenaufruf „Accept“ doch noch akzeptiert. Zum Schluss wird das Verifizierungsergebnis erneut gelesen. Erst dann darf die Antwort an den Client mit dem Methodenaufruf „AssociateRsp“ gesendet werden.

Dynamische Aushandlung der unterstützten Server-Dienste und Parameter

In den meisten Anwendungsfällen können die vom Server unterstützten Dienste und Parameter über Protokolleinstellungen in der globalen Variablenliste „TcTelecontrol“ konfigurieren werden. Die dort gesetzten Einstellungen gelten dann für alle Verbindungen des Servers. D.h. alle Clients können mit dem Server maximal nur die Dienste aushandeln, die dort auch global für alle Verbindungen konfiguriert (aktiviert) wurden.

In einigen Anwendungsfällen kann aber erforderlich sein, dass je nach Client-Verbindung (z. B. abhängig von der IP-Adresse des Clients oder dem Authentifizierungs-Kennwort) unterschiedliche Server-Dienste und Parameter ausgehandelt werden sollen. Der Server könnte bei einer speziellen Client-Verbindung mehr Dienste zulassen/unterstützen und bei einer anderen Client-Verbindung weniger.

Die Ereignisbehandlungsroutine „OnAssociateInd“ kann verwendet werden um zur Laufzeit (verbindungsabhängig) die unterstützten Dienste und Parameter auszuhandeln. Über die Schnittstellenvariable „ipAA.ipAuthentication“ kann eine Server-Applikation auf das interne Ergebnis der ausgehandelten Dienste und Parameter zugreifen. Das Ergebnis kann zu diesem Zeitpunkt noch nach Bedarf manipuliert werden. Im Beispielcode oben wird die max. Anzahl der eingehenden und ausgehenden bestätigten Anfragen (MMS-Request) von Standardwert 10 auf 5 begrenzt und die Unterstützung aller MMS-Dateidienste deaktiviert. Erst dann wird das neue Ergebnis im Antworttelegramm an den Client zurückgeschickt.

Einfache Authentifizierung im mutualen Authentifizierungsmodus

Der mutuale Authentifizierungsmodus muss von beiden Kommunikationspartnern unterstützt werden und ist in der IEC 61850 eher unüblich. In diesem Modus sendet der Server ein Kennwort zum Client als Antwort zurück. Dieses Antwortkennwort ist bereits im Server-Beispielprojekt mit dem Wert „RespondingPass“ in der globalen Variablenliste „TcTelecontrol“ konfiguriert. Im Client-Beispielprojekt ist ebenfalls ein Kennwort „RespondingPass“ in der globalen Variablenliste „TcTelecontrol“ konfiguriert. Das ist das Kennwort, welches der Client als Antwort vom Server erwartet. Die interne Verifizierungsfunktion des Clients wird dieses Kennwort mit dem vom Server empfangenen Kennwort vergleichen. Beim Erfolg bleibt die Verbindung erhalten und beim Fehler wird sie wieder geschlossen. In der einfachsten Konfiguration müssen nur in den generierten Server- und Client-Beispielprojekten die Antwortkennwörter angepasst/konfiguriert werden und der mutuale Authentifizierungsmodus in den Protokolleinstellungen aktiviert werden. Ein zusätzlicher Code in den Ereignisbehandlungsroutinen „OnAssociateInd“ oder „OnAssociateCnf“ ist für die mutuale Authentifizierung in der Grundfunktion nicht notwendig.

Benutzerdefinierte OnAssociateCnf-Ereignisbehandlungsroutine des Clients

In dem mutualen Authentifizierungsmodus kann auch der Client, ähnlich wie der Server, den Authentifizierungsprozess aktiv zur Laufzeit steuern. Allerdings muss der Server das vom Client empfangene Kennwort bereits akzeptiert haben. Eine vom Server abgewiesene Verbindung (negative Antwort) kann auf der Client-Seite nicht mehr akzeptiert werden. Im unilateralen Modus ist es nicht erforderlich die Ereignisbehandlungsroutine „OnAssociateCnf“ zu implementieren. Die hier vorgestellte benutzerdefinierte Implementierung der Ereignisbehandlungsroutine „OnAssociateCnf“ ist nur im mutualen Authentifizierungsmodus sinnvoll.

Um die verschiedenen vorhandenen Möglichkeiten zu präsentieren, wurde im Beispiel folgendes Verhalten implementiert:

METHOD OnAssociateCnf
VAR_INPUT
    ipAA   : I_ScsmAssociationClass;
    eError : E_AcsiServiceError;
END_VAR
VAR
END_VAR
sLastAbortReason:= '';
sLastErrorResult:= '';

bAccepted:= FALSE;
sMechanismName:= '';
sPassword:= '';
sRespondingPass:= '';
eAareResult:= E_ACSE_AareResult.Accepted;
eAareDiagnostic:= E_ACSE_AareDiagnostic.Null;
eAbrtDiagnostic:= E_ACSE_AbrtDiagnostic.Null;
IF (ipAA <> 0) AND_THEN (ipAA.ipAuthentication <> 0) THEN
    IF ipAA.ipAuthentication.GetVerifyResult(bAccepted=>bAccepted,
                            sMechanismName=>sMechanismName,
                            sPassword=>sPassword,
                            sRespondingPass=>sRespondingPass,
                            eResult=>eAareResult,
                            eDiagnostic=>eAareDiagnostic,
                            eAbrtDiagnostic=>eAbrtDiagnostic)
    THEN
        IF bAccepted THEN
            IF (sPassword = 'GeneralPass')
            OR_ELSE (sPassword = 'AnotherPass') THEN
                ;
            ELSIF (sPassword = 'MorePass') THEN
                bSuccess:= ipAA.ipAuthentication.Reject();
            ELSE
                ;
            END_IF
        ELSE
            IF (sPassword = 'FurtherPass') THEN
                bSuccess:= ipAA.ipAuthentication.Accept(sRespondingPass:='RespondingPass');
            ELSE
                ;
            END_IF
        END_IF
        
        ipAA.ipAuthentication.GetVerifyResult(bAccepted=>bAccepted,
                            sMechanismName=>sMechanismName,
                            sPassword=>sPassword,
                            sRespondingPass=>sRespondingPass,
                            eResult=>eAareResult,
                            eDiagnostic=>eAareDiagnostic,
                            eAbrtDiagnostic=>eAbrtDiagnostic);
    ELSE
        ;
    END_IF
END_IF

Wie bei der bereits oben beschriebenen Ereignisbehandlungsroutine „OnAssociateInd“ des Servers kann auch die Client-Applikation über die Eingangsvariable „ipAA“ der Ereignisbehandlungsroutine „OnAssociateCnf“ auf den Schnittstellenzeiger „ipAuthentication“ vom Typ I_ScsmAuthenticationClass zugreifen. Mit dem Methodenaufruf „GetVerifyResult“ kann die Client-Applikation das Ergebnis der internen Verifizierung abfragen und beim Bedarf modifizieren.

Test

Um einen einfachen Test durchführen zu können muss zuerst die Netzwerkadresse (IPv4-Adresse) des TwinCAT IEC 61850 Servers im Server- und Client-Beispielprojekt angepasst werden. Wenn das Client- und Server-Beispielprojekt auf zwei TwinCAT-Zielsysteme runtergeladen und gestartet ist, dann wird der Client für die Authentifizierung das Kennwort „GeneralPass“ verwenden und eine Verbindung zum Server aufbauen. Das verwendete Kennwort wird in der globalen Variablenliste „TcTelecontrol“ des Client-Projekts mit Hilfe der Index-Variablen „passIndex“ aus dem Array „passList“ selektiert. Im Beispiel hat die Variable „passIndex“ den Initialwert „0“ und selektiert das erste Kennwort aus dem Array „passList“ mit dem Wert „GeneralPass“.

Als nächstes können Sie z. B. im Online-Mode (siehe Bild unten) die Kennwort-Index-Variable „passIndex“ auf den Wert „2“ und die boolesche Variable „fbIEDClient._bAbort“ auf den Wert „TRUE“ setzen.

Authentifizierung, Aushandlung der unterstützten Dienste und optionale Kommunikationsparameter 4:

Der Client wird die alte Verbindung zuerst schließen und dann eine neue mit dem Kennwort „AnotherPass“ aufbauen. Sie können auf diese Weise die verschiedenen im Beispiel implementierten Kennwörter ausprobieren. Beim „passIndex“ Wert 1 oder 5 wird z. B. der Server den Verbindungswunsch ablehnen. Bitte beachten Sie, dass einige Sekunden vergehen können, bis eine neue Verbindung aufgebaut werden kann. Standardmäßig ist die min. Zeit für einen erneuten Verbindungsaufbau in den Konfigurationseinstellungen „fbIEDClient.fbConnection.settings.tConnect“ auf 45 Sekunden gesetzt.