/// <summary> /// Constructor for AARE error. /// </summary> internal GXDLMSException(AssociationResult result, SourceDiagnostic diagnostic) : base("Connection is " + GetResult(result) + ". " + GetDiagnostic(diagnostic)) { Result = result; Diagnostic = (byte)diagnostic; HelpLink = "https://www.gurux.fi/Gurux.DLMS.ErrorCodes"; }
public void PrintMessageTest() { string source = "OK. Error <- here is an error!"; IOriginReader reader = new StringOrigin(source).GetReader(); for (int i = 0; i < 4; i++) { reader.MoveNext(); // 'OK. ' } ILocation locBeg = reader.CurrentLocation; for (int i = 0; i < 5; i++) { reader.MoveNext(); // 'Error' } ILocation locEnd = reader.CurrentLocation; IFragment fr = locBeg.Origin.MakeFragment(locBeg, locEnd); SourceDiagnostic sd = new SourceDiagnostic(); string res = sd.PrepareMessage("warning", fr, "found an error in your source"); sd.PrintMessage("warning", fr, "found an error in your source"); Assert.AreEqual(res, "warning at line 1:4 \"Error\" - found an error in your source"); }
/// <summary> /// Get diagnostic as a string. /// </summary> /// <param name="diagnostic"></param> /// <returns></returns> static string GetDiagnostic(SourceDiagnostic diagnostic) { if (diagnostic == SourceDiagnostic.NoReasonGiven) { return("No reason is given."); } if (diagnostic == SourceDiagnostic.ApplicationContextNameNotSupported) { return("The application context name is not supported."); } if (diagnostic == SourceDiagnostic.AuthenticationMechanismNameNotRecognised) { return("The authentication mechanism name is not recognized."); } if (diagnostic == SourceDiagnostic.AuthenticationMechanismNameReguired) { return("Authentication mechanism name is required."); } if (diagnostic == SourceDiagnostic.AuthenticationFailure) { return("Authentication failure."); } if (diagnostic == SourceDiagnostic.AuthenticationRequired) { return("Authentication is required."); } throw new InvalidOperationException(); }
///<summary> ///Parse AARQ request that client send and returns AARE request. /// </summary> ///<returns> ///Reply to the client. ///</returns> private void HandleAarqRequest(GXByteBuffer data, GXDLMSConnectionEventArgs connectionInfo) { AssociationResult result = AssociationResult.Accepted; Settings.CtoSChallenge = null; if (!Settings.UseCustomChallenge) { Settings.StoCChallenge = null; } // Reset settings for wrapper. if (Settings.InterfaceType == InterfaceType.WRAPPER) { Reset(true); } SourceDiagnostic diagnostic = GXAPDU.ParsePDU(Settings, Settings.Cipher, data, null); if (diagnostic != SourceDiagnostic.None) { result = AssociationResult.PermanentRejected; diagnostic = SourceDiagnostic.ApplicationContextNameNotSupported; InvalidConnection(connectionInfo); } else { diagnostic = ValidateAuthentication(Settings.Authentication, Settings.Password); if (diagnostic != SourceDiagnostic.None) { result = AssociationResult.PermanentRejected; InvalidConnection(connectionInfo); } else if (Settings.Authentication > Authentication.Low) { // If High authentication is used. if (!Settings.UseCustomChallenge) { Settings.StoCChallenge = GXSecure.GenerateChallenge(Settings.Authentication); } result = AssociationResult.Accepted; diagnostic = SourceDiagnostic.AuthenticationRequired; } else { Connected(connectionInfo); Settings.Connected = true; } } Settings.IsAuthenticationRequired = diagnostic == SourceDiagnostic.AuthenticationRequired; if (Settings.InterfaceType == Enums.InterfaceType.HDLC) { replyData.Set(GXCommon.LLCReplyBytes); } // Generate AARE packet. GXAPDU.GenerateAARE(Settings, replyData, result, diagnostic, Settings.Cipher, null); }
// System.IO.Path.GetTempFileName() private static void Main() { var args = Environment.GetCommandLineArgs(); var parameters = Parameters.parse(args); if (parameters == null) { printHelp(args); return; } if (parameters.outputFile == null) { parameters.outputFile = System.IO.Path.GetTempFileName(); } var inputFile = new FileOrigin(args[1]); try { var parseTree = CSTBuilder.Build(inputFile); Console.WriteLine(parseTree.ToString()); var backendFunctions = new Frontend().FromParseTreeToBackend(parseTree); var backend = new Backend.Backend(); string assemblyFile = parameters.outputFile; if (!parameters.onlyAssembly) { assemblyFile = System.IO.Path.GetTempFileName(); } generateAssemblyFile(assemblyFile, backend.FromFunctionsToNasm(backendFunctions)); if (!parameters.onlyAssembly) { // TODO invoke NASM (using parameters) var nasm = new Process(); nasm.StartInfo.FileName = "nasm"; // take $PATH into account nasm.StartInfo.Arguments = assemblyFile + " -o " + parameters.outputFile; nasm.Start(); nasm.WaitForExit(); } } catch (CSTBuilder.LexerFailure ex) { Console.WriteLine("Syntax error:"); var diagnostics = new SourceDiagnostic(); diagnostics.PrintFragmentInLine(ex.Fragment); } }
public void PrintFragmentInLineTest() { string source = "OK. Error in line 1\nLine 2."; IOriginReader reader = new StringOrigin(source).GetReader(); for (int i = 0; i < 4; i++) { reader.MoveNext(); // 'OK. ' } ILocation locBeg = reader.CurrentLocation; for (int i = 0; i < 5; i++) { reader.MoveNext(); // 'Error' } ILocation locEnd = reader.CurrentLocation; IFragment fr = locBeg.Origin.MakeFragment(locBeg, locEnd); SourceDiagnostic sd = new SourceDiagnostic(); sd.PrintFragmentInLine(fr); }
///<summary> ///Parse AARQ request that client send and returns AARE request. /// </summary> ///<returns> ///Reply to the client. ///</returns> private byte[][] HandleAarqRequest() { AssociationResult result = AssociationResult.Accepted; Settings.CtoSChallenge = null; if (!Settings.UseCustomChallenge) { Settings.StoCChallenge = null; } SourceDiagnostic diagnostic = GXAPDU.ParsePDU(Settings, Settings.Cipher, Reply.Data); if (diagnostic != SourceDiagnostic.None) { result = AssociationResult.PermanentRejected; diagnostic = SourceDiagnostic.ApplicationContextNameNotSupported; } else { // Check that user can access server. diagnostic = ValidateAuthentication(Settings.Authentication, Settings.Password); if (diagnostic != SourceDiagnostic.None) { result = AssociationResult.PermanentRejected; } else if (Settings.Authentication > Authentication.Low) { // If High authentication is used. Settings.StoCChallenge = GXSecure.GenerateChallenge(Settings.Authentication); result = AssociationResult.Accepted; diagnostic = SourceDiagnostic.AuthenticationRequired; } } // Generate AARE packet. GXByteBuffer buff = new GXByteBuffer(150); GXAPDU.GenerateAARE(Settings, buff, result, diagnostic, Settings.Cipher); return(GXDLMS.SplitPdu(Settings, Command.Aare, 0, buff, ErrorCode.Ok, DateTime.MinValue)[0]); }
/// <summary> /// Constructor for AARE error. /// </summary> internal GXDLMSException(AssociationResult result, SourceDiagnostic diagnostic) : base("Connection is " + GetResult(result) + ". " + GetDiagnostic(diagnostic)) { Result = result; Diagnostic = diagnostic; }
/// <summary> /// Constructor for AARE error. /// </summary> internal GXDLMSException(AssociationResult result, SourceDiagnostic diagnostic) : base("Connection is " + GetResult(result) + Environment.NewLine + GetDiagnostic(diagnostic)) { Result = result; Diagnostic = diagnostic; }
/// <summary> /// Get diagnostic as a string. /// </summary> /// <param name="diagnostic"></param> /// <returns></returns> static string GetDiagnostic(SourceDiagnostic diagnostic) { string str; switch (diagnostic) { case SourceDiagnostic.None: str = "None"; break; case SourceDiagnostic.NoReasonGiven: str = "No reason is given."; break; case SourceDiagnostic.ApplicationContextNameNotSupported: str = "The application context name is not supported."; break; case SourceDiagnostic.CallingApTitleNotRecognized: str = "Calling AP title not recognized."; break; case SourceDiagnostic.CallingApInvocationIdentifierNotRecognized: str = "The authentication mechanism name is not recognized."; break; case SourceDiagnostic.CallingAeQualifierNotRecognized: str = "Calling AE qualifier not recognized."; break; case SourceDiagnostic.CallingAeInvocationIdentifierNotRecognized: str = "Calling AE invocation identifier not recognized"; break; case SourceDiagnostic.CalledApTitleNotRecognized: str = "called AP title not recognized."; break; case SourceDiagnostic.CalledApInvocationIdentifierNotRecognized: str = "Called AP invocation identifier not recognized."; break; case SourceDiagnostic.CalledAeQualifierNotRecognized: str = "Called AE qualifier not recognized."; break; case SourceDiagnostic.CalledAeInvocationIdentifierNotRecognized: str = "Called AE invocation identifier not recognized."; break; case SourceDiagnostic.AuthenticationMechanismNameNotRecognised: str = "Authentication mechanism name not recognised."; break; case SourceDiagnostic.AuthenticationMechanismNameReguired: str = "Authentication mechanism name is required."; break; case SourceDiagnostic.AuthenticationFailure: str = "Authentication failure."; break; case SourceDiagnostic.AuthenticationRequired: str = "Authentication is required."; break; default: str = "Unknown diagnostic error."; break; } return(str); }
///<summary> ///Server generates AARE message. ///</summary> internal static void GenerateAARE(GXDLMSSettings settings, GXByteBuffer data, AssociationResult result, SourceDiagnostic diagnostic, GXICipher cipher) { int offset = data.Position; // Set AARE tag and length data.SetUInt8(((byte)BerType.Application | (byte)BerType.Constructed | (byte)PduType.ApplicationContextName)); //0x61 // Length is updated later. data.SetUInt8(0); GenerateApplicationContextName(settings, data, cipher); //Result data.SetUInt8((byte)BerType.Context | (byte)BerType.Constructed | (byte)BerType.Integer); //0xA2 data.SetUInt8(3); //len data.SetUInt8(BerType.Integer); //Tag //Choice for result (INTEGER, universal) data.SetUInt8(1); //Len data.SetUInt8((byte)result); //ResultValue //SourceDiagnostic data.SetUInt8(0xA3); data.SetUInt8(5); //len data.SetUInt8(0xA1); //Tag data.SetUInt8(3); //len data.SetUInt8(2); //Tag //Choice for result (INTEGER, universal) data.SetUInt8(1); //Len data.SetUInt8((byte)diagnostic); //diagnostic //SystemTitle if (cipher != null && (cipher.IsCiphered() || settings.Authentication == Authentication.HighGMAC)) { data.SetUInt8((byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.CalledApInvocationId); data.SetUInt8((byte)(2 + cipher.SystemTitle.Length)); data.SetUInt8((byte)BerType.OctetString); data.SetUInt8((byte)cipher.SystemTitle.Length); data.Set(cipher.SystemTitle); } if (result != AssociationResult.PermanentRejected && diagnostic == SourceDiagnostic.AuthenticationRequired) { //Add server ACSE-requirenents field component. data.SetUInt8(0x88); data.SetUInt8(0x02); //Len. data.SetUInt16(0x0780); //Add tag. data.SetUInt8(0x89); data.SetUInt8(0x07);//Len data.SetUInt8(0x60); data.SetUInt8(0x85); data.SetUInt8(0x74); data.SetUInt8(0x05); data.SetUInt8(0x08); data.SetUInt8(0x02); data.SetUInt8((byte)settings.Authentication); //Add tag. data.SetUInt8(0xAA); data.SetUInt8((byte)(2 + settings.StoCChallenge.Length));//Len data.SetUInt8((byte)BerType.Context); data.SetUInt8((byte)settings.StoCChallenge.Length); data.Set(settings.StoCChallenge); } //Add User Information //Tag 0xBE data.SetUInt8((byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.UserInformation); byte[] tmp = GetUserInformation(settings, cipher); data.SetUInt8((byte)(2 + tmp.Length)); //Coding the choice for user-information (Octet STRING, universal) data.SetUInt8(BerType.OctetString); //Length data.SetUInt8((byte)tmp.Length); data.Set(tmp); data.SetUInt8((UInt16)(offset + 1), (byte)(data.Size - offset - 2)); }
///<summary> ///Parse APDU. ///</summary> static internal SourceDiagnostic ParsePDU(GXDLMSSettings settings, GXICipher cipher, GXByteBuffer buff) { // Get AARE tag and length int tag = buff.GetUInt8(); if (settings.IsServer) { if (tag != ((byte)BerType.Application | (byte)BerType.Constructed | (byte)PduType.ProtocolVersion)) { throw new Exception("Invalid tag."); } } else { if (tag != ((byte)BerType.Application | (byte)BerType.Constructed | (byte)PduType.ApplicationContextName)) { throw new Exception("Invalid tag."); } } int len = buff.GetUInt8(); int size = buff.Size - buff.Position; if (len > size) { throw new Exception("Not enough data."); } AssociationResult resultComponent = AssociationResult.Accepted; SourceDiagnostic resultDiagnosticValue = SourceDiagnostic.None; while (buff.Position < buff.Size) { tag = buff.GetUInt8(); switch (tag) { case (byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.ApplicationContextName: //0xA1 if (!ParseApplicationContextName(settings, buff)) { throw new GXDLMSException(AssociationResult.PermanentRejected, SourceDiagnostic.ApplicationContextNameNotSupported); } break; case (byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.CalledApTitle: ////Result 0xA2 //Get len. if (buff.GetUInt8() != 3) { throw new Exception("Invalid tag."); } //Choice for result (INTEGER, universal) if (buff.GetUInt8() != (byte)BerType.Integer) { throw new Exception("Invalid tag."); } //Get len. if (buff.GetUInt8() != 1) { throw new Exception("Invalid tag."); } resultComponent = (AssociationResult)buff.GetUInt8(); break; case (byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.CalledAeQualifier: ////SourceDiagnostic 0xA3 len = buff.GetUInt8(); // ACSE service user tag. tag = buff.GetUInt8(); len = buff.GetUInt8(); // Result source diagnostic component. if (buff.GetUInt8() != (byte)BerType.Integer) { throw new Exception("Invalid tag."); } if (buff.GetUInt8() != 1) { throw new Exception("Invalid tag."); } resultDiagnosticValue = (SourceDiagnostic)buff.GetUInt8(); break; case (byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.CalledApInvocationId: ////Result 0xA4 //Get len. if (buff.GetUInt8() != 0xA) { throw new Exception("Invalid tag."); } //Choice for result (Universal, Octetstring type) if (buff.GetUInt8() != (byte)BerType.OctetString) { throw new Exception("Invalid tag."); } //responding-AP-title-field //Get len. len = buff.GetUInt8(); settings.SourceSystemTitle = new byte[len]; buff.Get(settings.SourceSystemTitle); break; //Client Challenge. case (byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.CallingApTitle: //0xA6 len = buff.GetUInt8(); tag = buff.GetUInt8(); len = buff.GetUInt8(); settings.SourceSystemTitle = new byte[len]; buff.Get(settings.SourceSystemTitle); break; //Server Challenge. case (byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.SenderAcseRequirements: //0xAA len = buff.GetUInt8(); tag = buff.GetUInt8(); len = buff.GetUInt8(); settings.StoCChallenge = new byte[len]; buff.Get(settings.StoCChallenge); break; case (byte)BerType.Context | (byte)PduType.SenderAcseRequirements: //0x8A case (byte)BerType.Context | (byte)PduType.CallingApInvocationId: //0x88 //Get sender ACSE-requirements field component. if (buff.GetUInt8() != 2) { throw new Exception("Invalid tag."); } if (buff.GetUInt8() != (byte)BerType.ObjectDescriptor) { throw new Exception("Invalid tag."); } if (buff.GetUInt8() != 0x80) { throw new Exception("Invalid tag."); } break; case (byte)BerType.Context | (byte)PduType.MechanismName: //0x8B case (byte)BerType.Context | (byte)PduType.CallingAeInvocationId: //0x89 len = buff.GetUInt8(); if (buff.GetUInt8() != 0x60) { throw new Exception("Invalid tag."); } if (buff.GetUInt8() != 0x85) { throw new Exception("Invalid tag."); } if (buff.GetUInt8() != 0x74) { throw new Exception("Invalid tag."); } if (buff.GetUInt8() != 0x05) { throw new Exception("Invalid tag."); } if (buff.GetUInt8() != 0x08) { throw new Exception("Invalid tag."); } if (buff.GetUInt8() != 0x02) { throw new Exception("Invalid tag."); } int tmp = buff.GetUInt8(); if (tmp < 0 || tmp > 5) { throw new Exception("Invalid tag."); } settings.Authentication = (Authentication)tmp; break; case (byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.CallingAuthenticationValue: //0xAC len = buff.GetUInt8(); // Get authentication information. if (buff.GetUInt8() != 0x80) { throw new Exception("Invalid tag."); } len = buff.GetUInt8(); if (settings.Authentication < Authentication.HighMD5) { settings.Password = new byte[len]; buff.Get(settings.Password); } else { settings.CtoSChallenge = new byte[len]; buff.Get(settings.CtoSChallenge); } break; case (byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.UserInformation: //0xBE if (resultComponent != AssociationResult.Accepted && resultDiagnosticValue != SourceDiagnostic.None) { throw new GXDLMSException(resultComponent, resultDiagnosticValue); } ParseUserInformation(settings, cipher, buff); break; default: //Unknown tags. System.Diagnostics.Debug.WriteLine("Unknown tag: " + tag + "."); len = buff.GetUInt8(); buff.Position += (UInt16)len; break; } } return(resultDiagnosticValue); }
///<summary> ///Server generates AARE message. ///</summary> internal void GenerateAARE(List<byte> data, Authentication authentication, byte[] challenge, ushort maxReceivePDUSize, byte[] conformanceBlock, AssociationResult result, SourceDiagnostic diagnostic) { // Set AARE tag and length data.Add(0x61); ApplicationContextName.CodeData(data); //Result data.Add(0xA2); data.Add(3); //len data.Add(2); //Tag //Choice for result (INTEGER, universal) data.Add(1); //Len data.Add((byte) result); //ResultValue //SourceDiagnostic data.Add(0xA3); data.Add(5); //len data.Add(0xA1); //Tag data.Add(3); //len data.Add(2); //Tag //Choice for result (INTEGER, universal) data.Add(1); //Len data.Add((byte)diagnostic); //diagnostic if (diagnostic == SourceDiagnostic.AuthenticationRequired) { //Add server ACSE-requirenents field component. data.Add(0x88); data.Add(0x02); //Len. GXCommon.SetUInt16(0x0780, data); //Add tag. data.Add(0x89); data.Add(0x07);//Len data.Add(0x60); data.Add(0x85); data.Add(0x74); data.Add(0x05); data.Add(0x08); data.Add(0x02); data.Add((byte) authentication); //Add tag. data.Add(0xAA); data.Add((byte) (2 + challenge.Length));//Len data.Add(0x80); data.Add((byte) challenge.Length); data.AddRange(challenge); } //Add User Information data.Add(0xBE); //Tag data.Add(0x10); //Length for AARQ user field data.Add(0x04); //Coding the choice for user-information (Octet STRING, universal) data.Add(0xE); //Length data.Add(GXCommon.InitialResponce); // Tag for xDLMS-Initiate response data.Add(0x00); // Usage field for the response allowed component (not used) data.Add(6); // DLMSVersioNumber data.Add(0x5F); data.Add(0x1F); data.Add(0x04);// length of the conformance block data.Add(0x00);// encoding the number of unused bits in the bit string data.AddRange(conformanceBlock); GXCommon.SetUInt16(maxReceivePDUSize, data); //VAA Name VAA name (0x0007 for LN referencing and 0xFA00 for SN) if (UseLN) { GXCommon.SetUInt16(0x0007, data); } else { GXCommon.SetUInt16(0xFA00, data); } data.Insert(1, (byte) (data.Count - 1)); }
///<summary> ///EncodeData ///</summary> internal void EncodeData(byte[] buff, ref int index) { // Get AARE tag and length int tag = buff[index++]; if (tag != 0x61 && tag != 0x60 && tag != 0x81 && tag != 0x80) { throw new Exception("Invalid tag."); } int len = buff[index++]; int size = buff.Length - index; if (len > size) { throw new Exception("Not enought data."); } while (index < buff.Length) { tag = buff[index]; if (tag == 0xA1) { ApplicationContextName.EncodeData(buff, ref index); } else if (tag == 0xBE) { if (ResultValue != AssociationResult.Accepted && ResultDiagnosticValue != SourceDiagnostic.None) { return; } UserInformation.EncodeData(buff, ref index); } else if (tag == 0xA2) //Result { tag = buff[index++]; len = buff[index++]; //Choice for result (INTEGER, universal) tag = buff[index++]; len = buff[index++]; ResultValue = (AssociationResult)buff[index++]; } else if (tag == 0xA3) //SourceDiagnostic { tag = buff[index++]; len = buff[index++]; // ACSE service user tag. tag = buff[index++]; len = buff[index++]; // Result source diagnostic component. tag = buff[index++]; len = buff[index++]; ResultDiagnosticValue = (SourceDiagnostic)buff[index++]; } else if (tag == 0x8A || tag == 0x88) //Authentication. { tag = buff[index++]; //Get sender ACSE-requirenents field component. if (buff[index++] != 2) { throw new Exception("Invalid tag."); } int val = GXCommon.GetUInt16(buff, ref index); if (val != 0x0780 && val != 0x0680) { throw new Exception("Invalid tag."); } } else if (tag == 0xAA) //Server Challenge. { tag = buff[index++]; len = buff[index++]; ++index; len = buff[index++]; //Get challenge index += len; } else if (tag == 0x8B || tag == 0x89) //Authentication. { tag = buff[index++]; len = buff[index++]; bool IsAuthenticationTag = len > 7; if (buff[index++] != 0x60) { throw new Exception("Invalid tag."); } if (buff[index++] != 0x85) { throw new Exception("Invalid tag."); } if (buff[index++] != 0x74) { throw new Exception("Invalid tag."); } if (buff[index++] != 0x05) { throw new Exception("Invalid tag."); } if (buff[index++] != 0x08) { throw new Exception("Invalid tag."); } if (buff[index++] != 0x02) { throw new Exception("Invalid tag."); } int tmp = buff[index++]; if (tmp < 0 || tmp > 5) { throw new Exception("Invalid tag."); } if (IsAuthenticationTag) { Authentication = (Authentication)tmp; byte tag2 = buff[index++]; if (tag2 != 0xAC && tag2 != 0xAA) { throw new Exception("Invalid tag."); } len = buff[index++]; //Get authentication information. if (buff[index++] != 0x80) { throw new Exception("Invalid tag."); } len = buff[index++]; Password = new byte[len]; Array.Copy(buff, index, Password, 0, len); index += len; } else { Authentication = Authentication.None; } } //Unknown tags. else { tag = buff[index++]; len = buff[index++]; if (Tags != null) { GXDLMSTag tmp = new GXDLMSTag(); tmp.ID = tag; tmp.Data = new byte[len]; tmp.Data = GXCommon.Swap(buff, index, len); Tags.Add(tmp); } index += len; } } }
///<summary> ///EncodeData ///</summary> internal void EncodeData(byte[] buff, ref int index) { // Get AARE tag and length int tag = buff[index++]; if (tag != 0x61 && tag != 0x60 && tag != 0x81 && tag != 0x80) { throw new Exception("Invalid tag."); } int len = buff[index++]; int size = buff.Length - index; if (len > size) { throw new Exception("Not enough data."); } while (index < buff.Length) { tag = buff[index]; if (tag == 0xA1) { ApplicationContextName.EncodeData(buff, ref index); } else if (tag == 0xBE) { if (ResultValue != AssociationResult.Accepted && ResultDiagnosticValue != SourceDiagnostic.None) { return; } UserInformation.EncodeData(buff, ref index); } else if (tag == 0xA2) //Result { tag = buff[index++]; len = buff[index++]; //Choice for result (INTEGER, universal) tag = buff[index++]; len = buff[index++]; ResultValue = (AssociationResult)buff[index++]; } else if (tag == 0xA3) //SourceDiagnostic { tag = buff[index++]; len = buff[index++]; // ACSE service user tag. tag = buff[index++]; len = buff[index++]; // Result source diagnostic component. tag = buff[index++]; len = buff[index++]; ResultDiagnosticValue = (SourceDiagnostic)buff[index++]; } else if (tag == 0x8A || tag == 0x88) //Authentication. { tag = buff[index++]; //Get sender ACSE-requirements field component. if (buff[index++] != 2) { throw new Exception("Invalid tag."); } int val = GXCommon.GetUInt16(buff, ref index); if (val != 0x0780 && val != 0x0680) { throw new Exception("Invalid tag."); } } else if (tag == 0xAA) //Server Challenge. { tag = buff[index++]; len = buff[index++]; ++index; len = buff[index++]; //Get challenge and save it to the PW. Password = new byte[len]; Array.Copy(buff, index, Password, 0, len); index += len; } else if (tag == 0xAC) //Password. { tag = buff[index++]; len = buff[index++]; //Get authentication information. if (buff[index++] != 0x80) { throw new Exception("Invalid tag."); } len = buff[index++]; //Get password. Password = new byte[len]; Array.Copy(buff, index, Password, 0, len); index += len; } else if (tag == 0x8B || tag == 0x89) //Authentication. { tag = buff[index++]; len = buff[index++]; if (buff[index++] != 0x60) { throw new Exception("Invalid tag."); } if (buff[index++] != 0x85) { throw new Exception("Invalid tag."); } if (buff[index++] != 0x74) { throw new Exception("Invalid tag."); } if (buff[index++] != 0x05) { throw new Exception("Invalid tag."); } if (buff[index++] != 0x08) { throw new Exception("Invalid tag."); } if (buff[index++] != 0x02) { throw new Exception("Invalid tag."); } int tmp = buff[index++]; if (tmp < 0 || tmp > 5) { throw new Exception("Invalid tag."); } Authentication = (Authentication)tmp; } //Unknown tags. else { tag = buff[index++]; len = buff[index++]; if (Tags != null) { GXDLMSTag tmp = new GXDLMSTag(); tmp.ID = tag; tmp.Data = new byte[len]; tmp.Data = GXCommon.Swap(buff, index, len); Tags.Add(tmp); } index += len; } } }
/// <summary> /// Get diagnostic as a string. /// </summary> /// <param name="diagnostic"></param> /// <returns></returns> static string GetDiagnostic(SourceDiagnostic diagnostic) { if (diagnostic == SourceDiagnostic.NoReasonGiven) { return "No reason is given."; } if (diagnostic == SourceDiagnostic.ApplicationContextNameNotSupported) { return "The application context name is not supported."; } if (diagnostic == SourceDiagnostic.AuthenticationMechanismNameNotRecognised) { return "The authentication mechanism name is not recognized."; } if (diagnostic == SourceDiagnostic.AuthenticationMechanismNameReguired) { return "Authentication mechanism name is required."; } if (diagnostic == SourceDiagnostic.AuthenticationFailure) { return "Authentication failure."; } if (diagnostic == SourceDiagnostic.AuthenticationRequired) { return "Authentication is required."; } throw new InvalidOperationException(); }
///<summary> ///Server generates AARE message. ///</summary> internal void GenerateAARE(List <byte> data, Authentication authentication, byte[] challenge, ushort maxReceivePDUSize, byte[] conformanceBlock, AssociationResult result, SourceDiagnostic diagnostic) { // Set AARE tag and length data.Add(0x61); ApplicationContextName.CodeData(data); //Result data.Add(0xA2); data.Add(3); //len data.Add(2); //Tag //Choice for result (INTEGER, universal) data.Add(1); //Len data.Add((byte)result); //ResultValue //SourceDiagnostic data.Add(0xA3); data.Add(5); //len data.Add(0xA1); //Tag data.Add(3); //len data.Add(2); //Tag //Choice for result (INTEGER, universal) data.Add(1); //Len data.Add((byte)diagnostic); //diagnostic if (diagnostic == SourceDiagnostic.AuthenticationRequired) { //Add server ACSE-requirenents field component. data.Add(0x88); data.Add(0x02); //Len. GXCommon.SetUInt16(0x0780, data); //Add tag. data.Add(0x89); data.Add(0x07);//Len data.Add(0x60); data.Add(0x85); data.Add(0x74); data.Add(0x05); data.Add(0x08); data.Add(0x02); data.Add((byte)authentication); //Add tag. data.Add(0xAA); data.Add((byte)(2 + challenge.Length)); //Len data.Add(0x80); data.Add((byte)challenge.Length); data.AddRange(challenge); } //Add User Information data.Add(0xBE); //Tag data.Add(0x10); //Length for AARQ user field data.Add(0x04); //Coding the choice for user-information (Octet STRING, universal) data.Add(0xE); //Length data.Add(GXCommon.InitialResponce); // Tag for xDLMS-Initiate response data.Add(0x00); // Usage field for the response allowed component (not used) data.Add(6); // DLMSVersioNumber data.Add(0x5F); data.Add(0x1F); data.Add(0x04); // length of the conformance block data.Add(0x00); // encoding the number of unused bits in the bit string data.AddRange(conformanceBlock); GXCommon.SetUInt16(maxReceivePDUSize, data); //VAA Name VAA name (0x0007 for LN referencing and 0xFA00 for SN) if (UseLN) { GXCommon.SetUInt16(0x0007, data); } else { GXCommon.SetUInt16(0xFA00, data); } data.Insert(1, (byte)(data.Count - 1)); }
///<summary> ///Server generates AARE message. ///</summary> internal static void GenerateAARE(GXDLMSSettings settings, GXByteBuffer data, AssociationResult result, SourceDiagnostic diagnostic, GXICipher cipher, GXByteBuffer encryptedData) { int offset = data.Size; // Set AARE tag and length data.SetUInt8(((byte)BerType.Application | (byte)BerType.Constructed | (byte)PduType.ApplicationContextName)); //0x61 // Length is updated later. data.SetUInt8(0); GenerateApplicationContextName(settings, data, cipher); //Result data.SetUInt8((byte)BerType.Context | (byte)BerType.Constructed | (byte)BerType.Integer);//0xA2 data.SetUInt8(3); //len data.SetUInt8(BerType.Integer); //Tag //Choice for result (INTEGER, universal) data.SetUInt8(1); //Len data.SetUInt8((byte)result); //ResultValue //SourceDiagnostic data.SetUInt8(0xA3); data.SetUInt8(5); //len data.SetUInt8(0xA1); //Tag data.SetUInt8(3); //len data.SetUInt8(2); //Tag //Choice for result (INTEGER, universal) data.SetUInt8(1); //Len data.SetUInt8((byte)diagnostic); //diagnostic //SystemTitle if (cipher != null && (cipher.IsCiphered() || settings.Authentication == Authentication.HighGMAC)) { data.SetUInt8((byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.CalledApInvocationId); data.SetUInt8((byte)(2 + cipher.SystemTitle.Length)); data.SetUInt8((byte)BerType.OctetString); data.SetUInt8((byte)cipher.SystemTitle.Length); data.Set(cipher.SystemTitle); } if (result != AssociationResult.PermanentRejected && diagnostic == SourceDiagnostic.AuthenticationRequired) { //Add server ACSE-requirenents field component. data.SetUInt8(0x88); data.SetUInt8(0x02); //Len. data.SetUInt16(0x0780); //Add tag. data.SetUInt8(0x89); data.SetUInt8(0x07);//Len data.SetUInt8(0x60); data.SetUInt8(0x85); data.SetUInt8(0x74); data.SetUInt8(0x05); data.SetUInt8(0x08); data.SetUInt8(0x02); data.SetUInt8((byte)settings.Authentication); //Add tag. data.SetUInt8(0xAA); data.SetUInt8((byte)(2 + settings.StoCChallenge.Length));//Len data.SetUInt8((byte)BerType.Context); data.SetUInt8((byte)settings.StoCChallenge.Length); data.Set(settings.StoCChallenge); } byte[] tmp; //Add User Information //Tag 0xBE data.SetUInt8((byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.UserInformation); if (encryptedData != null && encryptedData.Size != 0) { GXByteBuffer tmp2 = new GXByteBuffer((UInt16)(2 + encryptedData.Size)); tmp2.SetUInt8((byte)Command.GloInitiateResponse); GXCommon.SetObjectCount(encryptedData.Size, tmp2); tmp2.Set(encryptedData); tmp = tmp2.Array(); } else { tmp = GetUserInformation(settings, cipher); } data.SetUInt8((byte)(2 + tmp.Length)); //Coding the choice for user-information (Octet STRING, universal) data.SetUInt8(BerType.OctetString); //Length data.SetUInt8((byte)tmp.Length); data.Set(tmp); data.SetUInt8((UInt16)(offset + 1), (byte)(data.Size - offset - 2)); }
/// <summary> /// Constructor for AARE error. /// </summary> internal GXDLMSException(AssociationResult result, SourceDiagnostic diagnostic) : base("Connection is " + GetResult(result) + ". " + GetDiagnostic(diagnostic)) { Result = result; Diagnostic = (byte)diagnostic; }