Commit 1a372992 authored by Brickner_cp's avatar Brickner_cp

DNS

parent 39796a8b
...@@ -4,6 +4,7 @@ namespace PcapDotNet.Base ...@@ -4,6 +4,7 @@ namespace PcapDotNet.Base
{ {
public struct SerialNumber32 : IEquatable<SerialNumber32>, IComparable<SerialNumber32> public struct SerialNumber32 : IEquatable<SerialNumber32>, IComparable<SerialNumber32>
{ {
public const int SizeOf = sizeof(uint);
public const int SerialBits = 32; public const int SerialBits = 32;
public const uint MaxAdditiveNumber = ((uint)1 << (SerialBits - 1)) - 1; public const uint MaxAdditiveNumber = ((uint)1 << (SerialBits - 1)) - 1;
......
...@@ -149,6 +149,7 @@ namespace PcapDotNet.Packets.TestUtils ...@@ -149,6 +149,7 @@ namespace PcapDotNet.Packets.TestUtils
return new DnsResourceDataMailExchange(random.NextUShort(), random.NextDnsDomainName()); return new DnsResourceDataMailExchange(random.NextUShort(), random.NextDnsDomainName());
case DnsType.Txt: case DnsType.Txt:
case DnsType.Spf:
return new DnsResourceDataText(((Func<DataSegment>)(() => random.NextDataSegment(random.Next(10)))).GenerateArray(10).AsReadOnly()); return new DnsResourceDataText(((Func<DataSegment>)(() => random.NextDataSegment(random.Next(10)))).GenerateArray(10).AsReadOnly());
case DnsType.Rp: case DnsType.Rp:
...@@ -297,6 +298,11 @@ namespace PcapDotNet.Packets.TestUtils ...@@ -297,6 +298,11 @@ namespace PcapDotNet.Packets.TestUtils
case DnsType.TaLink: case DnsType.TaLink:
return new DnsResourceDataTrustAnchorLink(random.NextDnsDomainName(), random.NextDnsDomainName()); return new DnsResourceDataTrustAnchorLink(random.NextDnsDomainName(), random.NextDnsDomainName());
case DnsType.TKey:
return new DnsResourceDataTransactionKey(random.NextDnsDomainName(), random.NextUInt(), random.NextUInt(),
random.NextEnum<DnsTransactionKeyMode>(), random.NextEnum<DnsResponseCode>(),
random.NextDataSegment(random.NextInt(0, 100)), random.NextDataSegment(random.NextInt(0, 100)));
default: default:
return new DnsResourceDataAnything(random.NextDataSegment(random.Next(100))); return new DnsResourceDataAnything(random.NextDataSegment(random.Next(100)));
} }
......
...@@ -73,7 +73,7 @@ namespace PcapDotNet.Packets.Dns ...@@ -73,7 +73,7 @@ namespace PcapDotNet.Packets.Dns
public const byte IsRecusionDesired = 0x01; public const byte IsRecusionDesired = 0x01;
public const byte IsRecusionAvailable = 0x80; public const byte IsRecusionAvailable = 0x80;
public const byte FutureUse = 0x60; public const byte FutureUse = 0x60;
public const byte ResponseCode = 0x1F; public const ushort ResponseCode = 0x1F;
} }
private static class Shift private static class Shift
...@@ -327,7 +327,7 @@ namespace PcapDotNet.Packets.Dns ...@@ -327,7 +327,7 @@ namespace PcapDotNet.Packets.Dns
if (isRecursionAvailable) if (isRecursionAvailable)
flags1 |= Mask.IsRecusionAvailable; flags1 |= Mask.IsRecusionAvailable;
flags1 |= (byte)((futureUse << Shift.FutureUse) & Mask.FutureUse); flags1 |= (byte)((futureUse << Shift.FutureUse) & Mask.FutureUse);
flags1 |= (byte)((byte)responseCode & Mask.ResponseCode); flags1 |= (byte)((ushort)responseCode & Mask.ResponseCode);
buffer.Write(offset + Offset.IsRecusionAvailable, flags1); buffer.Write(offset + Offset.IsRecusionAvailable, flags1);
DnsDomainNameCompressionData compressionData = new DnsDomainNameCompressionData(domainNameCompressionMode); DnsDomainNameCompressionData compressionData = new DnsDomainNameCompressionData(domainNameCompressionMode);
int recordOffset = HeaderLength; int recordOffset = HeaderLength;
......
...@@ -280,7 +280,7 @@ namespace PcapDotNet.Packets.Dns ...@@ -280,7 +280,7 @@ namespace PcapDotNet.Packets.Dns
private static class Offset private static class Offset
{ {
public const int Serial = 0; public const int Serial = 0;
public const int Refresh = Serial + sizeof(uint); public const int Refresh = Serial + SerialNumber32.SizeOf;
public const int Retry = Refresh + sizeof(uint); public const int Retry = Refresh + sizeof(uint);
public const int Expire = Retry + sizeof(uint); public const int Expire = Retry + sizeof(uint);
public const int MinimumTtl = Expire + sizeof(uint); public const int MinimumTtl = Expire + sizeof(uint);
...@@ -916,6 +916,7 @@ namespace PcapDotNet.Packets.Dns ...@@ -916,6 +916,7 @@ namespace PcapDotNet.Packets.Dns
/// </pre> /// </pre>
/// </summary> /// </summary>
[DnsTypeRegistration(Type = DnsType.Txt)] [DnsTypeRegistration(Type = DnsType.Txt)]
[DnsTypeRegistration(Type = DnsType.Spf)]
public sealed class DnsResourceDataText : DnsResourceDataStrings public sealed class DnsResourceDataText : DnsResourceDataStrings
{ {
public DnsResourceDataText(ReadOnlyCollection<DataSegment> strings) public DnsResourceDataText(ReadOnlyCollection<DataSegment> strings)
...@@ -1371,8 +1372,8 @@ namespace PcapDotNet.Packets.Dns ...@@ -1371,8 +1372,8 @@ namespace PcapDotNet.Packets.Dns
public const int Labels = Algorithm + sizeof(byte); public const int Labels = Algorithm + sizeof(byte);
public const int OriginalTtl = Labels + sizeof(byte); public const int OriginalTtl = Labels + sizeof(byte);
public const int SignatureExpiration = OriginalTtl + sizeof(uint); public const int SignatureExpiration = OriginalTtl + sizeof(uint);
public const int SignatureInception = SignatureExpiration + sizeof(uint); public const int SignatureInception = SignatureExpiration + SerialNumber32.SizeOf;
public const int KeyTag = SignatureInception + sizeof(uint); public const int KeyTag = SignatureInception + SerialNumber32.SizeOf;
public const int SignersName = KeyTag + sizeof(ushort); public const int SignersName = KeyTag + sizeof(ushort);
} }
...@@ -6110,4 +6111,226 @@ namespace PcapDotNet.Packets.Dns ...@@ -6110,4 +6111,226 @@ namespace PcapDotNet.Packets.Dns
return new DnsResourceDataTrustAnchorLink(previous, next); return new DnsResourceDataTrustAnchorLink(previous, next);
} }
} }
/// <summary>
/// RFC 2930.
/// </summary>
public enum DnsTransactionKeyMode : ushort
{
/// <summary>
/// RFC 2930.
/// </summary>
ServerAssignment = 1,
/// <summary>
/// RFC 2930.
/// </summary>
DiffieHellmanExchange = 2,
/// <summary>
/// RFC 2930.
/// </summary>
GssApiNegotiation = 3,
/// <summary>
/// RFC 2930.
/// </summary>
ResolverAssignment = 4,
/// <summary>
/// RFC 2930.
/// </summary>
KeyDeletion = 5,
}
/// <summary>
/// RFC 2930.
/// <pre>
/// +------+------------+------------+
/// | bit | 0-15 | 16-31 |
/// +------+------------+------------+
/// | 0 | Algorithm |
/// | ... | |
/// +------+-------------------------+
/// | X | Inception |
/// +------+-------------------------+
/// | X+32 | Expiration |
/// +------+------------+------------+
/// | X+64 | Mode | Error |
/// +------+------------+------------+
/// | X+96 | Key Size | |
/// +------+------------+ Key Data |
/// | ... | |
/// +------+------------+------------+
/// | | Other Size | |
/// +------+------------+ Other Data |
/// | ... | |
/// +------+-------------------------+
/// </pre>
/// </summary>
[DnsTypeRegistration(Type = DnsType.TKey)]
public sealed class DnsResourceDataTransactionKey : DnsResourceData, IEquatable<DnsResourceDataTransactionKey>
{
private static class OffsetAfterAlgorithm
{
public const int Inception = 0;
public const int Expiration = Inception + SerialNumber32.SizeOf;
public const int Mode = Expiration + SerialNumber32.SizeOf;
public const int Error = Mode + sizeof(ushort);
public const int KeySize = Error + sizeof(ushort);
public const int KeyData = KeySize + sizeof(ushort);
}
private const int ConstantPartLength = OffsetAfterAlgorithm.KeyData + sizeof(ushort);
public DnsResourceDataTransactionKey(DnsDomainName algorithm, SerialNumber32 inception, SerialNumber32 expiration, DnsTransactionKeyMode mode,
DnsResponseCode error, DataSegment key, DataSegment other)
{
if (key.Length > ushort.MaxValue)
throw new ArgumentOutOfRangeException("key", key.Length, string.Format("Cannot be longer than {0}", ushort.MaxValue));
if (other.Length > ushort.MaxValue)
throw new ArgumentOutOfRangeException("other", other.Length, string.Format("Cannot be longer than {0}", ushort.MaxValue));
Algorithm = algorithm;
Inception = inception;
Expiration = expiration;
Mode = mode;
Error = error;
Key = key;
Other = other;
}
/// <summary>
/// Name of the algorithm in domain name syntax.
/// The algorithm determines how the secret keying material agreed to using the TKEY RR is actually used to derive the algorithm specific key.
/// </summary>
public DnsDomainName Algorithm { get; private set; }
/// <summary>
/// Number of seconds since the beginning of 1 January 1970 GMT ignoring leap seconds treated as modulo 2**32 using ring arithmetic.
/// In messages between a DNS resolver and a DNS server where this field is meaningful,
/// it is either the requested validity interval start for the keying material asked for or
/// specify the validity interval start of keying material provided.
///
/// To avoid different interpretations of the inception time in TKEY RRs,
/// resolvers and servers exchanging them must have the same idea of what time it is.
/// One way of doing this is with the NTP protocol [RFC 2030] but that or any other time synchronization used for this purpose must be done securely.
/// </summary>
public SerialNumber32 Inception { get; private set; }
/// <summary>
/// Number of seconds since the beginning of 1 January 1970 GMT ignoring leap seconds treated as modulo 2**32 using ring arithmetic.
/// In messages between a DNS resolver and a DNS server where this field is meaningful,
/// it is either the requested validity interval end for the keying material asked for or
/// specify the validity interval end of keying material provided.
///
/// To avoid different interpretations of the expiration time in TKEY RRs,
/// resolvers and servers exchanging them must have the same idea of what time it is.
/// One way of doing this is with the NTP protocol [RFC 2030] but that or any other time synchronization used for this purpose must be done securely.
/// </summary>
public SerialNumber32 Expiration { get; private set; }
/// <summary>
/// Specifies the general scheme for key agreement or the purpose of the TKEY DNS message.
/// Servers and resolvers supporting this specification must implement the Diffie-Hellman key agreement mode and the key deletion mode for queries.
/// All other modes are optional.
/// A server supporting TKEY that receives a TKEY request with a mode it does not support returns the BADMODE error.
/// </summary>
public DnsTransactionKeyMode Mode { get; private set; }
/// <summary>
/// When the TKEY Error Field is non-zero in a response to a TKEY query, the DNS header RCODE field indicates no error.
/// However, it is possible if a TKEY is spontaneously included in a response the TKEY RR and DNS header error field could have unrelated non-zero error codes.
/// </summary>
public DnsResponseCode Error { get; private set; }
/// <summary>
/// The key exchange data.
/// The meaning of this data depends on the mode.
/// </summary>
public DataSegment Key { get; private set; }
/// <summary>
/// The Other field may be used in future extensions.
/// </summary>
public DataSegment Other { get; private set; }
public bool Equals(DnsResourceDataTransactionKey other)
{
return other != null &&
Algorithm.Equals(other.Algorithm) &&
Inception.Equals(other.Inception) &&
Expiration.Equals(other.Expiration) &&
Mode.Equals(other.Mode) &&
Error.Equals(other.Error) &&
Key.Equals(other.Key) &&
Other.Equals(other.Other);
}
public override bool Equals(DnsResourceData other)
{
return Equals(other as DnsResourceDataTransactionKey);
}
internal DnsResourceDataTransactionKey()
: this(DnsDomainName.Root, 0, 0, DnsTransactionKeyMode.DiffieHellmanExchange, DnsResponseCode.NoError, DataSegment.Empty, DataSegment.Empty)
{
}
internal override int GetLength(DnsDomainNameCompressionData compressionData, int offsetInDns)
{
return Algorithm.GetLength(compressionData, offsetInDns) + ConstantPartLength + Key.Length + Other.Length;
}
internal override int WriteData(byte[] buffer, int dnsOffset, int offsetInDns, DnsDomainNameCompressionData compressionData)
{
int algorithmLength = Algorithm.Write(buffer, dnsOffset, compressionData, offsetInDns);
int offset = dnsOffset + offsetInDns + algorithmLength;
buffer.Write(offset + OffsetAfterAlgorithm.Inception, Inception.Value, Endianity.Big);
buffer.Write(offset + OffsetAfterAlgorithm.Expiration, Expiration.Value, Endianity.Big);
buffer.Write(offset + OffsetAfterAlgorithm.Mode, (ushort)Mode, Endianity.Big);
buffer.Write(offset + OffsetAfterAlgorithm.Error, (ushort)Error, Endianity.Big);
buffer.Write(offset + OffsetAfterAlgorithm.KeySize, (ushort)Key.Length, Endianity.Big);
Key.Write(buffer, offset + OffsetAfterAlgorithm.KeyData);
int otherSizeOffset = offset + OffsetAfterAlgorithm.KeyData + Key.Length;
buffer.Write(otherSizeOffset, (ushort)Other.Length, Endianity.Big);
Other.Write(buffer, otherSizeOffset + sizeof(ushort));
return algorithmLength + ConstantPartLength + Key.Length + Other.Length;
}
internal override DnsResourceData CreateInstance(DnsDatagram dns, int offsetInDns, int length)
{
if (length < ConstantPartLength + DnsDomainName.RootLength)
return null;
DnsDomainName algorithm;
int algorithmLength;
if (!DnsDomainName.TryParse(dns, offsetInDns, length - ConstantPartLength, out algorithm, out algorithmLength))
return null;
offsetInDns += algorithmLength;
length -= algorithmLength;
uint inception = dns.ReadUInt(offsetInDns + OffsetAfterAlgorithm.Inception, Endianity.Big);
uint expiration = dns.ReadUInt(offsetInDns + OffsetAfterAlgorithm.Expiration, Endianity.Big);
DnsTransactionKeyMode mode = (DnsTransactionKeyMode)dns.ReadUShort(offsetInDns + OffsetAfterAlgorithm.Mode, Endianity.Big);
DnsResponseCode error = (DnsResponseCode)dns.ReadUShort(offsetInDns + OffsetAfterAlgorithm.Error, Endianity.Big);
int keySize = dns.ReadUShort(offsetInDns + OffsetAfterAlgorithm.KeySize, Endianity.Big);
if (length < ConstantPartLength + keySize)
return null;
DataSegment key = dns.SubSegment(offsetInDns + OffsetAfterAlgorithm.KeyData, keySize);
int totalReadAfterAlgorithm = OffsetAfterAlgorithm.KeyData + keySize;
offsetInDns += totalReadAfterAlgorithm;
length -= totalReadAfterAlgorithm;
int otherSize = dns.ReadUShort(offsetInDns, Endianity.Big);
if (length != sizeof(ushort) + otherSize)
return null;
DataSegment other = dns.SubSegment(offsetInDns + sizeof(ushort), otherSize);
return new DnsResourceDataTransactionKey(algorithm, inception, expiration, mode, error, key, other);
}
}
} }
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
/// <summary> /// <summary>
/// RFCs 1035, 2136, 2671, 2845, 2930, 4635. /// RFCs 1035, 2136, 2671, 2845, 2930, 4635.
/// </summary> /// </summary>
public enum DnsResponseCode : byte public enum DnsResponseCode : ushort
{ {
/// <summary> /// <summary>
/// RFC 1035. /// RFC 1035.
......
...@@ -407,32 +407,39 @@ ...@@ -407,32 +407,39 @@
/// <summary> /// <summary>
/// RFC 4408. /// RFC 4408.
/// Sender Policy Framework.
/// Payload type: DnsResourceDataText.
/// </summary> /// </summary>
Spf = 99, Spf = 99,
/// <summary> /// <summary>
/// IANA-Reserved. /// IANA-Reserved.
/// Not documented.
/// </summary> /// </summary>
UInfo = 100, UInfo = 100,
/// <summary> /// <summary>
/// IANA-Reserved. /// IANA-Reserved.
/// Not documented.
/// </summary> /// </summary>
Uid = 101, Uid = 101,
/// <summary> /// <summary>
/// IANA-Reserved. /// IANA-Reserved.
/// Not documented.
/// </summary> /// </summary>
Gid = 102, Gid = 102,
/// <summary> /// <summary>
/// IANA-Reserved. /// IANA-Reserved.
/// Not documented.
/// </summary> /// </summary>
UnSpec = 103, UnSpec = 103,
/// <summary> /// <summary>
/// RFC 2930. /// RFC 2930.
/// Transaction Key. /// Transaction Key.
/// Payload type: DnsResourceDataTransactionKey.
/// </summary> /// </summary>
TKey = 249, TKey = 249,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment