using System; using System.IO; using System.Net; using System.Text; using DnDns.Enums; namespace DnDns.Records { /// /// Implementation of a TSIG record structure as per RFC 2845 /// public sealed class TSigRecord : DnsRecordBase { private string _algorithmName; private RCode _error; private ushort _fudge; private ushort _originalId; private byte[] _otherData; private byte[] _mac; private DateTime _timeSigned; public string AlgorithmName { get { return _algorithmName; } } public RCode Error { get { return _error; } } public ushort Fudge { get { return _fudge; } } public ushort OriginalID { get { return _originalId; } } public byte[] OtherData { get { return _otherData; } } public byte[] Mac { get { return _mac; } } public DateTime TimeSigned { get { return _timeSigned; } } public TSigRecord(RecordHeader dnsHeader) : base(dnsHeader) { } public TSigRecord(string name, string algorithmName, RCode error, ushort fudge, ushort originalId, byte[] otherData, byte[] mac, DateTime timeSigned) { DnsHeader = new RecordHeader(name, NsType.TSIG, NsClass.ANY, 0); _algorithmName = algorithmName; _error = error; _fudge = fudge; _originalId = originalId; _otherData = otherData; _mac = mac; _timeSigned = timeSigned; if(otherData == null) { _otherData = new byte[]{}; } } public override void ParseRecord(ref MemoryStream memoryStream) { Byte[] dataUInt16 = new byte[2]; Byte[] dataUInt32 = new byte[4]; _algorithmName = ParseName(ref memoryStream); memoryStream.Read(dataUInt16, 0, dataUInt16.Length); long timeHigh = (ushort) IPAddress.NetworkToHostOrder((short)BitConverter.ToUInt16(dataUInt16, 0)); memoryStream.Read(dataUInt32, 0, dataUInt32.Length); long timeLow = (uint) IPAddress.NetworkToHostOrder((int)BitConverter.ToUInt32(dataUInt32, 0)); _timeSigned = DnsHelpers.ConvertFromDnsTime(timeLow, timeHigh); memoryStream.Read(dataUInt16, 0, dataUInt16.Length); _fudge = (ushort)IPAddress.NetworkToHostOrder((short)BitConverter.ToUInt16(dataUInt16, 0)); memoryStream.Read(dataUInt16, 0, dataUInt16.Length); Int32 macLen = (ushort)IPAddress.NetworkToHostOrder((short)BitConverter.ToUInt16(dataUInt16, 0)); _mac = new byte[macLen]; memoryStream.Read(_mac, 0, macLen); memoryStream.Read(dataUInt16, 0, dataUInt16.Length); _originalId = (ushort)IPAddress.NetworkToHostOrder((short)BitConverter.ToUInt16(dataUInt16, 0)); memoryStream.Read(dataUInt16, 0, dataUInt16.Length); _error = (RCode)IPAddress.NetworkToHostOrder((short)BitConverter.ToUInt16(dataUInt16, 0)); memoryStream.Read(dataUInt16, 0, dataUInt16.Length); Int32 otherLen = (ushort)IPAddress.NetworkToHostOrder((short)BitConverter.ToUInt16(dataUInt16, 0)); if(otherLen > 0) { _otherData = new byte[otherLen]; memoryStream.Read(_otherData, 0, otherLen); } else { _otherData = null; } _answer = ToString(); } public override byte[] GetMessageBytes() { MemoryStream memoryStream = new MemoryStream(); byte[] data = DnsHeader.GetMessageBytes(); memoryStream.Write(data,0,data.Length); long rLengthPosition = memoryStream.Position; data = DnsHelpers.CanonicaliseDnsName(_algorithmName, false); memoryStream.Write(data, 0, data.Length); int timeHigh; long timeLow; DnsHelpers.ConvertToDnsTime(_timeSigned.ToUniversalTime(), out timeHigh, out timeLow); data = BitConverter.GetBytes((ushort)(IPAddress.HostToNetworkOrder((ushort)timeHigh) >> 16)); memoryStream.Write(data, 0, data.Length); data = BitConverter.GetBytes((uint)(IPAddress.HostToNetworkOrder((uint)timeLow) >> 32)); memoryStream.Write(data, 0, data.Length); data = BitConverter.GetBytes((ushort)(IPAddress.HostToNetworkOrder(_fudge) >> 16)); memoryStream.Write(data, 0, data.Length); data = BitConverter.GetBytes((ushort)(IPAddress.HostToNetworkOrder(_mac.Length) >> 16)); memoryStream.Write(data, 0, data.Length); memoryStream.Write(_mac, 0, _mac.Length); data = BitConverter.GetBytes((ushort)(IPAddress.HostToNetworkOrder(_originalId) >> 16)); memoryStream.Write(data, 0, data.Length); data = BitConverter.GetBytes((ushort)(IPAddress.HostToNetworkOrder((ushort)_error) >> 16)); memoryStream.Write(data, 0, data.Length); data = BitConverter.GetBytes((ushort)(IPAddress.HostToNetworkOrder((ushort)_otherData.Length) >> 16)); memoryStream.Write(data, 0, data.Length); if(_otherData.Length != 0) { memoryStream.Write(_otherData, 0, _otherData.Length); } // Add the rdata lenght long rlength = memoryStream.Position - rLengthPosition; memoryStream.Seek(rLengthPosition - 2, SeekOrigin.Begin); data = BitConverter.GetBytes((ushort)(IPAddress.HostToNetworkOrder((ushort)rlength) >> 16)); memoryStream.Write(data, 0, data.Length); return memoryStream.ToArray(); } public override string ToString() { StringBuilder sb = new StringBuilder(); sb.Append(_algorithmName); sb.Append(" "); sb.Append(_timeSigned); sb.Append(" "); sb.Append(_fudge); sb.Append(" "); sb.Append(_mac.Length); sb.Append(" "); sb.Append(Convert.ToBase64String(Mac)); sb.Append(" "); sb.Append(_error); sb.Append(" "); if (_otherData == null) { sb.Append(0); } else { sb.Append(_otherData.Length); sb.Append(" "); if (_error == RCode.BADTIME) { if (_otherData.Length != 6) { sb.Append(""); } else { long time = ((long)(_otherData[0] & 0xFF) << 40) + ((long)(_otherData[1] & 0xFF) << 32) + ((_otherData[2] & 0xFF) << 24) + ((_otherData[3] & 0xFF) << 16) + ((_otherData[4] & 0xFF) << 8) + ((_otherData[5] & 0xFF)); sb.Append(""); } } else { sb.Append("<"); sb.Append(Convert.ToBase64String(_otherData)); sb.Append(">"); } } return sb.ToString(); } } }