Commit 2d605154 authored by Brickner_cp's avatar Brickner_cp

DNS

parent 3bfe71e1
......@@ -137,6 +137,11 @@ namespace PcapDotNet.Packets.TestUtils
random.NextUInt(), random.NextUInt(), random.NextUShort(), random.NextDnsDomainName(),
random.NextDataSegment(random.Next(100)));
case DnsType.Key:
return new DnsResourceDataKey(random.NextBool(), random.NextBool(), random.NextEnum<DnsKeyNameType>(), random.NextFlags<DnsKeySignatory>(),
random.NextEnum<DnsKeyProtocol>(), random.NextEnum<DnsAlgorithm>(),
random.NextBool() ? (ushort?)random.NextUShort() : null, random.NextDataSegment(random.Next(100)));
default:
return new DnsResourceDataAnything(random.NextDataSegment(random.Next(100)));
}
......
......@@ -1324,7 +1324,7 @@ namespace PcapDotNet.Packets.Dns
/// </pre>
/// </summary>
[DnsTypeRegistration(Type = DnsType.Sig)]
public sealed class DnsResourceDataSig : DnsResourceData
public sealed class DnsResourceDataSig : DnsResourceData, IEquatable<DnsResourceDataSig>
{
private static class Offset
{
......@@ -1509,4 +1509,288 @@ namespace PcapDotNet.Packets.Dns
return new DnsResourceDataSig(typeCovered, algorithm, labels, originalTtl, signatureExpiration, signatureInception, keyTag, signersName, signature);
}
}
/// <summary>
/// RFC 2535.
/// </summary>
public enum DnsKeyNameType : byte
{
/// <summary>
/// Indicates that this is a key associated with a "user" or "account" at an end entity, usually a host.
/// The coding of the owner name is that used for the responsible individual mailbox in the SOA and RP RRs:
/// The owner name is the user name as the name of a node under the entity name.
/// For example, "j_random_user" on host.subdomain.example could have a public key associated through a KEY RR with name j_random_user.host.subdomain.example.
/// It could be used in a security protocol where authentication of a user was desired.
/// This key might be useful in IP or other security for a user level service such a telnet, ftp, rlogin, etc.
/// </summary>
UserOrAccountAtEndEntity = 0,
/// <summary>
/// Indicates that this is a zone key for the zone whose name is the KEY RR owner name.
/// This is the public key used for the primary DNS security feature of data origin authentication.
/// Zone KEY RRs occur only at delegation points.
/// </summary>
ZoneKey = 1,
/// <summary>
/// Indicates that this is a key associated with the non-zone "entity" whose name is the RR owner name.
/// This will commonly be a host but could, in some parts of the DNS tree, be some other type of entity such as a telephone number [RFC 1530] or numeric IP address.
/// This is the public key used in connection with DNS request and transaction authentication services.
/// It could also be used in an IP-security protocol where authentication at the host, rather than user, level was desired, such as routing, NTP, etc.
/// </summary>
NonZoneEntity = 2,
}
/// <summary>
/// RFC 2137.
/// </summary>
[Flags]
public enum DnsKeySignatory : byte
{
/// <summary>
/// The general update signatory field bit has no special meaning.
/// If the other three bits are all zero, it must be one so that the field is non-zero to designate that the key is an update key.
/// The meaning of all values of the signatory field with the general bit and one or more other signatory field bits on is reserved.
/// </summary>
General = 1,
/// <summary>
/// If non-zero, this key is authorized to add and update RRs for only a single owner name.
/// If there already exist RRs with one or more names signed by this key, they may be updated but no new name created until the number of existing names is reduced to zero.
/// This bit is meaningful only for mode A dynamic zones and is ignored in mode B dynamic zones.
/// This bit is meaningful only if the owner name is a wildcard.
/// (Any dynamic update KEY with a non-wildcard name is, in effect, a unique name update key.)
/// </summary>
Unique = 2,
/// <summary>
/// If non-zero, this key is authorized to add and delete RRs even if there are other RRs with the same owner name and class that are authenticated by a SIG signed with a different dynamic update KEY.
/// If zero, the key can only authorize updates where any existing RRs of the same owner and class are authenticated by a SIG using the same key.
/// This bit is meaningful only for type A dynamic zones and is ignored in type B dynamic zones.
///
/// Keeping this bit zero on multiple KEY RRs with the same or nested wild card owner names permits multiple entities to exist that can create and delete names but can not effect RRs with different owner names from any they created.
/// In effect, this creates two levels of dynamic update key, strong and weak, where weak keys are limited in interfering with each other but a strong key can interfere with any weak keys or other strong keys.
/// </summary>
Strong = 4,
/// <summary>
/// If nonzero, this key is authorized to attach, detach, and move zones by creating and deleting NS, glue A, and zone KEY RR(s).
/// If zero, the key can not authorize any update that would effect such RRs.
/// This bit is meaningful for both type A and type B dynamic secure zones.
/// NOTE: do not confuse the "zone" signatory field bit with the "zone" key type bit.
/// </summary>
Zone = 8,
}
/// <summary>
/// RFC 2535.
/// </summary>
public enum DnsKeyProtocol : byte
{
/// <summary>
/// Connection with TLS.
/// </summary>
Tls = 1,
/// <summary>
/// Connection with email.
/// </summary>
Email = 2,
/// <summary>
/// DNS security.
/// The protocol field should be set to this value for zone keys and other keys used in DNS security.
/// Implementations that can determine that a key is a DNS security key by the fact that flags label it a zone key or the signatory flag field is non-zero are not required to check the protocol field.
/// </summary>
DnsSec = 3,
/// <summary>
/// Oakley/IPSEC [RFC 2401] protocol.
/// Indicates that this key is valid for use in conjunction with that security standard.
/// This key could be used in connection with secured communication on behalf of an end entity or user whose name is the owner name of the KEY RR if the entity or user flag bits are set.
/// The presence of a KEY resource with this protocol value is an assertion that the host speaks Oakley/IPSEC.
/// </summary>
IpSec = 4,
/// <summary>
/// The key can be used in connection with any protocol for which KEY RR protocol octet values have been defined.
/// The use of this value is discouraged and the use of different keys for different protocols is encouraged.
/// </summary>
All = 255,
}
/// <summary>
/// <pre>
/// +-----+---+---+----------+----+----------+--------+----------+-------+
/// | bit | 0 | 1 | 2 | 3 | 4-5 | 6-7 | 8-11 | 12-15 |
/// +-----+---+---+----------+----+----------+--------+----------+-------+
/// | 0 | A | C | Reserved | XT | Reserved | NAMTYP | Reserved | SIG |
/// +-----+---+---+----------+----+----------+--------+----------+-------+
/// | 16 | protocol | algorithm |
/// +-----+-------------------------------------------+------------------+
/// | 32 | Flags extension (optional) |
/// +-----+--------------------------------------------------------------+
/// | 32 | public key |
/// | or | |
/// | 48 | |
/// +-----+--------------------------------------------------------------+
/// </pre>
/// </summary>
[DnsTypeRegistration(Type = DnsType.Key)]
public sealed class DnsResourceDataKey : DnsResourceDataSimple, IEquatable<DnsResourceDataKey>
{
private static class Offset
{
public const int AuthenticationProhibited = 0;
public const int ConfidentialityProhibited = 0;
public const int IsFlagsExtension = 0;
public const int NameType = 0;
public const int Signatory = 1;
public const int Protocol = sizeof(ushort);
public const int Algorithm = Protocol + sizeof(byte);
public const int FlagsExtension = Algorithm + sizeof(byte);
}
private static class Mask
{
public const byte AuthenticationProhibited = 0x80;
public const byte ConfidentialityProhibited = 0x40;
public const byte IsFlagsExtension = 0x10;
public const byte NameType = 0x03;
public const byte Signatory = 0x0F;
}
private const int ConstantPartLength = Offset.FlagsExtension;
public DnsResourceDataKey()
: this(false, false, DnsKeyNameType.ZoneKey, DnsKeySignatory.Zone, DnsKeyProtocol.All, DnsAlgorithm.None, null, DataSegment.Empty)
{
}
public DnsResourceDataKey(bool authenticationProhibited, bool confidentialityProhibited, DnsKeyNameType nameType, DnsKeySignatory signatory,
DnsKeyProtocol protocol, DnsAlgorithm algorithm, ushort? flagsExtension, DataSegment publicKey)
{
AuthenticationProhibited = authenticationProhibited;
ConfidentialityProhibited = confidentialityProhibited;
FlagsExtension = flagsExtension;
NameType = nameType;
Signatory = signatory;
Protocol = protocol;
Algorithm = algorithm;
PublicKey = publicKey;
}
/// <summary>
/// Use of the key is prohibited for authentication.
/// </summary>
public bool AuthenticationProhibited { get; private set; }
/// <summary>
/// Use of the key is prohibited for confidentiality.
/// </summary>
public bool ConfidentialityProhibited { get; private set; }
/// <summary>
/// The name type.
/// </summary>
public DnsKeyNameType NameType { get; private set; }
/// <summary>
/// If non-zero, indicates that the key can validly sign things as specified in DNS dynamic update.
/// Note that zone keys always have authority to sign any RRs in the zone regardless of the value of the signatory field.
/// </summary>
public DnsKeySignatory Signatory { get; private set; }
/// <summary>
/// It is anticipated that keys stored in DNS will be used in conjunction with a variety of Internet protocols.
/// It is intended that the protocol octet and possibly some of the currently unused (must be zero) bits in the KEY RR flags as specified in the future will be used to indicate a key's validity for different protocols.
/// </summary>
public DnsKeyProtocol Protocol { get; private set; }
/// <summary>
/// The key algorithm parallel to the same field for the SIG resource.
/// </summary>
public DnsAlgorithm Algorithm { get; private set; }
/// <summary>
/// Optional second 16 bit flag field after the algorithm octet and before the key data.
/// Must not be non-null unless one or more such additional bits have been defined and are non-zero.
/// </summary>
public ushort? FlagsExtension { get; private set; }
/// <summary>
/// The public key value.
/// </summary>
public DataSegment PublicKey { get; private set; }
public bool Equals(DnsResourceDataKey other)
{
return other != null &&
AuthenticationProhibited.Equals(other.AuthenticationProhibited) &&
ConfidentialityProhibited.Equals(other.ConfidentialityProhibited) &&
NameType.Equals(other.NameType) &&
Signatory.Equals(other.Signatory) &&
Protocol.Equals(other.Protocol) &&
Algorithm.Equals(other.Algorithm) &&
(FlagsExtension.HasValue
? other.FlagsExtension.HasValue && FlagsExtension.Value.Equals(other.FlagsExtension.Value)
: !other.FlagsExtension.HasValue) &&
PublicKey.Equals(other.PublicKey);
}
public override bool Equals(DnsResourceData other)
{
return Equals(other as DnsResourceDataKey);
}
internal override int GetLength()
{
return ConstantPartLength + (FlagsExtension != null ? sizeof(ushort) : 0) + PublicKey.Length;
}
internal override void WriteDataSimple(byte[] buffer, int offset)
{
byte flagsByte0 = 0;
if (AuthenticationProhibited)
flagsByte0 |= Mask.AuthenticationProhibited;
if (ConfidentialityProhibited)
flagsByte0 |= Mask.ConfidentialityProhibited;
if (FlagsExtension.HasValue)
flagsByte0 |= Mask.IsFlagsExtension;
flagsByte0 |= (byte)((byte)NameType & Mask.NameType);
buffer.Write(offset + Offset.AuthenticationProhibited, flagsByte0);
byte flagsByte1 = 0;
flagsByte1 |= (byte)((byte)Signatory & Mask.Signatory);
buffer.Write(offset+ Offset.Signatory, flagsByte1);
buffer.Write(offset + Offset.Protocol, (byte)Protocol);
buffer.Write(offset + Offset.Algorithm, (byte)Algorithm);
if (FlagsExtension.HasValue)
buffer.Write(offset + Offset.FlagsExtension, FlagsExtension.Value, Endianity.Big);
PublicKey.Write(buffer, offset + Offset.FlagsExtension + (FlagsExtension.HasValue ? sizeof(ushort) : 0));
}
internal override DnsResourceData CreateInstance(DataSegment data)
{
if (data.Length < ConstantPartLength)
return null;
bool authenticationProhibited = data.ReadBool(Offset.AuthenticationProhibited, Mask.AuthenticationProhibited);
bool confidentialityProhibited = data.ReadBool(Offset.ConfidentialityProhibited, Mask.ConfidentialityProhibited);
bool isFlagsExtension = data.ReadBool(Offset.IsFlagsExtension, Mask.IsFlagsExtension);
DnsKeyNameType nameType = (DnsKeyNameType)(data[Offset.NameType] & Mask.NameType);
DnsKeySignatory signatory = (DnsKeySignatory)(data[Offset.Signatory] & Mask.Signatory);
DnsKeyProtocol protocol = (DnsKeyProtocol)data[Offset.Protocol];
DnsAlgorithm algorithm = (DnsAlgorithm)data[Offset.Algorithm];
ushort? flagsExtension = (isFlagsExtension ? ((ushort?)data.ReadUShort(Offset.FlagsExtension, Endianity.Big)) : null);
int publicKeyOffset = Offset.FlagsExtension + (isFlagsExtension ? sizeof(ushort) : 0);
DataSegment publicKey = data.SubSegment(publicKeyOffset, data.Length - publicKeyOffset);
return new DnsResourceDataKey(authenticationProhibited, confidentialityProhibited, nameType, signatory, protocol, algorithm, flagsExtension,
publicKey);
}
}
}
......@@ -180,6 +180,7 @@
/// <summary>
/// RFCs 2535, 3755, 4034.
/// For security key.
/// Payload type: DnsResourceDataKey.
/// </summary>
Key = 25,
......
......@@ -156,7 +156,9 @@ namespace PcapDotNet.TestUtils
List<object> enumValuesAsUnderlyingType = new List<object>(enumValues.Select(value => Convert.ChangeType(value, underlyingType)));
List<ulong> enumValuesAsULong;
if (underlyingType == typeof(ushort))
if (underlyingType == typeof(byte))
enumValuesAsULong = new List<ulong>(enumValuesAsUnderlyingType.Cast<byte>().Select(value => (ulong)value));
else if (underlyingType == typeof(ushort))
enumValuesAsULong = new List<ulong>(enumValuesAsUnderlyingType.Cast<ushort>().Select(value => (ulong)value));
else
throw new ArgumentException("Type " + underlyingType + " is not supported");
......
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