private static void updatePassword(GXDLMSSettings settings, GXByteBuffer buff, GXDLMSTranslatorStructure xml) { int len = buff.GetUInt8(); // Get authentication information. if (buff.GetUInt8() != 0x80) { throw new Exception("Invalid tag."); } len = buff.GetUInt8(); if (settings.Authentication == Authentication.Low) { settings.Password = new byte[len]; buff.Get(settings.Password); } else { settings.CtoSChallenge = new byte[len]; buff.Get(settings.CtoSChallenge); } if (xml != null) { if (xml.OutputType == TranslatorOutputType.SimpleXml) { if (settings.Authentication == Authentication.Low) { xml.AppendLine(TranslatorGeneralTags.CallingAuthentication, "Value", GXCommon.ToHex(settings.Password, false)); } else { xml.AppendLine(TranslatorGeneralTags.CallingAuthentication, "Value", GXCommon.ToHex(settings.CtoSChallenge, false)); } } else { xml.AppendStartTag( TranslatorGeneralTags.CallingAuthentication); xml.AppendStartTag(TranslatorGeneralTags.CharString); if (settings.Authentication == Authentication.Low) { xml.Append(GXCommon.ToHex(settings.Password, false)); } else { xml.Append( GXCommon.ToHex(settings.CtoSChallenge, false)); } xml.AppendEndTag(TranslatorGeneralTags.CharString); xml.AppendEndTag(TranslatorGeneralTags.CallingAuthentication); } } }
///<summary> ///Parse APDU. ///</summary> static internal SourceDiagnostic ParsePDU(GXDLMSSettings settings, GXICipher cipher, GXByteBuffer buff, GXDLMSTranslatorStructure xml) { // 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."); } //Opening tags if (xml != null) { if (settings.IsServer) { xml.AppendStartTag(Command.Aarq); } else { xml.AppendStartTag(Command.Aare); } } 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, xml)) { throw new GXDLMSException(AssociationResult.PermanentRejected, SourceDiagnostic.ApplicationContextNameNotSupported); } break; case (byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.CalledApTitle://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(); if (xml != null) { xml.AppendLine(TranslatorGeneralTags.AssociationResult, "Value", xml.IntegerToHex((int)resultComponent, 2)); xml.AppendStartTag(TranslatorGeneralTags.ResultSourceDiagnostic); } 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(); if (xml != null) { xml.AppendLine(TranslatorGeneralTags.ACSEServiceUser, "Value", xml.IntegerToHex((int)resultDiagnosticValue, 2)); xml.AppendEndTag(TranslatorGeneralTags.ResultSourceDiagnostic); } 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); if (xml != null) { //RespondingAPTitle xml.AppendLine(TranslatorGeneralTags.RespondingAPTitle, "Value", GXCommon.ToHex(settings.SourceSystemTitle, false)); } 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); if (xml != null) { //CallingAPTitle xml.AppendLine(TranslatorGeneralTags.CallingAPTitle, "Value", GXCommon.ToHex(settings.SourceSystemTitle, false)); } 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); AppendServerSystemTitleToXml(settings, xml, tag); 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."); } //SenderACSERequirements if (xml != null) { xml.AppendLine(tag, "Value", "1"); } break; case (byte)BerType.Context | (byte)PduType.MechanismName://0x8B case (byte)BerType.Context | (byte)PduType.CallingAeInvocationId://0x89 UpdateAuthentication(settings, buff); if (xml != null) { if (xml.OutputType == TranslatorOutputType.SimpleXml) { xml.AppendLine(tag, "Value", settings.Authentication.ToString()); } else { xml.AppendLine(tag, "Value", ((int)settings.Authentication).ToString()); } } break; case (byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.CallingAuthenticationValue://0xAC updatePassword(settings, buff, xml); break; case (byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.UserInformation: //0xBE if (xml == null && resultComponent != AssociationResult.Accepted && resultDiagnosticValue != SourceDiagnostic.None) { throw new GXDLMSException(resultComponent, resultDiagnosticValue); } ParseUserInformation(settings, cipher, buff, xml); break; default: //Unknown tags. System.Diagnostics.Debug.WriteLine("Unknown tag: " + tag + "."); if (buff.Position < buff.Size) { len = buff.GetUInt8(); buff.Position += (UInt16)len; } break; } } //Closing tags if (xml != null) { if (settings.IsServer) { xml.AppendEndTag(Command.Aarq); } else { xml.AppendEndTag(Command.Aare); } } return resultDiagnosticValue; }
private static void AppendServerSystemTitleToXml( GXDLMSSettings settings, GXDLMSTranslatorStructure xml, int tag) { if (xml != null) { // RespondingAuthentication if (xml.OutputType == TranslatorOutputType.SimpleXml) { xml.AppendLine(tag, "Value", GXCommon.ToHex(settings.StoCChallenge, false)); } else { xml.Append(tag, true); xml.Append((int)TranslatorGeneralTags.CharString, true); xml.Append(GXCommon.ToHex(settings.StoCChallenge, false)); xml.Append((int)TranslatorGeneralTags.CharString, false); xml.Append(tag, false); xml.Append("\r\n"); } } }
/// <summary> /// Parse application context name. /// </summary> /// <param name="settings">DLMS settings.</param> /// <param name="buff">Received data.</param> private static bool ParseApplicationContextName(GXDLMSSettings settings, GXByteBuffer buff, GXDLMSTranslatorStructure xml) { //Get length. int len = buff.GetUInt8(); if (buff.Size - buff.Position < len) { throw new Exception("Encoding failed. Not enough data."); } if (buff.GetUInt8() != 0x6) { throw new Exception("Encoding failed. Not an Object ID."); } if (settings.IsServer && settings.Cipher != null) { settings.Cipher.Security = Gurux.DLMS.Enums.Security.None; } //Object ID length. len = buff.GetUInt8(); if (xml != null) { if (buff.Compare(GXCommon.LogicalNameObjectID)) { if (xml.OutputType == TranslatorOutputType.SimpleXml) { xml.AppendLine(TranslatorGeneralTags.ApplicationContextName, "Value", "LN"); } else { xml.AppendLine( TranslatorGeneralTags.ApplicationContextName, null, "1"); } settings.UseLogicalNameReferencing = true; } else if (buff.Compare(GXCommon.LogicalNameObjectIdWithCiphering)) { if (xml.OutputType == TranslatorOutputType.SimpleXml) { xml.AppendLine(TranslatorGeneralTags.ApplicationContextName, "Value", "LN_WITH_CIPHERING"); } else { xml.AppendLine( TranslatorGeneralTags.ApplicationContextName, null, "3"); } settings.UseLogicalNameReferencing = true; } else if (buff.Compare(GXCommon.ShortNameObjectID)) { if (xml.OutputType == TranslatorOutputType.SimpleXml) { xml.AppendLine(TranslatorGeneralTags.ApplicationContextName, "Value", "SN"); } else { xml.AppendLine( TranslatorGeneralTags.ApplicationContextName, null, "2"); } settings.UseLogicalNameReferencing = false; } else if (buff.Compare(GXCommon.ShortNameObjectIdWithCiphering)) { if (xml.OutputType == TranslatorOutputType.SimpleXml) { xml.AppendLine(TranslatorGeneralTags.ApplicationContextName, "Value", "SN_WITH_CIPHERING"); } else { xml.AppendLine( TranslatorGeneralTags.ApplicationContextName, null, "4"); } settings.UseLogicalNameReferencing = false; } else { return false; } return true; } if (settings.UseLogicalNameReferencing) { if (buff.Compare(GXCommon.LogicalNameObjectID)) { return true; } // If ciphering is used. return buff.Compare(GXCommon.LogicalNameObjectIdWithCiphering); } if (buff.Compare(GXCommon.ShortNameObjectID)) { return true; } // If ciphering is used. return buff.Compare(GXCommon.ShortNameObjectIdWithCiphering); }
/// <summary> /// Parse User Information from PDU. /// </summary> public static void ParseUserInformation(GXDLMSSettings settings, GXICipher cipher, GXByteBuffer data, GXDLMSTranslatorStructure xml) { byte len = data.GetUInt8(); GXByteBuffer tmp2 = new GXByteBuffer(); tmp2.SetUInt8(0); if (data.Size - data.Position < len) { throw new Exception("Not enough data."); } if (xml != null && xml.OutputType == TranslatorOutputType.StandardXml) { len = (byte)(data.Size - data.Position); xml.AppendLine(Command.InitiateRequest, null, GXCommon .ToHex(data.Data, false, data.Position, len)); data.Position = data.Position + len; return; } //Excoding the choice for user information int tag = data.GetUInt8(); if (tag != 0x4) { throw new Exception("Invalid tag."); } len = data.GetUInt8(); //Tag for xDLMS-Initate.response tag = data.GetUInt8(); if (tag == (byte)Command.GloInitiateResponse) { if (xml != null) { int cnt = GXCommon.GetObjectCount(data); byte[] tmp = new byte[cnt]; data.Get(tmp); //<glo_InitiateResponse> xml.AppendLine(Command.GloInitiateResponse, "Value", GXCommon.ToHex(tmp, false)); return; } --data.Position; cipher.Security = cipher.Decrypt(settings.SourceSystemTitle, data); tag = data.GetUInt8(); } else if (tag == (byte)Command.GloInitiateRequest) { if (xml != null) { int cnt = GXCommon.GetObjectCount(data); byte[] tmp = new byte[cnt]; data.Get(tmp); //<glo_InitiateRequest> xml.AppendLine(Command.GloInitiateRequest, "Value", GXCommon.ToHex(tmp, false)); return; } --data.Position; cipher.Security = cipher.Decrypt(settings.SourceSystemTitle, data); tag = data.GetUInt8(); } bool response = tag == (byte)Command.InitiateResponse; if (response) { if (xml != null) { //<InitiateResponse> xml.AppendStartTag(Command.InitiateResponse); } //Optional usage field of the negotiated quality of service component tag = data.GetUInt8(); len = 0; if (tag != 0)//Skip if used. { len = data.GetUInt8(); data.Position += len; if (len == 0 && xml != null) { //NegotiatedQualityOfService xml.AppendLine(TranslatorGeneralTags.NegotiatedQualityOfService, "Value", "00"); } } } else if (tag == (byte)Command.InitiateRequest) { if (xml != null) { //<InitiateRequest> xml.AppendStartTag(Command.InitiateRequest); } //Optional usage field of the negotiated quality of service component tag = data.GetUInt8(); //CtoS. if (tag != 0) { len = data.GetUInt8(); settings.CtoSChallenge = new byte[len]; data.Get(settings.CtoSChallenge); } //Optional usage field of the negotiated quality of service component tag = data.GetUInt8(); if (tag != 0)//Skip if used. { len = data.GetUInt8(); data.Position += len; } //Optional usage field of the proposed quality of service component tag = data.GetUInt8(); if (tag != 0)//Skip if used. { len = data.GetUInt8(); data.Position += len; } } else { throw new Exception("Invalid tag."); } //Get DLMS version number. if (!response) { if (data.GetUInt8() != 6) { throw new Exception("Invalid DLMS version number."); } //ProposedDlmsVersionNumber if (xml != null) { xml.AppendLine(TranslatorGeneralTags.ProposedDlmsVersionNumber, "Value", xml.IntegerToHex(settings.DLMSVersion, 2)); } } else { if (data.GetUInt8() != 6) { throw new Exception("Invalid DLMS version number."); } if (xml != null) { xml.AppendLine(TranslatorGeneralTags.NegotiatedDlmsVersionNumber, "Value", xml.IntegerToHex(settings.DLMSVersion, 2)); } } //Tag for conformance block tag = data.GetUInt8(); if (tag != 0x5F) { throw new Exception("Invalid tag."); } //Old Way... if (data.GetUInt8(data.Position) == 0x1F) { data.GetUInt8(); } len = data.GetUInt8(); //The number of unused bits in the bit string. tag = data.GetUInt8(); if (!response) { //ProposedConformance if (xml != null) { xml.AppendStartTag(TranslatorGeneralTags.ProposedConformance); } data.Get(settings.ConformanceBlock); tmp2.Set(settings.ConformanceBlock); } else { //NegotiatedConformance if (xml != null) { xml.AppendStartTag(TranslatorGeneralTags.NegotiatedConformance); } if (settings.UseLogicalNameReferencing) { data.Get(settings.LnSettings.ConformanceBlock); tmp2.Set(settings.LnSettings.ConformanceBlock); } else { data.Get(settings.SnSettings.ConformanceBlock); tmp2.Set(settings.SnSettings.ConformanceBlock); } } if (xml != null) { GetConformance(tmp2.GetUInt32(), xml); } if (!response) { //Proposed max PDU size. settings.MaxPduSize = data.GetUInt16(); if (xml != null) { //ProposedConformance closing xml.AppendEndTag(TranslatorGeneralTags.ProposedConformance); //ProposedMaxPduSize xml.AppendLine(TranslatorGeneralTags.ProposedMaxPduSize, "Value", xml.IntegerToHex(settings.MaxPduSize, 4)); } //If client asks too high PDU. if (settings.MaxPduSize > settings.MaxServerPDUSize) { settings.MaxPduSize = settings.MaxServerPDUSize; } } else { //Max PDU size. settings.MaxPduSize = data.GetUInt16(); if (xml != null) { //NegotiatedConformance closing xml.AppendEndTag(TranslatorGeneralTags.NegotiatedConformance); //NegotiatedMaxPduSize xml.AppendLine(TranslatorGeneralTags.NegotiatedMaxPduSize, "Value", xml.IntegerToHex(settings.MaxPduSize, 4)); } } if (response) { //VAA Name tag = data.GetUInt16(); if (xml != null) { xml.AppendLine(TranslatorGeneralTags.VaaName, "Value", xml.IntegerToHex(tag, 4)); } if (tag == 0x0007) { // If LN if (!settings.UseLogicalNameReferencing) { throw new ArgumentException("Invalid VAA."); } } else if (tag == 0xFA00) { // If SN if (settings.UseLogicalNameReferencing) { throw new ArgumentException("Invalid VAA."); } } else { // Unknown VAA. throw new ArgumentException("Invalid VAA."); } if (xml != null) { //<InitiateResponse> xml.AppendEndTag(Command.InitiateResponse); } } else if (xml != null) { //</InitiateRequest> xml.AppendEndTag(Command.InitiateRequest); } }
private static void GetConformance(UInt32 value, GXDLMSTranslatorStructure xml) { foreach (var it in Enum.GetValues(typeof(Conformance))) { if (((int)it & value) != 0) { xml.AppendLine(TranslatorGeneralTags.ConformanceBit, "Name", it.ToString()); } } }