From 8703bf3adf27fd76be503d85f53cd3c206398484 Mon Sep 17 00:00:00 2001 From: marcbarry <> Date: Tue, 24 Sep 2019 16:35:11 +0100 Subject: [PATCH 1/6] remove exotic records and external dependencies --- ARSoft.Tools.Net/ARSoft.Tools.Net.csproj | 115 --- ARSoft.Tools.Net/Dns/Cache/DnsCache.cs | 190 ---- ARSoft.Tools.Net/Dns/Cache/NameserverCache.cs | 135 --- ARSoft.Tools.Net/Dns/DnsClient.cs | 305 ------- ARSoft.Tools.Net/Dns/DnsClientBase.cs | 810 ------------------ ARSoft.Tools.Net/Dns/DnsClientEndpointInfo.cs | 29 - ARSoft.Tools.Net/Dns/DnsMessage.cs | 41 - ARSoft.Tools.Net/Dns/DnsMessageBase.cs | 284 +----- ARSoft.Tools.Net/Dns/DnsQueryOptions.cs | 57 -- ARSoft.Tools.Net/Dns/DnsRecord/AfsdbRecord.cs | 116 --- ARSoft.Tools.Net/Dns/DnsRecord/AplRecord.cs | 207 ----- ARSoft.Tools.Net/Dns/DnsRecord/CAARecord.cs | 100 --- .../Dns/DnsRecord/CDnsKeyRecord.cs | 236 ----- ARSoft.Tools.Net/Dns/DnsRecord/CDsRecord.cs | 113 --- ARSoft.Tools.Net/Dns/DnsRecord/CSyncRecord.cs | 225 ----- ARSoft.Tools.Net/Dns/DnsRecord/CertRecord.cs | 217 ----- ARSoft.Tools.Net/Dns/DnsRecord/DNameRecord.cs | 79 -- ARSoft.Tools.Net/Dns/DnsRecord/DhcidRecord.cs | 79 -- .../Dns/DnsRecord/DnsRecordBase.cs | 95 +- ARSoft.Tools.Net/Dns/DnsRecord/GPosRecord.cs | 102 --- ARSoft.Tools.Net/Dns/DnsRecord/HInfoRecord.cs | 90 -- ARSoft.Tools.Net/Dns/DnsRecord/HipRecord.cs | 135 --- ARSoft.Tools.Net/Dns/DnsRecord/ITextRecord.cs | 8 +- .../Dns/DnsRecord/IpSecKeyRecord.cs | 272 ------ ARSoft.Tools.Net/Dns/DnsRecord/IsdnRecord.cs | 103 --- ARSoft.Tools.Net/Dns/DnsRecord/KxRecord.cs | 90 -- ARSoft.Tools.Net/Dns/DnsRecord/L32Record.cs | 90 -- ARSoft.Tools.Net/Dns/DnsRecord/L64Record.cs | 90 -- ARSoft.Tools.Net/Dns/DnsRecord/LPRecord.cs | 91 -- ARSoft.Tools.Net/Dns/DnsRecord/NIdRecord.cs | 103 --- ARSoft.Tools.Net/Dns/DnsRecord/NsapRecord.cs | 84 -- .../Dns/DnsRecord/OpenPGPKeyRecord.cs | 78 -- ARSoft.Tools.Net/Dns/DnsRecord/PxRecord.cs | 101 --- ARSoft.Tools.Net/Dns/DnsRecord/RtRecord.cs | 90 -- ARSoft.Tools.Net/Dns/DnsRecord/SpfRecord.cs | 58 -- ARSoft.Tools.Net/Dns/DnsRecord/SshFpRecord.cs | 177 ---- ARSoft.Tools.Net/Dns/DnsRecord/TKeyRecord.cs | 204 ----- ARSoft.Tools.Net/Dns/DnsRecord/TlsaRecord.cs | 304 ------- ARSoft.Tools.Net/Dns/DnsRecord/UriRecord.cs | 100 --- ARSoft.Tools.Net/Dns/DnsRecord/WksRecord.cs | 129 --- ARSoft.Tools.Net/Dns/DnsRecord/X25Record.cs | 79 -- .../Dns/DnsSec/DiffieHellmanKeyRecord.cs | 114 --- ARSoft.Tools.Net/Dns/DnsSec/DlvRecord.cs | 113 --- ARSoft.Tools.Net/Dns/DnsSec/DnsKeyFlags.cs | 57 -- ARSoft.Tools.Net/Dns/DnsSec/DnsKeyRecord.cs | 616 ------------- .../Dns/DnsSec/DnsSecAlgorithm.cs | 250 ------ .../Dns/DnsSec/DnsSecDigestType.cs | 67 -- .../Dns/DnsSec/DnsSecValidationException.cs | 34 - .../Dns/DnsSec/DnsSecValidator.cs | 275 ------ ARSoft.Tools.Net/Dns/DnsSec/DsRecord.cs | 186 ---- .../Dns/DnsSec/IInternalDnsSecResolver.cs | 35 - ARSoft.Tools.Net/Dns/DnsSec/KeyRecord.cs | 89 -- ARSoft.Tools.Net/Dns/DnsSec/KeyRecordBase.cs | 358 -------- .../Dns/DnsSec/NSec3HashAlgorithm.cs | 64 -- .../Dns/DnsSec/NSec3ParamRecord.cs | 115 --- ARSoft.Tools.Net/Dns/DnsSec/NSecRecord.cs | 200 ----- ARSoft.Tools.Net/Dns/DnsSec/Nsec3Record.cs | 158 ---- ARSoft.Tools.Net/Dns/DnsSec/RrSigRecord.cs | 257 ------ ARSoft.Tools.Net/Dns/DnsSec/SigRecord.cs | 193 ----- ARSoft.Tools.Net/Dns/DnsServer.cs | 99 +-- .../Dns/DynamicUpdate/DnsUpdateMessage.cs | 7 - .../Dns/EDns/ClientSubnetOption.cs | 111 --- ARSoft.Tools.Net/Dns/EDns/CookieOption.cs | 85 -- .../EDns/DnssecAlgorithmUnderstoodOption.cs | 72 -- .../Dns/EDns/DsHashUnderstoodOption.cs | 72 -- ARSoft.Tools.Net/Dns/EDns/EDnsOptionBase.cs | 45 - ARSoft.Tools.Net/Dns/EDns/EDnsOptionType.cs | 121 --- ARSoft.Tools.Net/Dns/EDns/ExpireOption.cs | 70 -- .../Dns/EDns/LongLivedQueryOption.cs | 174 ---- ARSoft.Tools.Net/Dns/EDns/NsIdOption.cs | 64 -- .../Dns/EDns/Nsec3HashUnderstoodOption.cs | 72 -- ARSoft.Tools.Net/Dns/EDns/OptRecord.cs | 223 ----- ARSoft.Tools.Net/Dns/EDns/OwnerOption.cs | 151 ---- ARSoft.Tools.Net/Dns/EDns/UnknownOption.cs | 62 -- .../Dns/EDns/UpdateLeaseOption.cs | 64 -- ARSoft.Tools.Net/Dns/LlmnrClient.cs | 111 --- ARSoft.Tools.Net/Dns/LlmnrMessage.cs | 148 ---- ARSoft.Tools.Net/Dns/MulticastDnsMessage.cs | 217 ----- .../Dns/MulticastDnsOneShotClient.cs | 111 --- .../Dns/Resolver/DnsResolverExtensions.cs | 156 ---- .../Resolver/DnsSecRecursiveDnsResolver.cs | 361 -------- .../Dns/Resolver/DnsSecResolverExtensions.cs | 64 -- ARSoft.Tools.Net/Dns/Resolver/DnsSecResult.cs | 45 - .../Dns/Resolver/DnsSecValidationResult.cs | 46 - .../Dns/Resolver/DnsStubResolver.cs | 188 ---- ARSoft.Tools.Net/Dns/Resolver/IDnsResolver.cs | 61 -- .../Dns/Resolver/IDnsSecResolver.cs | 56 -- .../Dns/Resolver/IResolverHintStore.cs | 42 - .../Dns/Resolver/RecursiveDnsResolver.cs | 294 ------- .../SelfValidatingDnsSecStubResolver.cs | 220 ----- .../Dns/Resolver/StaticResolverHintStore.cs | 101 --- .../UpdateableResolverHintStoreBase.cs | 117 --- .../Dns/Resolver/ZoneFileResolverHintStore.cs | 70 -- ARSoft.Tools.Net/Dns/TSig/TSigAlgorithm.cs | 82 -- .../Dns/TSig/TSigAlgorithmHelper.cs | 110 --- ARSoft.Tools.Net/Dns/TSig/TSigRecord.cs | 206 ----- ARSoft.Tools.Net/Dns/Zone.cs | 203 +---- ARSoft.Tools.Net/DomainName.cs | 43 - ARSoft.Tools.Net/Net/DaneStream.cs | 434 ---------- ARSoft.Tools.Net/Spf/SenderIDRecord.cs | 195 ----- ARSoft.Tools.Net/Spf/SenderIDScope.cs | 46 - ARSoft.Tools.Net/Spf/SenderIDValidator.cs | 95 -- ARSoft.Tools.Net/Spf/SpfCheckHostParameter.cs | 54 -- ARSoft.Tools.Net/Spf/SpfMechanism.cs | 100 --- ARSoft.Tools.Net/Spf/SpfMechanismType.cs | 76 -- ARSoft.Tools.Net/Spf/SpfModifier.cs | 56 -- ARSoft.Tools.Net/Spf/SpfModifierType.cs | 46 - ARSoft.Tools.Net/Spf/SpfQualifier.cs | 66 -- ARSoft.Tools.Net/Spf/SpfRecord.cs | 99 --- ARSoft.Tools.Net/Spf/SpfRecordBase.cs | 57 -- ARSoft.Tools.Net/Spf/SpfTerm.cs | 111 --- ARSoft.Tools.Net/Spf/SpfValidator.cs | 63 -- ARSoft.Tools.Net/Spf/ValidationResult.cs | 36 - ARSoft.Tools.Net/Spf/ValidatorBase.cs | 644 -------------- 114 files changed, 32 insertions(+), 15882 deletions(-) delete mode 100644 ARSoft.Tools.Net/Dns/Cache/DnsCache.cs delete mode 100644 ARSoft.Tools.Net/Dns/Cache/NameserverCache.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsClient.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsClientBase.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsClientEndpointInfo.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsRecord/AfsdbRecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsRecord/AplRecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsRecord/CAARecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsRecord/CDnsKeyRecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsRecord/CDsRecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsRecord/CSyncRecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsRecord/CertRecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsRecord/DNameRecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsRecord/DhcidRecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsRecord/GPosRecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsRecord/HInfoRecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsRecord/HipRecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsRecord/IpSecKeyRecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsRecord/IsdnRecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsRecord/KxRecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsRecord/L32Record.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsRecord/L64Record.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsRecord/LPRecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsRecord/NIdRecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsRecord/NsapRecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsRecord/OpenPGPKeyRecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsRecord/PxRecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsRecord/RtRecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsRecord/SpfRecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsRecord/SshFpRecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsRecord/TKeyRecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsRecord/TlsaRecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsRecord/UriRecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsRecord/WksRecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsRecord/X25Record.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsSec/DiffieHellmanKeyRecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsSec/DlvRecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsSec/DnsKeyFlags.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsSec/DnsKeyRecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsSec/DnsSecAlgorithm.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsSec/DnsSecDigestType.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsSec/DnsSecValidationException.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsSec/DnsSecValidator.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsSec/DsRecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsSec/IInternalDnsSecResolver.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsSec/KeyRecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsSec/KeyRecordBase.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsSec/NSec3HashAlgorithm.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsSec/NSec3ParamRecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsSec/NSecRecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsSec/Nsec3Record.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsSec/RrSigRecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsSec/SigRecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/EDns/ClientSubnetOption.cs delete mode 100644 ARSoft.Tools.Net/Dns/EDns/CookieOption.cs delete mode 100644 ARSoft.Tools.Net/Dns/EDns/DnssecAlgorithmUnderstoodOption.cs delete mode 100644 ARSoft.Tools.Net/Dns/EDns/DsHashUnderstoodOption.cs delete mode 100644 ARSoft.Tools.Net/Dns/EDns/EDnsOptionBase.cs delete mode 100644 ARSoft.Tools.Net/Dns/EDns/EDnsOptionType.cs delete mode 100644 ARSoft.Tools.Net/Dns/EDns/ExpireOption.cs delete mode 100644 ARSoft.Tools.Net/Dns/EDns/LongLivedQueryOption.cs delete mode 100644 ARSoft.Tools.Net/Dns/EDns/NsIdOption.cs delete mode 100644 ARSoft.Tools.Net/Dns/EDns/Nsec3HashUnderstoodOption.cs delete mode 100644 ARSoft.Tools.Net/Dns/EDns/OptRecord.cs delete mode 100644 ARSoft.Tools.Net/Dns/EDns/OwnerOption.cs delete mode 100644 ARSoft.Tools.Net/Dns/EDns/UnknownOption.cs delete mode 100644 ARSoft.Tools.Net/Dns/EDns/UpdateLeaseOption.cs delete mode 100644 ARSoft.Tools.Net/Dns/LlmnrClient.cs delete mode 100644 ARSoft.Tools.Net/Dns/LlmnrMessage.cs delete mode 100644 ARSoft.Tools.Net/Dns/MulticastDnsMessage.cs delete mode 100644 ARSoft.Tools.Net/Dns/MulticastDnsOneShotClient.cs delete mode 100644 ARSoft.Tools.Net/Dns/Resolver/DnsResolverExtensions.cs delete mode 100644 ARSoft.Tools.Net/Dns/Resolver/DnsSecRecursiveDnsResolver.cs delete mode 100644 ARSoft.Tools.Net/Dns/Resolver/DnsSecResolverExtensions.cs delete mode 100644 ARSoft.Tools.Net/Dns/Resolver/DnsSecResult.cs delete mode 100644 ARSoft.Tools.Net/Dns/Resolver/DnsSecValidationResult.cs delete mode 100644 ARSoft.Tools.Net/Dns/Resolver/DnsStubResolver.cs delete mode 100644 ARSoft.Tools.Net/Dns/Resolver/IDnsResolver.cs delete mode 100644 ARSoft.Tools.Net/Dns/Resolver/IDnsSecResolver.cs delete mode 100644 ARSoft.Tools.Net/Dns/Resolver/IResolverHintStore.cs delete mode 100644 ARSoft.Tools.Net/Dns/Resolver/RecursiveDnsResolver.cs delete mode 100644 ARSoft.Tools.Net/Dns/Resolver/SelfValidatingDnsSecStubResolver.cs delete mode 100644 ARSoft.Tools.Net/Dns/Resolver/StaticResolverHintStore.cs delete mode 100644 ARSoft.Tools.Net/Dns/Resolver/UpdateableResolverHintStoreBase.cs delete mode 100644 ARSoft.Tools.Net/Dns/Resolver/ZoneFileResolverHintStore.cs delete mode 100644 ARSoft.Tools.Net/Dns/TSig/TSigAlgorithm.cs delete mode 100644 ARSoft.Tools.Net/Dns/TSig/TSigAlgorithmHelper.cs delete mode 100644 ARSoft.Tools.Net/Dns/TSig/TSigRecord.cs delete mode 100644 ARSoft.Tools.Net/Net/DaneStream.cs delete mode 100644 ARSoft.Tools.Net/Spf/SenderIDRecord.cs delete mode 100644 ARSoft.Tools.Net/Spf/SenderIDScope.cs delete mode 100644 ARSoft.Tools.Net/Spf/SenderIDValidator.cs delete mode 100644 ARSoft.Tools.Net/Spf/SpfCheckHostParameter.cs delete mode 100644 ARSoft.Tools.Net/Spf/SpfMechanism.cs delete mode 100644 ARSoft.Tools.Net/Spf/SpfMechanismType.cs delete mode 100644 ARSoft.Tools.Net/Spf/SpfModifier.cs delete mode 100644 ARSoft.Tools.Net/Spf/SpfModifierType.cs delete mode 100644 ARSoft.Tools.Net/Spf/SpfQualifier.cs delete mode 100644 ARSoft.Tools.Net/Spf/SpfRecord.cs delete mode 100644 ARSoft.Tools.Net/Spf/SpfRecordBase.cs delete mode 100644 ARSoft.Tools.Net/Spf/SpfTerm.cs delete mode 100644 ARSoft.Tools.Net/Spf/SpfValidator.cs delete mode 100644 ARSoft.Tools.Net/Spf/ValidationResult.cs delete mode 100644 ARSoft.Tools.Net/Spf/ValidatorBase.cs diff --git a/ARSoft.Tools.Net/ARSoft.Tools.Net.csproj b/ARSoft.Tools.Net/ARSoft.Tools.Net.csproj index 4a5324d..397e49d 100644 --- a/ARSoft.Tools.Net/ARSoft.Tools.Net.csproj +++ b/ARSoft.Tools.Net/ARSoft.Tools.Net.csproj @@ -51,33 +51,16 @@ D:\arsoft.pfx - - ..\packages\BouncyCastle.1.8.1\lib\BouncyCastle.Crypto.dll - True - 3.5 - - 3.5 - - - 3.5 - - - - - - - - @@ -85,75 +68,19 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -165,40 +92,13 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -209,23 +109,8 @@ - - - - - - - - - - - - - - - diff --git a/ARSoft.Tools.Net/Dns/Cache/DnsCache.cs b/ARSoft.Tools.Net/Dns/Cache/DnsCache.cs deleted file mode 100644 index a792226..0000000 --- a/ARSoft.Tools.Net/Dns/Cache/DnsCache.cs +++ /dev/null @@ -1,190 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - internal class DnsCacheRecordList : List - { - public DnsSecValidationResult ValidationResult { get; set; } - } - - internal class DnsCache - { - private class CacheKey - { - private readonly DomainName _name; - private readonly RecordClass _recordClass; - private readonly int _hashCode; - private readonly RecordType _recordType; - - public CacheKey(DomainName name, RecordType recordType, RecordClass recordClass) - { - _name = name; - _recordClass = recordClass; - _recordType = recordType; - - _hashCode = name.GetHashCode() ^ (7 * (int) recordType) ^ (11 * (int) recordClass); - } - - - public override int GetHashCode() - { - return _hashCode; - } - - public override bool Equals(object obj) - { - CacheKey other = obj as CacheKey; - - if (other == null) - return false; - - return (_recordType == other._recordType) && (_recordClass == other._recordClass) && (_name.Equals(other._name)); - } - - public override string ToString() - { - return _name + " " + _recordClass.ToShortString() + " " + _recordType.ToShortString(); - } - } - - private class CacheValue - { - public DateTime ExpireDateUtc { get; } - public DnsCacheRecordList Records { get; } - - public CacheValue(DnsCacheRecordList records, int timeToLive) - { - Records = records; - ExpireDateUtc = DateTime.UtcNow.AddSeconds(timeToLive); - } - } - - private readonly ConcurrentDictionary _cache = new ConcurrentDictionary(); - - public void Add(DomainName name, RecordType recordType, RecordClass recordClass, IEnumerable records, DnsSecValidationResult validationResult, int timeToLive) - where TRecord : DnsRecordBase - { - DnsCacheRecordList cacheValues = new DnsCacheRecordList(); - cacheValues.AddRange(records); - cacheValues.ValidationResult = validationResult; - - Add(name, recordType, recordClass, cacheValues, timeToLive); - } - - public void Add(DomainName name, RecordType recordType, RecordClass recordClass, DnsCacheRecordList records, int timeToLive) - { - CacheKey key = new CacheKey(name, recordType, recordClass); - _cache.TryAdd(key, new CacheValue(records, timeToLive)); - } - - public bool TryGetRecords(DomainName name, RecordType recordType, RecordClass recordClass, out List records) - where TRecord : DnsRecordBase - { - CacheKey key = new CacheKey(name, recordType, recordClass); - DateTime utcNow = DateTime.UtcNow; - - CacheValue cacheValue; - if (_cache.TryGetValue(key, out cacheValue)) - { - if (cacheValue.ExpireDateUtc < utcNow) - { - _cache.TryRemove(key, out cacheValue); - records = null; - return false; - } - - int ttl = (int) (cacheValue.ExpireDateUtc - utcNow).TotalSeconds; - - records = new List(); - - records.AddRange(cacheValue - .Records - .OfType() - .Select(x => - { - TRecord record = x.Clone(); - record.TimeToLive = ttl; - return record; - })); - - return true; - } - - records = null; - return false; - } - - public bool TryGetRecords(DomainName name, RecordType recordType, RecordClass recordClass, out DnsCacheRecordList records) - where TRecord : DnsRecordBase - { - CacheKey key = new CacheKey(name, recordType, recordClass); - DateTime utcNow = DateTime.UtcNow; - - CacheValue cacheValue; - if (_cache.TryGetValue(key, out cacheValue)) - { - if (cacheValue.ExpireDateUtc < utcNow) - { - _cache.TryRemove(key, out cacheValue); - records = null; - return false; - } - - int ttl = (int) (cacheValue.ExpireDateUtc - utcNow).TotalSeconds; - - records = new DnsCacheRecordList(); - - records.AddRange(cacheValue - .Records - .OfType() - .Select(x => - { - TRecord record = x.Clone(); - record.TimeToLive = ttl; - return record; - })); - - records.ValidationResult = cacheValue.Records.ValidationResult; - - return true; - } - - records = null; - return false; - } - - public void RemoveExpiredItems() - { - DateTime utcNow = DateTime.UtcNow; - - foreach (var kvp in _cache) - { - CacheValue tmp; - if (kvp.Value.ExpireDateUtc < utcNow) - _cache.TryRemove(kvp.Key, out tmp); - } - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/Cache/NameserverCache.cs b/ARSoft.Tools.Net/Dns/Cache/NameserverCache.cs deleted file mode 100644 index f8a8aea..0000000 --- a/ARSoft.Tools.Net/Dns/Cache/NameserverCache.cs +++ /dev/null @@ -1,135 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - internal class NameserverCache - { - private class CacheValue - { - public DateTime ExpireDateUtc { get; } - public IPAddress Address { get; } - - public CacheValue(int timeToLive, IPAddress address) - { - ExpireDateUtc = DateTime.UtcNow.AddSeconds(timeToLive); - Address = address; - } - - public override int GetHashCode() - { - return Address.GetHashCode(); - } - - public override bool Equals(object obj) - { - CacheValue second = obj as CacheValue; - - if (second == null) - return false; - - return Address.Equals(second.Address); - } - } - - private readonly ConcurrentDictionary> _cache = new ConcurrentDictionary>(); - - public void Add(DomainName zoneName, IPAddress address, int timeToLive) - { - HashSet addresses; - - if (_cache.TryGetValue(zoneName, out addresses)) - { - lock (addresses) - { - addresses.Add(new CacheValue(timeToLive, address)); - } - } - else - { - _cache.TryAdd(zoneName, new HashSet() { new CacheValue(timeToLive, address) }); - } - } - - public bool TryGetAddresses(DomainName zoneName, out List addresses) - { - DateTime utcNow = DateTime.UtcNow; - - HashSet cacheValues; - if (_cache.TryGetValue(zoneName, out cacheValues)) - { - addresses = new List(); - bool needsCleanup = false; - - lock (cacheValues) - { - foreach (CacheValue cacheValue in cacheValues) - { - if (cacheValue.ExpireDateUtc < utcNow) - { - needsCleanup = true; - } - else - { - addresses.Add(cacheValue.Address); - } - } - - if (needsCleanup) - { - cacheValues.RemoveWhere(x => x.ExpireDateUtc < utcNow); - if (cacheValues.Count == 0) -#pragma warning disable 0728 - _cache.TryRemove(zoneName, out cacheValues); -#pragma warning restore 0728 - } - } - - if (addresses.Count > 0) - return true; - } - - addresses = null; - return false; - } - - public void RemoveExpiredItems() - { - DateTime utcNow = DateTime.UtcNow; - - foreach (var kvp in _cache) - { - lock (kvp.Value) - { - HashSet tmp; - - kvp.Value.RemoveWhere(x => x.ExpireDateUtc < utcNow); - if (kvp.Value.Count == 0) - _cache.TryRemove(kvp.Key, out tmp); - } - } - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsClient.cs b/ARSoft.Tools.Net/Dns/DnsClient.cs deleted file mode 100644 index 11a2b67..0000000 --- a/ARSoft.Tools.Net/Dns/DnsClient.cs +++ /dev/null @@ -1,305 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Net; -using System.Net.NetworkInformation; -using System.Net.Sockets; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using ARSoft.Tools.Net.Dns.DynamicUpdate; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Provides a client for querying dns records - /// - public class DnsClient : DnsClientBase - { - /// - /// Returns a default instance of the DnsClient, which uses the configured dns servers of the executing computer and a - /// query timeout of 10 seconds. - /// - public static DnsClient Default { get; private set; } - - /// - /// Gets or sets a value indicationg whether queries can be sent using UDP. - /// - public new bool IsUdpEnabled - { - get { return base.IsUdpEnabled; } - set { base.IsUdpEnabled = value; } - } - - /// - /// Gets or sets a value indicationg whether queries can be sent using TCP. - /// - public new bool IsTcpEnabled - { - get { return base.IsTcpEnabled; } - set { base.IsTcpEnabled = value; } - } - - static DnsClient() - { - Default = new DnsClient(GetLocalConfiguredDnsServers(), 10000) { IsResponseValidationEnabled = true }; - } - - /// - /// Provides a new instance with custom dns server and query timeout - /// - /// The IPAddress of the dns server to use - /// Query timeout in milliseconds - public DnsClient(IPAddress dnsServer, int queryTimeout) - : this(new List { dnsServer }, queryTimeout) {} - - /// - /// Provides a new instance with custom dns servers and query timeout - /// - /// The IPAddresses of the dns servers to use - /// Query timeout in milliseconds - public DnsClient(IEnumerable dnsServers, int queryTimeout) - : base(dnsServers, queryTimeout, 53) - { - IsUdpEnabled = true; - IsTcpEnabled = true; - } - - protected override int MaximumQueryMessageSize => 512; - - /// - /// Queries a dns server for specified records. - /// - /// Domain, that should be queried - /// Type the should be queried - /// Class the should be queried - /// Options for the query - /// The complete response of the dns server - public DnsMessage Resolve(DomainName name, RecordType recordType = RecordType.A, RecordClass recordClass = RecordClass.INet, DnsQueryOptions options = null) - { - if (name == null) - throw new ArgumentNullException(nameof(name), "Name must be provided"); - - DnsMessage message = new DnsMessage() { IsQuery = true, OperationCode = OperationCode.Query, IsRecursionDesired = true, IsEDnsEnabled = true }; - - if (options == null) - { - message.IsRecursionDesired = true; - message.IsEDnsEnabled = true; - } - else - { - message.IsRecursionDesired = options.IsRecursionDesired; - message.IsCheckingDisabled = options.IsCheckingDisabled; - message.EDnsOptions = options.EDnsOptions; - } - - message.Questions.Add(new DnsQuestion(name, recordType, recordClass)); - - return SendMessage(message); - } - - /// - /// Queries a dns server for specified records as an asynchronous operation. - /// - /// Domain, that should be queried - /// Type the should be queried - /// Class the should be queried - /// Options for the query - /// The token to monitor cancellation requests - /// The complete response of the dns server - public Task ResolveAsync(DomainName name, RecordType recordType = RecordType.A, RecordClass recordClass = RecordClass.INet, DnsQueryOptions options = null, CancellationToken token = default(CancellationToken)) - { - if (name == null) - throw new ArgumentNullException(nameof(name), "Name must be provided"); - - DnsMessage message = new DnsMessage() { IsQuery = true, OperationCode = OperationCode.Query, IsRecursionDesired = true, IsEDnsEnabled = true }; - - if (options == null) - { - message.IsRecursionDesired = true; - message.IsEDnsEnabled = true; - } - else - { - message.IsRecursionDesired = options.IsRecursionDesired; - message.IsCheckingDisabled = options.IsCheckingDisabled; - message.EDnsOptions = options.EDnsOptions; - } - - message.Questions.Add(new DnsQuestion(name, recordType, recordClass)); - - return SendMessageAsync(message, token); - } - - /// - /// Send a custom message to the dns server and returns the answer. - /// - /// Message, that should be send to the dns server - /// The complete response of the dns server - public DnsMessage SendMessage(DnsMessage message) - { - if (message == null) - throw new ArgumentNullException(nameof(message)); - - if ((message.Questions == null) || (message.Questions.Count == 0)) - throw new ArgumentException("At least one question must be provided", nameof(message)); - - return SendMessage(message); - } - - /// - /// Send a custom message to the dns server and returns the answer as an asynchronous operation. - /// - /// Message, that should be send to the dns server - /// The token to monitor cancellation requests - /// The complete response of the dns server - public Task SendMessageAsync(DnsMessage message, CancellationToken token = default(CancellationToken)) - { - if (message == null) - throw new ArgumentNullException(nameof(message)); - - if ((message.Questions == null) || (message.Questions.Count == 0)) - throw new ArgumentException("At least one question must be provided", nameof(message)); - - return SendMessageAsync(message, token); - } - - /// - /// Send an dynamic update to the dns server and returns the answer. - /// - /// Update, that should be send to the dns server - /// The complete response of the dns server - public DnsUpdateMessage SendUpdate(DnsUpdateMessage message) - { - if (message == null) - throw new ArgumentNullException(nameof(message)); - - if (message.ZoneName == null) - throw new ArgumentException("Zone name must be provided", nameof(message)); - - return SendMessage(message); - } - - /// - /// Send an dynamic update to the dns server and returns the answer as an asynchronous operation. - /// - /// Update, that should be send to the dns server - /// The token to monitor cancellation requests - /// The complete response of the dns server - public Task SendUpdateAsync(DnsUpdateMessage message, CancellationToken token = default(CancellationToken)) - { - if (message == null) - throw new ArgumentNullException(nameof(message)); - - if (message.ZoneName == null) - throw new ArgumentException("Zone name must be provided", nameof(message)); - - return SendMessageAsync(message, token); - } - - /// - /// Returns a list of the local configured DNS servers. - /// - /// - public static List GetLocalConfiguredDnsServers() - { - List res = new List(); - - try - { - foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces()) - { - if ((nic.OperationalStatus == OperationalStatus.Up) && (nic.NetworkInterfaceType != NetworkInterfaceType.Loopback)) - { - foreach (IPAddress dns in nic.GetIPProperties().DnsAddresses) - { - // only use servers defined in draft-ietf-ipngwg-dns-discovery if they are in the same subnet - // fec0::/10 is marked deprecated in RFC 3879, so nobody should use these addresses - if (dns.AddressFamily == AddressFamily.InterNetworkV6) - { - IPAddress unscoped = new IPAddress(dns.GetAddressBytes()); - if (unscoped.Equals(IPAddress.Parse("fec0:0:0:ffff::1")) - || unscoped.Equals(IPAddress.Parse("fec0:0:0:ffff::2")) - || unscoped.Equals(IPAddress.Parse("fec0:0:0:ffff::3"))) - { - if (!nic.GetIPProperties().UnicastAddresses.Any(x => x.Address.GetNetworkAddress(10).Equals(IPAddress.Parse("fec0::")))) - continue; - } - } - - if (!res.Contains(dns)) - res.Add(dns); - } - } - } - } - catch (Exception e) - { - Trace.TraceError("Configured nameserver couldn't be determined: " + e); - } - - // try parsing resolv.conf since getting data by NetworkInterface is not supported on non-windows mono - if ((res.Count == 0) && ((Environment.OSVersion.Platform == PlatformID.Unix) || (Environment.OSVersion.Platform == PlatformID.MacOSX))) - { - try - { - using (StreamReader reader = File.OpenText("/etc/resolv.conf")) - { - string line; - while ((line = reader.ReadLine()) != null) - { - int commentStart = line.IndexOf('#'); - if (commentStart != -1) - { - line = line.Substring(0, commentStart); - } - - string[] lineData = line.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); - IPAddress dns; - if ((lineData.Length == 2) && (lineData[0] == "nameserver") && (IPAddress.TryParse(lineData[1], out dns))) - { - res.Add(dns); - } - } - } - } - catch (Exception e) - { - Trace.TraceError("/etc/resolv.conf could not be parsed: " + e); - } - } - - if (res.Count == 0) - { - // fallback: use the public dns-resolvers of google - res.Add(IPAddress.Parse("2001:4860:4860::8844")); - res.Add(IPAddress.Parse("2001:4860:4860::8888")); - res.Add(IPAddress.Parse("8.8.4.4")); - res.Add(IPAddress.Parse("8.8.8.8")); - } - - return res.OrderBy(x => x.AddressFamily == AddressFamily.InterNetworkV6 ? 1 : 0).ToList(); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsClientBase.cs b/ARSoft.Tools.Net/Dns/DnsClientBase.cs deleted file mode 100644 index 7afc507..0000000 --- a/ARSoft.Tools.Net/Dns/DnsClientBase.cs +++ /dev/null @@ -1,810 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Net; -using System.Net.NetworkInformation; -using System.Net.Sockets; -using System.Threading; -using System.Threading.Tasks; -using Org.BouncyCastle.Crypto.Prng; -using Org.BouncyCastle.Security; - -namespace ARSoft.Tools.Net.Dns -{ - public abstract class DnsClientBase - { - private static readonly SecureRandom _secureRandom = new SecureRandom(new CryptoApiRandomGenerator()); - - private readonly List _servers; - private readonly bool _isAnyServerMulticast; - private readonly int _port; - - internal DnsClientBase(IEnumerable servers, int queryTimeout, int port) - { - _servers = servers.OrderBy(s => s.AddressFamily == AddressFamily.InterNetworkV6 ? 0 : 1).ToList(); - _isAnyServerMulticast = _servers.Any(s => s.IsMulticast()); - QueryTimeout = queryTimeout; - _port = port; - } - - /// - /// Milliseconds after which a query times out. - /// - public int QueryTimeout { get; } - - /// - /// Gets or set a value indicating whether the response is validated as described in - /// - /// draft-vixie-dnsext-dns0x20-00 - /// - /// - public bool IsResponseValidationEnabled { get; set; } - - /// - /// Gets or set a value indicating whether the query labels are used for additional validation as described in - /// - /// draft-vixie-dnsext-dns0x20-00 - /// - /// - // ReSharper disable once InconsistentNaming - public bool Is0x20ValidationEnabled { get; set; } - - protected abstract int MaximumQueryMessageSize { get; } - - protected virtual bool IsUdpEnabled { get; set; } - - protected virtual bool IsTcpEnabled { get; set; } - - protected TMessage SendMessage(TMessage message) - where TMessage : DnsMessageBase, new() - { - int messageLength; - byte[] messageData; - DnsServer.SelectTsigKey tsigKeySelector; - byte[] tsigOriginalMac; - - PrepareMessage(message, out messageLength, out messageData, out tsigKeySelector, out tsigOriginalMac); - - bool sendByTcp = ((messageLength > MaximumQueryMessageSize) || message.IsTcpUsingRequested || !IsUdpEnabled); - - var endpointInfos = GetEndpointInfos(); - - for (int i = 0; i < endpointInfos.Count; i++) - { - TcpClient tcpClient = null; - NetworkStream tcpStream = null; - - try - { - var endpointInfo = endpointInfos[i]; - - IPAddress responderAddress; - byte[] resultData = sendByTcp ? QueryByTcp(endpointInfo.ServerAddress, messageData, messageLength, ref tcpClient, ref tcpStream, out responderAddress) : QueryByUdp(endpointInfo, messageData, messageLength, out responderAddress); - - if (resultData != null) - { - TMessage result; - - try - { - result = DnsMessageBase.Parse(resultData, tsigKeySelector, tsigOriginalMac); - } - catch (Exception e) - { - Trace.TraceError("Error on dns query: " + e); - continue; - } - - if (!ValidateResponse(message, result)) - continue; - - if ((result.ReturnCode == ReturnCode.ServerFailure) && (i != endpointInfos.Count - 1)) - { - continue; - } - - if (result.IsTcpResendingRequested) - { - resultData = QueryByTcp(responderAddress, messageData, messageLength, ref tcpClient, ref tcpStream, out responderAddress); - if (resultData != null) - { - TMessage tcpResult; - - try - { - tcpResult = DnsMessageBase.Parse(resultData, tsigKeySelector, tsigOriginalMac); - } - catch (Exception e) - { - Trace.TraceError("Error on dns query: " + e); - continue; - } - - if (tcpResult.ReturnCode == ReturnCode.ServerFailure) - { - if (i != endpointInfos.Count - 1) - { - continue; - } - } - else - { - result = tcpResult; - } - } - } - - bool isTcpNextMessageWaiting = result.IsTcpNextMessageWaiting(false); - bool isSucessfullFinished = true; - - while (isTcpNextMessageWaiting) - { - resultData = QueryByTcp(responderAddress, null, 0, ref tcpClient, ref tcpStream, out responderAddress); - if (resultData != null) - { - TMessage tcpResult; - - try - { - tcpResult = DnsMessageBase.Parse(resultData, tsigKeySelector, tsigOriginalMac); - } - catch (Exception e) - { - Trace.TraceError("Error on dns query: " + e); - isSucessfullFinished = false; - break; - } - - if (tcpResult.ReturnCode == ReturnCode.ServerFailure) - { - isSucessfullFinished = false; - break; - } - else - { - result.AnswerRecords.AddRange(tcpResult.AnswerRecords); - isTcpNextMessageWaiting = tcpResult.IsTcpNextMessageWaiting(true); - } - } - else - { - isSucessfullFinished = false; - break; - } - } - - if (isSucessfullFinished) - return result; - } - } - finally - { - try - { - tcpStream?.Dispose(); - tcpClient?.Close(); - } - catch - { - // ignored - } - } - } - - return null; - } - - protected List SendMessageParallel(TMessage message) - where TMessage : DnsMessageBase, new() - { - Task> result = SendMessageParallelAsync(message, default(CancellationToken)); - - result.Wait(); - - return result.Result; - } - - private bool ValidateResponse(TMessage message, TMessage result) - where TMessage : DnsMessageBase - { - if (IsResponseValidationEnabled) - { - if ((result.ReturnCode == ReturnCode.NoError) || (result.ReturnCode == ReturnCode.NxDomain)) - { - if (message.TransactionID != result.TransactionID) - return false; - - if ((message.Questions == null) || (result.Questions == null)) - return false; - - if ((message.Questions.Count != result.Questions.Count)) - return false; - - for (int j = 0; j < message.Questions.Count; j++) - { - DnsQuestion queryQuestion = message.Questions[j]; - DnsQuestion responseQuestion = result.Questions[j]; - - if ((queryQuestion.RecordClass != responseQuestion.RecordClass) - || (queryQuestion.RecordType != responseQuestion.RecordType) - || (!queryQuestion.Name.Equals(responseQuestion.Name, false))) - { - return false; - } - } - } - } - - return true; - } - - private void PrepareMessage(TMessage message, out int messageLength, out byte[] messageData, out DnsServer.SelectTsigKey tsigKeySelector, out byte[] tsigOriginalMac) - where TMessage : DnsMessageBase, new() - { - if (message.TransactionID == 0) - { - message.TransactionID = (ushort) _secureRandom.Next(1, 0xffff); - } - - if (Is0x20ValidationEnabled) - { - message.Questions.ForEach(q => q.Name = q.Name.Add0x20Bits()); - } - - messageLength = message.Encode(false, out messageData); - - if (message.TSigOptions != null) - { - tsigKeySelector = (n, a) => message.TSigOptions.KeyData; - tsigOriginalMac = message.TSigOptions.Mac; - } - else - { - tsigKeySelector = null; - tsigOriginalMac = null; - } - } - - private byte[] QueryByUdp(DnsClientEndpointInfo endpointInfo, byte[] messageData, int messageLength, out IPAddress responderAddress) - { - using (var udpClient = new Socket(endpointInfo.LocalAddress.AddressFamily, SocketType.Dgram, ProtocolType.Udp)) - { - try - { - udpClient.ReceiveTimeout = QueryTimeout; - - PrepareAndBindUdpSocket(endpointInfo, udpClient); - - EndPoint serverEndpoint = new IPEndPoint(endpointInfo.ServerAddress, _port); - - udpClient.SendTo(messageData, messageLength, SocketFlags.None, serverEndpoint); - - if (endpointInfo.IsMulticast) - serverEndpoint = new IPEndPoint(udpClient.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, _port); - - byte[] buffer = new byte[65535]; - int length = udpClient.ReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref serverEndpoint); - - responderAddress = ((IPEndPoint) serverEndpoint).Address; - - byte[] res = new byte[length]; - Buffer.BlockCopy(buffer, 0, res, 0, length); - return res; - } - catch (Exception e) - { - Trace.TraceError("Error on dns query: " + e); - responderAddress = default(IPAddress); - return null; - } - } - } - - private void PrepareAndBindUdpSocket(DnsClientEndpointInfo endpointInfo, Socket udpClient) - { - if (endpointInfo.IsMulticast) - { - udpClient.Bind(new IPEndPoint(endpointInfo.LocalAddress, 0)); - } - else - { - udpClient.Connect(endpointInfo.ServerAddress, _port); - } - } - - private byte[] QueryByTcp(IPAddress nameServer, byte[] messageData, int messageLength, ref TcpClient tcpClient, ref NetworkStream tcpStream, out IPAddress responderAddress) - { - responderAddress = nameServer; - - if (!IsTcpEnabled) - return null; - - IPEndPoint endPoint = new IPEndPoint(nameServer, _port); - - try - { - if (tcpClient == null) - { - tcpClient = new TcpClient(nameServer.AddressFamily) - { - ReceiveTimeout = QueryTimeout, - SendTimeout = QueryTimeout - }; - - if (!tcpClient.TryConnect(endPoint, QueryTimeout)) - return null; - - tcpStream = tcpClient.GetStream(); - } - - int tmp = 0; - byte[] lengthBuffer = new byte[2]; - - if (messageLength > 0) - { - DnsMessageBase.EncodeUShort(lengthBuffer, ref tmp, (ushort) messageLength); - - tcpStream.Write(lengthBuffer, 0, 2); - tcpStream.Write(messageData, 0, messageLength); - } - - if (!TryRead(tcpClient, tcpStream, lengthBuffer, 2)) - return null; - - tmp = 0; - int length = DnsMessageBase.ParseUShort(lengthBuffer, ref tmp); - - byte[] resultData = new byte[length]; - - return TryRead(tcpClient, tcpStream, resultData, length) ? resultData : null; - } - catch (Exception e) - { - Trace.TraceError("Error on dns query: " + e); - return null; - } - } - - private bool TryRead(TcpClient client, NetworkStream stream, byte[] buffer, int length) - { - int readBytes = 0; - - while (readBytes < length) - { - if (!client.IsConnected()) - return false; - - readBytes += stream.Read(buffer, readBytes, length - readBytes); - } - - return true; - } - - protected async Task SendMessageAsync(TMessage message, CancellationToken token) - where TMessage : DnsMessageBase, new() - { - int messageLength; - byte[] messageData; - DnsServer.SelectTsigKey tsigKeySelector; - byte[] tsigOriginalMac; - - PrepareMessage(message, out messageLength, out messageData, out tsigKeySelector, out tsigOriginalMac); - - bool sendByTcp = ((messageLength > MaximumQueryMessageSize) || message.IsTcpUsingRequested || !IsUdpEnabled); - - var endpointInfos = GetEndpointInfos(); - - for (int i = 0; i < endpointInfos.Count; i++) - { - token.ThrowIfCancellationRequested(); - - var endpointInfo = endpointInfos[i]; - QueryResponse resultData = null; - - try - { - resultData = await (sendByTcp ? QueryByTcpAsync(endpointInfo.ServerAddress, messageData, messageLength, null, null, token) : QuerySingleResponseByUdpAsync(endpointInfo, messageData, messageLength, token)); - - if (resultData == null) - return null; - - TMessage result; - - try - { - result = DnsMessageBase.Parse(resultData.Buffer, tsigKeySelector, tsigOriginalMac); - } - catch (Exception e) - { - Trace.TraceError("Error on dns query: " + e); - continue; - } - - if (!ValidateResponse(message, result)) - continue; - - if ((result.ReturnCode != ReturnCode.NoError) && (result.ReturnCode != ReturnCode.NxDomain) && (i != endpointInfos.Count - 1)) - continue; - - if (result.IsTcpResendingRequested) - { - resultData = await QueryByTcpAsync(resultData.ResponderAddress, messageData, messageLength, resultData.TcpClient, resultData.TcpStream, token); - if (resultData != null) - { - TMessage tcpResult; - - try - { - tcpResult = DnsMessageBase.Parse(resultData.Buffer, tsigKeySelector, tsigOriginalMac); - } - catch (Exception e) - { - Trace.TraceError("Error on dns query: " + e); - return null; - } - - if (tcpResult.ReturnCode == ReturnCode.ServerFailure) - { - return result; - } - else - { - result = tcpResult; - } - } - } - - bool isTcpNextMessageWaiting = result.IsTcpNextMessageWaiting(false); - bool isSucessfullFinished = true; - - while (isTcpNextMessageWaiting) - { - // ReSharper disable once PossibleNullReferenceException - resultData = await QueryByTcpAsync(resultData.ResponderAddress, null, 0, resultData.TcpClient, resultData.TcpStream, token); - if (resultData != null) - { - TMessage tcpResult; - - try - { - tcpResult = DnsMessageBase.Parse(resultData.Buffer, tsigKeySelector, tsigOriginalMac); - } - catch (Exception e) - { - Trace.TraceError("Error on dns query: " + e); - isSucessfullFinished = false; - break; - } - - if (tcpResult.ReturnCode == ReturnCode.ServerFailure) - { - isSucessfullFinished = false; - break; - } - else - { - result.AnswerRecords.AddRange(tcpResult.AnswerRecords); - isTcpNextMessageWaiting = tcpResult.IsTcpNextMessageWaiting(true); - } - } - else - { - isSucessfullFinished = false; - break; - } - } - - if (isSucessfullFinished) - return result; - } - finally - { - if (resultData != null) - { - try - { - resultData.TcpStream?.Dispose(); - resultData.TcpClient?.Close(); - } - catch - { - // ignored - } - } - } - } - - return null; - } - - private async Task QuerySingleResponseByUdpAsync(DnsClientEndpointInfo endpointInfo, byte[] messageData, int messageLength, CancellationToken token) - { - try - { - if (endpointInfo.IsMulticast) - { - using (UdpClient udpClient = new UdpClient(new IPEndPoint(endpointInfo.LocalAddress, 0))) - { - IPEndPoint serverEndpoint = new IPEndPoint(endpointInfo.ServerAddress, _port); - await udpClient.SendAsync(messageData, messageLength, serverEndpoint); - - udpClient.Client.SendTimeout = QueryTimeout; - udpClient.Client.ReceiveTimeout = QueryTimeout; - - UdpReceiveResult response = await udpClient.ReceiveAsync(QueryTimeout, token); - return new QueryResponse(response.Buffer, response.RemoteEndPoint.Address); - } - } - else - { - using (UdpClient udpClient = new UdpClient(endpointInfo.LocalAddress.AddressFamily)) - { - udpClient.Connect(endpointInfo.ServerAddress, _port); - - udpClient.Client.SendTimeout = QueryTimeout; - udpClient.Client.ReceiveTimeout = QueryTimeout; - - await udpClient.SendAsync(messageData, messageLength); - - UdpReceiveResult response = await udpClient.ReceiveAsync(QueryTimeout, token); - return new QueryResponse(response.Buffer, response.RemoteEndPoint.Address); - } - } - } - catch (Exception e) - { - Trace.TraceError("Error on dns query: " + e); - return null; - } - } - - private class QueryResponse - { - public byte[] Buffer { get; } - public IPAddress ResponderAddress { get; } - - public TcpClient TcpClient { get; } - public NetworkStream TcpStream { get; } - - public QueryResponse(byte[] buffer, IPAddress responderAddress) - { - Buffer = buffer; - ResponderAddress = responderAddress; - } - - public QueryResponse(byte[] buffer, IPAddress responderAddress, TcpClient tcpClient, NetworkStream tcpStream) - { - Buffer = buffer; - ResponderAddress = responderAddress; - TcpClient = tcpClient; - TcpStream = tcpStream; - } - } - - private async Task QueryByTcpAsync(IPAddress nameServer, byte[] messageData, int messageLength, TcpClient tcpClient, NetworkStream tcpStream, CancellationToken token) - { - if (!IsTcpEnabled) - return null; - - try - { - if (tcpClient == null) - { - tcpClient = new TcpClient(nameServer.AddressFamily) - { - ReceiveTimeout = QueryTimeout, - SendTimeout = QueryTimeout - }; - - if (!await tcpClient.TryConnectAsync(nameServer, _port, QueryTimeout, token)) - { - return null; - } - - tcpStream = tcpClient.GetStream(); - } - - int tmp = 0; - byte[] lengthBuffer = new byte[2]; - - if (messageLength > 0) - { - DnsMessageBase.EncodeUShort(lengthBuffer, ref tmp, (ushort) messageLength); - - await tcpStream.WriteAsync(lengthBuffer, 0, 2, token); - await tcpStream.WriteAsync(messageData, 0, messageLength, token); - } - - if (!await TryReadAsync(tcpClient, tcpStream, lengthBuffer, 2, token)) - return null; - - tmp = 0; - int length = DnsMessageBase.ParseUShort(lengthBuffer, ref tmp); - - byte[] resultData = new byte[length]; - - return await TryReadAsync(tcpClient, tcpStream, resultData, length, token) ? new QueryResponse(resultData, nameServer, tcpClient, tcpStream) : null; - } - catch (Exception e) - { - Trace.TraceError("Error on dns query: " + e); - return null; - } - } - - private async Task TryReadAsync(TcpClient client, NetworkStream stream, byte[] buffer, int length, CancellationToken token) - { - int readBytes = 0; - - while (readBytes < length) - { - if (token.IsCancellationRequested || !client.IsConnected()) - return false; - - readBytes += await stream.ReadAsync(buffer, readBytes, length - readBytes, token); - } - - return true; - } - - protected async Task> SendMessageParallelAsync(TMessage message, CancellationToken token) - where TMessage : DnsMessageBase, new() - { - int messageLength; - byte[] messageData; - DnsServer.SelectTsigKey tsigKeySelector; - byte[] tsigOriginalMac; - - PrepareMessage(message, out messageLength, out messageData, out tsigKeySelector, out tsigOriginalMac); - - if (messageLength > MaximumQueryMessageSize) - throw new ArgumentException("Message exceeds maximum size"); - - if (message.IsTcpUsingRequested) - throw new NotSupportedException("Using tcp is not supported in parallel mode"); - - BlockingCollection results = new BlockingCollection(); - CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); - - // ReSharper disable once ReturnValueOfPureMethodIsNotUsed - GetEndpointInfos().Select(x => SendMessageParallelAsync(x, message, messageData, messageLength, tsigKeySelector, tsigOriginalMac, results, CancellationTokenSource.CreateLinkedTokenSource(token, cancellationTokenSource.Token).Token)).ToArray(); - - await Task.Delay(QueryTimeout, token); - - cancellationTokenSource.Cancel(); - - return results.ToList(); - } - - private async Task SendMessageParallelAsync(DnsClientEndpointInfo endpointInfo, TMessage message, byte[] messageData, int messageLength, DnsServer.SelectTsigKey tsigKeySelector, byte[] tsigOriginalMac, BlockingCollection results, CancellationToken token) - where TMessage : DnsMessageBase, new() - { - using (UdpClient udpClient = new UdpClient(new IPEndPoint(endpointInfo.LocalAddress, 0))) - { - IPEndPoint serverEndpoint = new IPEndPoint(endpointInfo.ServerAddress, _port); - await udpClient.SendAsync(messageData, messageLength, serverEndpoint); - - udpClient.Client.SendTimeout = QueryTimeout; - udpClient.Client.ReceiveTimeout = QueryTimeout; - - while (true) - { - TMessage result; - UdpReceiveResult response = await udpClient.ReceiveAsync(Int32.MaxValue, token); - - try - { - result = DnsMessageBase.Parse(response.Buffer, tsigKeySelector, tsigOriginalMac); - } - catch (Exception e) - { - Trace.TraceError("Error on dns query: " + e); - continue; - } - - if (!ValidateResponse(message, result)) - continue; - - if (result.ReturnCode == ReturnCode.ServerFailure) - continue; - - results.Add(result, token); - - if (token.IsCancellationRequested) - break; - } - } - } - - private List GetEndpointInfos() - { - List endpointInfos; - if (_isAnyServerMulticast) - { - var localIPs = NetworkInterface.GetAllNetworkInterfaces() - .Where(n => n.SupportsMulticast && (n.OperationalStatus == OperationalStatus.Up) && (n.NetworkInterfaceType != NetworkInterfaceType.Loopback)) - .SelectMany(n => n.GetIPProperties().UnicastAddresses.Select(a => a.Address)) - .Where(a => !IPAddress.IsLoopback(a) && ((a.AddressFamily == AddressFamily.InterNetwork) || a.IsIPv6LinkLocal)) - .ToList(); - - endpointInfos = _servers - .SelectMany( - s => - { - if (s.IsMulticast()) - { - return localIPs - .Where(l => l.AddressFamily == s.AddressFamily) - .Select( - l => new DnsClientEndpointInfo - { - IsMulticast = true, - ServerAddress = s, - LocalAddress = l - }); - } - else - { - return new[] - { - new DnsClientEndpointInfo - { - IsMulticast = false, - ServerAddress = s, - LocalAddress = s.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any - } - }; - } - }).ToList(); - } - else - { - endpointInfos = _servers - .Where(x => IsIPv6Enabled || (x.AddressFamily == AddressFamily.InterNetwork)) - .Select( - s => new DnsClientEndpointInfo - { - IsMulticast = false, - ServerAddress = s, - LocalAddress = s.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any - } - ).ToList(); - } - return endpointInfos; - } - - private static bool IsIPv6Enabled { get; } = IsAnyIPv6Configured(); - - private static readonly IPAddress _ipvMappedNetworkAddress = IPAddress.Parse("0:0:0:0:0:FFFF::"); - - private static bool IsAnyIPv6Configured() - { - return NetworkInterface.GetAllNetworkInterfaces() - .Where(n => (n.OperationalStatus == OperationalStatus.Up) && (n.NetworkInterfaceType != NetworkInterfaceType.Loopback)) - .SelectMany(n => n.GetIPProperties().UnicastAddresses.Select(a => a.Address)) - .Any(a => !IPAddress.IsLoopback(a) && (a.AddressFamily == AddressFamily.InterNetworkV6) && !a.IsIPv6LinkLocal && !a.IsIPv6Teredo && !a.GetNetworkAddress(96).Equals(_ipvMappedNetworkAddress)); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsClientEndpointInfo.cs b/ARSoft.Tools.Net/Dns/DnsClientEndpointInfo.cs deleted file mode 100644 index 4cc7e30..0000000 --- a/ARSoft.Tools.Net/Dns/DnsClientEndpointInfo.cs +++ /dev/null @@ -1,29 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System.Net; - -namespace ARSoft.Tools.Net.Dns -{ - internal class DnsClientEndpointInfo - { - public bool IsMulticast; - public IPAddress LocalAddress; - public IPAddress ServerAddress; - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsMessage.cs b/ARSoft.Tools.Net/Dns/DnsMessage.cs index 7925919..3bf7683 100644 --- a/ARSoft.Tools.Net/Dns/DnsMessage.cs +++ b/ARSoft.Tools.Net/Dns/DnsMessage.cs @@ -205,39 +205,6 @@ public bool IsCheckingDisabled set { base.AuthorityRecords = (value ?? new List()); } } - /// - /// Gets or sets the DNSSEC answer OK (DO) flag - /// - /// Defined in - /// RFC 4035 - /// and - /// RFC 3225 - /// - /// - public bool IsDnsSecOk - { - get - { - OptRecord ednsOptions = EDnsOptions; - return (ednsOptions != null) && ednsOptions.IsDnsSecOk; - } - set - { - OptRecord ednsOptions = EDnsOptions; - if (ednsOptions == null) - { - if (value) - { - throw new ArgumentOutOfRangeException(nameof(value), "Setting DO flag is allowed in edns messages only"); - } - } - else - { - ednsOptions.IsDnsSecOk = value; - } - } - } - /// /// Creates a new instance of the DnsMessage as response to the current instance /// @@ -247,21 +214,13 @@ public DnsMessage CreateResponseInstance() DnsMessage result = new DnsMessage() { TransactionID = TransactionID, - IsEDnsEnabled = IsEDnsEnabled, IsQuery = false, OperationCode = OperationCode, IsRecursionDesired = IsRecursionDesired, IsCheckingDisabled = IsCheckingDisabled, - IsDnsSecOk = IsDnsSecOk, Questions = new List(Questions), }; - if (IsEDnsEnabled) - { - result.EDnsOptions.Version = EDnsOptions.Version; - result.EDnsOptions.UdpPayloadSize = EDnsOptions.UdpPayloadSize; - } - return result; } diff --git a/ARSoft.Tools.Net/Dns/DnsMessageBase.cs b/ARSoft.Tools.Net/Dns/DnsMessageBase.cs index 0281f72..432dd79 100644 --- a/ARSoft.Tools.Net/Dns/DnsMessageBase.cs +++ b/ARSoft.Tools.Net/Dns/DnsMessageBase.cs @@ -98,117 +98,17 @@ public ReturnCode ReturnCode { ReturnCode rcode = (ReturnCode) (Flags & 0x000f); - OptRecord ednsOptions = EDnsOptions; - if (ednsOptions == null) - { - return rcode; - } - else - { - // ReSharper disable once BitwiseOperatorOnEnumWithoutFlags - return (rcode | ednsOptions.ExtendedReturnCode); - } + return rcode; } set { - OptRecord ednsOptions = EDnsOptions; - - if ((ushort) value > 15) - { - if (ednsOptions == null) - { - throw new ArgumentOutOfRangeException(nameof(value), "ReturnCodes greater than 15 only allowed in edns messages"); - } - else - { - ednsOptions.ExtendedReturnCode = value; - } - } - else - { - if (ednsOptions != null) - { - ednsOptions.ExtendedReturnCode = 0; - } - } - ushort clearedOp = (ushort) (Flags & 0xfff0); Flags = (ushort) (clearedOp | ((ushort) value & 0x0f)); } } #endregion - - #region EDNS - /// - /// Enables or disables EDNS - /// - public bool IsEDnsEnabled - { - get - { - if (_additionalRecords != null) - { - return _additionalRecords.Any(record => (record.RecordType == RecordType.Opt)); - } - else - { - return false; - } - } - set - { - if (value && !IsEDnsEnabled) - { - if (_additionalRecords == null) - { - _additionalRecords = new List(); - } - _additionalRecords.Add(new OptRecord()); - } - else if (!value && IsEDnsEnabled) - { - _additionalRecords.RemoveAll(record => (record.RecordType == RecordType.Opt)); - } - } - } - - /// - /// Gets or set the OptRecord for the EDNS options - /// - public OptRecord EDnsOptions - { - get { return (OptRecord) _additionalRecords?.Find(record => (record.RecordType == RecordType.Opt)); } - set - { - if (value == null) - { - IsEDnsEnabled = false; - } - else if (IsEDnsEnabled) - { - int pos = _additionalRecords.FindIndex(record => (record.RecordType == RecordType.Opt)); - _additionalRecords[pos] = value; - } - else - { - if (_additionalRecords == null) - { - _additionalRecords = new List(); - } - _additionalRecords.Add(value); - } - } - } - #endregion - - #region TSig - /// - /// Gets or set the TSigRecord for the tsig signed messages - /// - // ReSharper disable once InconsistentNaming - public TSigRecord TSigOptions { get; set; } - - internal static DnsMessageBase CreateByFlag(byte[] data, DnsServer.SelectTsigKey tsigKeySelector, byte[] originalMac) + + internal static DnsMessageBase CreateByFlag(byte[] data) { int flagPosition = 2; ushort flags = ParseUShort(data, ref flagPosition); @@ -226,26 +126,20 @@ internal static DnsMessageBase CreateByFlag(byte[] data, DnsServer.SelectTsigKey break; } - res.ParseInternal(data, tsigKeySelector, originalMac); + res.ParseInternal(data); return res; } internal static TMessage Parse(byte[] data) where TMessage : DnsMessageBase, new() - { - return Parse(data, null, null); - } - - internal static TMessage Parse(byte[] data, DnsServer.SelectTsigKey tsigKeySelector, byte[] originalMac) - where TMessage : DnsMessageBase, new() { TMessage result = new TMessage(); - result.ParseInternal(data, tsigKeySelector, originalMac); + result.ParseInternal(data); return result; } - private void ParseInternal(byte[] data, DnsServer.SelectTsigKey tsigKeySelector, byte[] originalMac) + private void ParseInternal(byte[] data) { int currentPosition = 0; @@ -262,88 +156,9 @@ private void ParseInternal(byte[] data, DnsServer.SelectTsigKey tsigKeySelector, ParseSection(data, ref currentPosition, AuthorityRecords, authorityRecordCount); ParseSection(data, ref currentPosition, _additionalRecords, additionalRecordCount); - if (_additionalRecords.Count > 0) - { - int tSigPos = _additionalRecords.FindIndex(record => (record.RecordType == RecordType.TSig)); - if (tSigPos == (_additionalRecords.Count - 1)) - { - TSigOptions = (TSigRecord) _additionalRecords[tSigPos]; - - _additionalRecords.RemoveAt(tSigPos); - - TSigOptions.ValidationResult = ValidateTSig(data, tsigKeySelector, originalMac); - } - } - FinishParsing(); } - private ReturnCode ValidateTSig(byte[] resultData, DnsServer.SelectTsigKey tsigKeySelector, byte[] originalMac) - { - byte[] keyData; - if ((TSigOptions.Algorithm == TSigAlgorithm.Unknown) || (tsigKeySelector == null) || ((keyData = tsigKeySelector(TSigOptions.Algorithm, TSigOptions.Name)) == null)) - { - return ReturnCode.BadKey; - } - else if (((TSigOptions.TimeSigned - TSigOptions.Fudge) > DateTime.Now) || ((TSigOptions.TimeSigned + TSigOptions.Fudge) < DateTime.Now)) - { - return ReturnCode.BadTime; - } - else if ((TSigOptions.Mac == null) || (TSigOptions.Mac.Length == 0)) - { - return ReturnCode.BadSig; - } - else - { - TSigOptions.KeyData = keyData; - - // maxLength for the buffer to validate: Original (unsigned) dns message and encoded TSigOptions - // because of compression of keyname, the size of the signed message can not be used - int maxLength = TSigOptions.StartPosition + TSigOptions.MaximumLength; - if (originalMac != null) - { - // add length of mac on responses. MacSize not neccessary, this field is allready included in the size of the tsig options - maxLength += originalMac.Length; - } - - byte[] validationBuffer = new byte[maxLength]; - - int currentPosition = 0; - - // original mac if neccessary - if ((originalMac != null) && (originalMac.Length > 0)) - { - EncodeUShort(validationBuffer, ref currentPosition, (ushort) originalMac.Length); - EncodeByteArray(validationBuffer, ref currentPosition, originalMac); - } - - // original unsiged buffer - Buffer.BlockCopy(resultData, 0, validationBuffer, currentPosition, TSigOptions.StartPosition); - - // update original transaction id and ar count in message - EncodeUShort(validationBuffer, currentPosition, TSigOptions.OriginalID); - EncodeUShort(validationBuffer, currentPosition + 10, (ushort) _additionalRecords.Count); - currentPosition += TSigOptions.StartPosition; - - // TSig Variables - EncodeDomainName(validationBuffer, 0, ref currentPosition, TSigOptions.Name, null, false); - EncodeUShort(validationBuffer, ref currentPosition, (ushort) TSigOptions.RecordClass); - EncodeInt(validationBuffer, ref currentPosition, (ushort) TSigOptions.TimeToLive); - EncodeDomainName(validationBuffer, 0, ref currentPosition, TSigAlgorithmHelper.GetDomainName(TSigOptions.Algorithm), null, false); - TSigRecord.EncodeDateTime(validationBuffer, ref currentPosition, TSigOptions.TimeSigned); - EncodeUShort(validationBuffer, ref currentPosition, (ushort) TSigOptions.Fudge.TotalSeconds); - EncodeUShort(validationBuffer, ref currentPosition, (ushort) TSigOptions.Error); - EncodeUShort(validationBuffer, ref currentPosition, (ushort) TSigOptions.OtherData.Length); - EncodeByteArray(validationBuffer, ref currentPosition, TSigOptions.OtherData); - - // Validate MAC - KeyedHashAlgorithm hashAlgorithm = TSigAlgorithmHelper.GetHashAlgorithm(TSigOptions.Algorithm); - hashAlgorithm.Key = keyData; - return (hashAlgorithm.ComputeHash(validationBuffer, 0, currentPosition).SequenceEqual(TSigOptions.Mac)) ? ReturnCode.NoError : ReturnCode.BadSig; - } - } - #endregion - #region Parsing protected virtual void FinishParsing() {} @@ -591,21 +406,12 @@ internal static byte[] ParseByteData(byte[] resultData, ref int currentPosition, #region Serializing protected virtual void PrepareEncoding() {} - public int Encode(bool addLengthPrefix, out byte[] messageData) - { - byte[] newTSigMac; - - return Encode(addLengthPrefix, null, false, out messageData, out newTSigMac); - } - - public int Encode(bool addLengthPrefix, byte[] originalTsigMac, out byte[] messageData) + public int Encode(bool addLengthPrefix, out byte[] messageData) { - byte[] newTSigMac; - - return Encode(addLengthPrefix, originalTsigMac, false, out messageData, out newTSigMac); + return Encode(addLengthPrefix, false, out messageData); } - public int Encode(bool addLengthPrefix, byte[] originalTsigMac, bool isSubSequentResponse, out byte[] messageData, out byte[] newTSigMac) + public int Encode(bool addLengthPrefix, bool isSubSequentResponse, out byte[] messageData) { PrepareEncoding(); @@ -613,19 +419,6 @@ public int Encode(bool addLengthPrefix, byte[] originalTsigMac, bool isSubSequen int messageOffset = offset; int maxLength = addLengthPrefix ? 2 : 0; - originalTsigMac = originalTsigMac ?? new byte[] { }; - - if (TSigOptions != null) - { - if (!IsQuery) - { - offset += 2 + originalTsigMac.Length; - maxLength += 2 + originalTsigMac.Length; - } - - maxLength += TSigOptions.MaximumLength; - } - #region Get Message Length maxLength += 12; maxLength += Questions.Sum(question => question.MaximumLength); @@ -662,64 +455,7 @@ public int Encode(bool addLengthPrefix, byte[] originalTsigMac, bool isSubSequen { record.Encode(messageData, offset, ref currentPosition, domainNames); } - - if (TSigOptions == null) - { - newTSigMac = null; - } - else - { - if (!IsQuery) - { - EncodeUShort(messageData, messageOffset, (ushort) originalTsigMac.Length); - Buffer.BlockCopy(originalTsigMac, 0, messageData, messageOffset + 2, originalTsigMac.Length); - } - - EncodeUShort(messageData, offset, TSigOptions.OriginalID); - - int tsigVariablesPosition = currentPosition; - - if (isSubSequentResponse) - { - TSigRecord.EncodeDateTime(messageData, ref tsigVariablesPosition, TSigOptions.TimeSigned); - EncodeUShort(messageData, ref tsigVariablesPosition, (ushort) TSigOptions.Fudge.TotalSeconds); - } - else - { - EncodeDomainName(messageData, offset, ref tsigVariablesPosition, TSigOptions.Name, null, false); - EncodeUShort(messageData, ref tsigVariablesPosition, (ushort) TSigOptions.RecordClass); - EncodeInt(messageData, ref tsigVariablesPosition, (ushort) TSigOptions.TimeToLive); - EncodeDomainName(messageData, offset, ref tsigVariablesPosition, TSigAlgorithmHelper.GetDomainName(TSigOptions.Algorithm), null, false); - TSigRecord.EncodeDateTime(messageData, ref tsigVariablesPosition, TSigOptions.TimeSigned); - EncodeUShort(messageData, ref tsigVariablesPosition, (ushort) TSigOptions.Fudge.TotalSeconds); - EncodeUShort(messageData, ref tsigVariablesPosition, (ushort) TSigOptions.Error); - EncodeUShort(messageData, ref tsigVariablesPosition, (ushort) TSigOptions.OtherData.Length); - EncodeByteArray(messageData, ref tsigVariablesPosition, TSigOptions.OtherData); - } - - KeyedHashAlgorithm hashAlgorithm = TSigAlgorithmHelper.GetHashAlgorithm(TSigOptions.Algorithm); - if ((hashAlgorithm != null) && (TSigOptions.KeyData != null) && (TSigOptions.KeyData.Length > 0)) - { - hashAlgorithm.Key = TSigOptions.KeyData; - newTSigMac = hashAlgorithm.ComputeHash(messageData, messageOffset, tsigVariablesPosition); - } - else - { - newTSigMac = new byte[] { }; - } - - EncodeUShort(messageData, offset, TransactionID); - EncodeUShort(messageData, offset + 10, (ushort) (_additionalRecords.Count + 1)); - - TSigOptions.Encode(messageData, offset, ref currentPosition, domainNames, newTSigMac); - - if (!IsQuery) - { - Buffer.BlockCopy(messageData, offset, messageData, messageOffset, (currentPosition - offset)); - currentPosition -= (2 + originalTsigMac.Length); - } - } - + if (addLengthPrefix) { Buffer.BlockCopy(messageData, 0, messageData, 2, currentPosition); diff --git a/ARSoft.Tools.Net/Dns/DnsQueryOptions.cs b/ARSoft.Tools.Net/Dns/DnsQueryOptions.cs index e7c33b3..8c647f4 100644 --- a/ARSoft.Tools.Net/Dns/DnsQueryOptions.cs +++ b/ARSoft.Tools.Net/Dns/DnsQueryOptions.cs @@ -45,62 +45,5 @@ public class DnsQueryOptions /// /// public bool IsCheckingDisabled { get; set; } - - /// - /// Enables or disables EDNS - /// - public bool IsEDnsEnabled - { - get { return (EDnsOptions != null); } - set - { - if (value && (EDnsOptions == null)) - { - EDnsOptions = new OptRecord(); - } - else if (!value) - { - EDnsOptions = null; - } - } - } - - /// - /// Gets or set the OptRecord for the EDNS options - /// - public OptRecord EDnsOptions { get; set; } - - /// - /// Gets or sets the DNSSEC answer OK (DO) flag - /// - /// Defined in - /// RFC 4035 - /// and - /// RFC 3225 - /// - /// - public bool IsDnsSecOk - { - get - { - OptRecord ednsOptions = EDnsOptions; - return (ednsOptions != null) && ednsOptions.IsDnsSecOk; - } - set - { - OptRecord ednsOptions = EDnsOptions; - if (ednsOptions == null) - { - if (value) - { - throw new ArgumentOutOfRangeException(nameof(value), "Setting DO flag is allowed in edns messages only"); - } - } - else - { - ednsOptions.IsDnsSecOk = value; - } - } - } } } \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/AfsdbRecord.cs b/ARSoft.Tools.Net/Dns/DnsRecord/AfsdbRecord.cs deleted file mode 100644 index 8291ddc..0000000 --- a/ARSoft.Tools.Net/Dns/DnsRecord/AfsdbRecord.cs +++ /dev/null @@ -1,116 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// AFS data base location - /// - /// Defined in - /// RFC 1183 - /// and - /// RFC 5864 - /// - /// - public class AfsdbRecord : DnsRecordBase - { - /// - /// AFS database subtype - /// - public enum AfsSubType : ushort - { - /// - /// Andrews File Service v3.0 Location service - /// - /// Defined in - /// RFC 1183 - /// - /// - Afs = 1, - - /// - /// DCE/NCA root cell directory node - /// - /// Defined in - /// RFC 1183 - /// - /// - Dce = 2, - } - - /// - /// Subtype of the record - /// - public AfsSubType SubType { get; private set; } - - /// - /// Hostname of the AFS database - /// - public DomainName Hostname { get; private set; } - - internal AfsdbRecord() {} - - /// - /// Creates a new instance of the AfsdbRecord class - /// - /// Name of the record - /// Seconds the record should be cached at most - /// Subtype of the record - /// Hostname of the AFS database - public AfsdbRecord(DomainName name, int timeToLive, AfsSubType subType, DomainName hostname) - : base(name, RecordType.Afsdb, RecordClass.INet, timeToLive) - { - SubType = subType; - Hostname = hostname ?? DomainName.Root; - } - - internal override void ParseRecordData(byte[] resultData, int startPosition, int length) - { - SubType = (AfsSubType) DnsMessageBase.ParseUShort(resultData, ref startPosition); - Hostname = DnsMessageBase.ParseDomainName(resultData, ref startPosition); - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length != 2) - throw new FormatException(); - - SubType = (AfsSubType) Byte.Parse(stringRepresentation[0]); - Hostname = ParseDomainName(origin, stringRepresentation[1]); - } - - internal override string RecordDataToString() - { - return (byte) SubType - + " " + Hostname; - } - - protected internal override int MaximumRecordDataLength => Hostname.MaximumRecordDataLength + 4; - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, (ushort) SubType); - DnsMessageBase.EncodeDomainName(messageData, offset, ref currentPosition, Hostname, null, useCanonical); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/AplRecord.cs b/ARSoft.Tools.Net/Dns/DnsRecord/AplRecord.cs deleted file mode 100644 index 8084c5a..0000000 --- a/ARSoft.Tools.Net/Dns/DnsRecord/AplRecord.cs +++ /dev/null @@ -1,207 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Text; -using System.Text.RegularExpressions; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Address prefixes record - /// - /// Defined in - /// RFC 3123 - /// - /// - public class AplRecord : DnsRecordBase - { - internal enum Family : ushort - { - /// - /// IPv4 - /// - /// Defined in - /// RFC 3123 - /// - /// - IpV4 = 1, - - /// - /// IPv6 - /// - /// Defined in - /// RFC 3123 - /// - /// - IpV6 = 2, - } - - /// - /// Represents an address prefix - /// - public class AddressPrefix - { - private static readonly Regex _parserRegex = new Regex(@"^(?!?)(?(1|2)):(?[^/]+)/(?\d+)$", RegexOptions.ExplicitCapture | RegexOptions.Compiled); - - /// - /// Is negated prefix - /// - public bool IsNegated { get; } - - /// - /// Address familiy - /// - internal Family AddressFamily { get; } - - /// - /// Network address - /// - public IPAddress Address { get; } - - /// - /// Prefix of the network - /// - public byte Prefix { get; } - - /// - /// Creates a new instance of the AddressPrefix class - /// - /// Is negated prefix - /// Network address - /// Prefix of the network - public AddressPrefix(bool isNegated, IPAddress address, byte prefix) - { - IsNegated = isNegated; - AddressFamily = (address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) ? Family.IpV4 : Family.IpV6; - Address = address; - Prefix = prefix; - } - - /// - /// Returns the textual representation of an address prefix - /// - /// The textual representation - public override string ToString() - { - return (IsNegated ? "!" : "") - + (ushort) AddressFamily - + ":" + Address - + "/" + Prefix; - } - - internal static AddressPrefix Parse(string s) - { - var groups = _parserRegex.Match(s).Groups; - - IPAddress address = IPAddress.Parse(groups["addr"].Value); - - if ((address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) && (groups["fam"].Value != "1")) - throw new FormatException(); - - return new AddressPrefix(groups["isneg"].Success, address, Byte.Parse(groups["pref"].Value)); - } - } - - /// - /// List of address prefixes covered by this record - /// - public List Prefixes { get; private set; } - - internal AplRecord() {} - - /// - /// Creates a new instance of the AplRecord class - /// - /// Name of the record - /// Seconds the record should be cached at most - /// List of address prefixes covered by this record - public AplRecord(DomainName name, int timeToLive, List prefixes) - : base(name, RecordType.Apl, RecordClass.INet, timeToLive) - { - Prefixes = prefixes ?? new List(); - } - - internal override void ParseRecordData(byte[] resultData, int currentPosition, int length) - { - int endPosition = currentPosition + length; - - Prefixes = new List(); - while (currentPosition < endPosition) - { - Family family = (Family) DnsMessageBase.ParseUShort(resultData, ref currentPosition); - byte prefix = resultData[currentPosition++]; - - byte addressLength = resultData[currentPosition++]; - bool isNegated = false; - if (addressLength > 127) - { - isNegated = true; - addressLength -= 128; - } - - byte[] addressData = new byte[(family == Family.IpV4) ? 4 : 16]; - Buffer.BlockCopy(resultData, currentPosition, addressData, 0, addressLength); - currentPosition += addressLength; - - Prefixes.Add(new AddressPrefix(isNegated, new IPAddress(addressData), prefix)); - } - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length == 0) - throw new FormatException(); - - Prefixes = stringRepresentation.Select(AddressPrefix.Parse).ToList(); - } - - internal override string RecordDataToString() - { - return String.Join(" ", Prefixes.Select(p => p.ToString())); - } - - protected internal override int MaximumRecordDataLength => Prefixes.Count * 20; - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - foreach (AddressPrefix addressPrefix in Prefixes) - { - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, (ushort) addressPrefix.AddressFamily); - messageData[currentPosition++] = addressPrefix.Prefix; - - // no increment of position pointer, just set 1 bit - if (addressPrefix.IsNegated) - messageData[currentPosition] = 128; - - byte[] addressData = addressPrefix.Address.GetNetworkAddress(addressPrefix.Prefix).GetAddressBytes(); - int length = addressData.Length; - for (; length > 0; length--) - { - if (addressData[length - 1] != 0) - break; - } - messageData[currentPosition++] |= (byte) length; - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, addressData, length); - } - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/CAARecord.cs b/ARSoft.Tools.Net/Dns/DnsRecord/CAARecord.cs deleted file mode 100644 index 99ffcc2..0000000 --- a/ARSoft.Tools.Net/Dns/DnsRecord/CAARecord.cs +++ /dev/null @@ -1,100 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// CAA - /// - /// Defined in - /// RFC 6844 - /// - /// - // ReSharper disable once InconsistentNaming - public class CAARecord : DnsRecordBase - { - /// - /// The flags - /// - public byte Flags { get; private set; } - - /// - /// The name of the tag - /// - public string Tag { get; private set; } - - /// - /// The value of the tag - /// - public string Value { get; private set; } - - internal CAARecord() {} - - /// - /// Creates a new instance of the CAARecord class - /// - /// Name of the zone - /// Seconds the record should be cached at most - /// The flags - /// The name of the tag - /// The value of the tag - public CAARecord(DomainName name, int timeToLive, byte flags, string tag, string value) - : base(name, RecordType.CAA, RecordClass.INet, timeToLive) - { - Flags = flags; - Tag = tag; - Value = value; - } - - internal override void ParseRecordData(byte[] resultData, int startPosition, int length) - { - Flags = resultData[startPosition++]; - Tag = DnsMessageBase.ParseText(resultData, ref startPosition); - Value = DnsMessageBase.ParseText(resultData, ref startPosition, length - (2 + Tag.Length)); - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length != 3) - throw new FormatException(); - - Flags = Byte.Parse(stringRepresentation[0]); - Tag = stringRepresentation[1]; - Value = stringRepresentation[2]; - } - - internal override string RecordDataToString() - { - return Flags + " " + Tag.ToMasterfileLabelRepresentation() + " " + Value.ToMasterfileLabelRepresentation(); - } - - protected internal override int MaximumRecordDataLength => 2 + Tag.Length + Value.Length; - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - messageData[currentPosition++] = Flags; - DnsMessageBase.EncodeTextBlock(messageData, ref currentPosition, Tag); - DnsMessageBase.EncodeTextWithoutLength(messageData, ref currentPosition, Value); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/CDnsKeyRecord.cs b/ARSoft.Tools.Net/Dns/DnsRecord/CDnsKeyRecord.cs deleted file mode 100644 index a05839c..0000000 --- a/ARSoft.Tools.Net/Dns/DnsRecord/CDnsKeyRecord.cs +++ /dev/null @@ -1,236 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Child DNS Key record - /// - /// Defined in - /// RFC 7344 - /// - /// - public class CDnsKeyRecord : DnsRecordBase - { - /// - /// Flags of the key - /// - public DnsKeyFlags Flags { get; private set; } - - /// - /// Protocol field - /// - public byte Protocol { get; private set; } - - /// - /// Algorithm of the key - /// - public DnsSecAlgorithm Algorithm { get; private set; } - - /// - /// Binary data of the public key - /// - public byte[] PublicKey { get; private set; } - - /// - /// Binary data of the private key - /// - public byte[] PrivateKey { get; private set; } - - /// - /// Record holds a DNS zone key - /// - /// Defined in - /// RFC 4034 - /// and - /// RFC 3757 - /// - /// - public bool IsZoneKey - { - get { return (Flags & DnsKeyFlags.Zone) == DnsKeyFlags.Zone; } - set - { - if (value) - { - Flags |= DnsKeyFlags.Zone; - } - else - { - Flags &= ~DnsKeyFlags.Zone; - } - } - } - - /// - /// Key is intended for use as a secure entry point - /// - /// Defined in - /// RFC 4034 - /// and - /// RFC 3757 - /// - /// - public bool IsSecureEntryPoint - { - get { return (Flags & DnsKeyFlags.SecureEntryPoint) == DnsKeyFlags.SecureEntryPoint; } - set - { - if (value) - { - Flags |= DnsKeyFlags.SecureEntryPoint; - } - else - { - Flags &= ~DnsKeyFlags.SecureEntryPoint; - } - } - } - - /// - /// Key is intended for use as a secure entry point - /// - /// Defined in - /// RFC 5011 - /// - /// - public bool IsRevoked - { - get { return (Flags & DnsKeyFlags.Revoke) == DnsKeyFlags.Revoke; } - set - { - if (value) - { - Flags |= DnsKeyFlags.Revoke; - } - else - { - Flags &= ~DnsKeyFlags.Revoke; - } - } - } - - /// - /// Calculates the key tag - /// - /// Defined in - /// RFC 4034 - /// - /// - /// - public ushort CalculateKeyTag() - { - if (Algorithm == DnsSecAlgorithm.RsaMd5) - return (ushort) (PublicKey[PublicKey.Length - 4] & PublicKey[PublicKey.Length - 3] << 8); - - byte[] buffer = new byte[MaximumRecordDataLength]; - int currentPosition = 0; - EncodeRecordData(buffer, 0, ref currentPosition, null, false); - - ulong ac = 0; - - for (int i = 0; i < currentPosition; ++i) - { - ac += ((i & 1) == 1) ? buffer[i] : (ulong) buffer[i] << 8; - } - - ac += (ac >> 16) & 0xFFFF; - - ushort res = (ushort) (ac & 0xffff); - - return res; - } - - internal CDnsKeyRecord() {} - - /// - /// Creates a new instance of the DnsKeyRecord class - /// - /// Name of the record - /// Class of the record - /// Seconds the record should be cached at most - /// Flags of the key - /// Protocol field - /// Algorithm of the key - /// Binary data of the public key - public CDnsKeyRecord(DomainName name, RecordClass recordClass, int timeToLive, DnsKeyFlags flags, byte protocol, DnsSecAlgorithm algorithm, byte[] publicKey) - : this(name, recordClass, timeToLive, flags, protocol, algorithm, publicKey, null) {} - - /// - /// Creates a new instance of the DnsKeyRecord class - /// - /// Name of the record - /// Class of the record - /// Seconds the record should be cached at most - /// Flags of the key - /// Protocol field - /// Algorithm of the key - /// Binary data of the public key - /// Binary data of the private key - public CDnsKeyRecord(DomainName name, RecordClass recordClass, int timeToLive, DnsKeyFlags flags, byte protocol, DnsSecAlgorithm algorithm, byte[] publicKey, byte[] privateKey) - : base(name, RecordType.CDnsKey, recordClass, timeToLive) - { - Flags = flags; - Protocol = protocol; - Algorithm = algorithm; - PublicKey = publicKey; - PrivateKey = privateKey; - } - - internal override void ParseRecordData(byte[] resultData, int startPosition, int length) - { - Flags = (DnsKeyFlags) DnsMessageBase.ParseUShort(resultData, ref startPosition); - Protocol = resultData[startPosition++]; - Algorithm = (DnsSecAlgorithm) resultData[startPosition++]; - PublicKey = DnsMessageBase.ParseByteData(resultData, ref startPosition, length - 4); - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length < 4) - throw new FormatException(); - - Flags = (DnsKeyFlags) UInt16.Parse(stringRepresentation[0]); - Protocol = Byte.Parse(stringRepresentation[1]); - Algorithm = (DnsSecAlgorithm) Byte.Parse(stringRepresentation[2]); - PublicKey = String.Join(String.Empty, stringRepresentation.Skip(3)).FromBase64String(); - } - - internal override string RecordDataToString() - { - return (ushort) Flags - + " " + Protocol - + " " + (byte) Algorithm - + " " + PublicKey.ToBase64String(); - } - - protected internal override int MaximumRecordDataLength => 4 + PublicKey.Length; - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, (ushort) Flags); - messageData[currentPosition++] = Protocol; - messageData[currentPosition++] = (byte) Algorithm; - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, PublicKey); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/CDsRecord.cs b/ARSoft.Tools.Net/Dns/DnsRecord/CDsRecord.cs deleted file mode 100644 index 5073917..0000000 --- a/ARSoft.Tools.Net/Dns/DnsRecord/CDsRecord.cs +++ /dev/null @@ -1,113 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Child Delegation signer - /// - /// Defined in - /// RFC 7344 - /// - /// - public class CDsRecord : DnsRecordBase - { - /// - /// Key tag - /// - public ushort KeyTag { get; private set; } - - /// - /// Algorithm used - /// - public DnsSecAlgorithm Algorithm { get; private set; } - - /// - /// Type of the digest - /// - public DnsSecDigestType DigestType { get; private set; } - - /// - /// Binary data of the digest - /// - public byte[] Digest { get; private set; } - - internal CDsRecord() {} - - /// - /// Creates a new instance of the CDsRecord class - /// - /// Name of the record - /// Class of the record - /// Seconds the record should be cached at most - /// Key tag - /// Algorithm used - /// Type of the digest - /// Binary data of the digest - public CDsRecord(DomainName name, RecordClass recordClass, int timeToLive, ushort keyTag, DnsSecAlgorithm algorithm, DnsSecDigestType digestType, byte[] digest) - : base(name, RecordType.Ds, recordClass, timeToLive) - { - KeyTag = keyTag; - Algorithm = algorithm; - DigestType = digestType; - Digest = digest ?? new byte[] { }; - } - - internal override void ParseRecordData(byte[] resultData, int startPosition, int length) - { - KeyTag = DnsMessageBase.ParseUShort(resultData, ref startPosition); - Algorithm = (DnsSecAlgorithm) resultData[startPosition++]; - DigestType = (DnsSecDigestType) resultData[startPosition++]; - Digest = DnsMessageBase.ParseByteData(resultData, ref startPosition, length - 4); - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length < 4) - throw new FormatException(); - - KeyTag = UInt16.Parse(stringRepresentation[0]); - Algorithm = (DnsSecAlgorithm) Byte.Parse(stringRepresentation[1]); - DigestType = (DnsSecDigestType) Byte.Parse(stringRepresentation[2]); - Digest = String.Join(String.Empty, stringRepresentation.Skip(3)).FromBase16String(); - } - - internal override string RecordDataToString() - { - return KeyTag - + " " + (byte) Algorithm - + " " + (byte) DigestType - + " " + Digest.ToBase16String(); - } - - protected internal override int MaximumRecordDataLength => 4 + Digest.Length; - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, KeyTag); - messageData[currentPosition++] = (byte) Algorithm; - messageData[currentPosition++] = (byte) DigestType; - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, Digest); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/CSyncRecord.cs b/ARSoft.Tools.Net/Dns/DnsRecord/CSyncRecord.cs deleted file mode 100644 index 1bd2474..0000000 --- a/ARSoft.Tools.Net/Dns/DnsRecord/CSyncRecord.cs +++ /dev/null @@ -1,225 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Child-to-Parent Synchronization - /// - /// Defined in - /// RFC 7477 - /// - /// - public class CSyncRecord : DnsRecordBase - { - /// - /// CSync record flags - /// - public enum CSyncFlags : ushort - { - /// - /// Immediate - /// - /// Defined in - /// RFC 7477 - /// - /// - Immediate = 1, - - /// - /// SOA minimum - /// - /// Defined in - /// RFC 7477 - /// - /// - SoaMinimum = 2, - } - - /// - /// SOA Serial Field - /// - public uint SerialNumber { get; internal set; } - - /// - /// Flags - /// - public CSyncFlags Flags { get; internal set; } - - /// - /// Record types - /// - public List Types { get; private set; } - - internal CSyncRecord() {} - - /// - /// Creates a new instance of the CSyncRecord class - /// - /// Name of the record - /// Class of the record - /// Seconds the record should be cached at most - /// SOA Serial Field - /// Flags - /// Record types of the next owner - public CSyncRecord(DomainName name, RecordClass recordClass, int timeToLive, uint serialNumber, CSyncFlags flags, List types) - : base(name, RecordType.CSync, recordClass, timeToLive) - { - SerialNumber = serialNumber; - Flags = flags; - - if ((types == null) || (types.Count == 0)) - { - Types = new List(); - } - else - { - Types = types.Distinct().OrderBy(x => x).ToList(); - } - } - - internal override void ParseRecordData(byte[] resultData, int currentPosition, int length) - { - int endPosition = currentPosition + length; - - SerialNumber = DnsMessageBase.ParseUInt(resultData, ref currentPosition); - Flags = (CSyncFlags) DnsMessageBase.ParseUShort(resultData, ref currentPosition); - Types = ParseTypeBitMap(resultData, ref currentPosition, endPosition); - } - - internal static List ParseTypeBitMap(byte[] resultData, ref int currentPosition, int endPosition) - { - List types = new List(); - while (currentPosition < endPosition) - { - byte windowNumber = resultData[currentPosition++]; - byte windowLength = resultData[currentPosition++]; - - for (int i = 0; i < windowLength; i++) - { - byte bitmap = resultData[currentPosition++]; - - for (int bit = 0; bit < 8; bit++) - { - if ((bitmap & (1 << Math.Abs(bit - 7))) != 0) - { - types.Add((RecordType) (windowNumber * 256 + i * 8 + bit)); - } - } - } - } - return types; - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length < 3) - throw new FormatException(); - - SerialNumber = UInt32.Parse(stringRepresentation[0]); - Flags = (CSyncFlags) UInt16.Parse(stringRepresentation[1]); - Types = stringRepresentation.Skip(2).Select(RecordTypeHelper.ParseShortString).ToList(); - } - - internal override string RecordDataToString() - { - return SerialNumber - + " " + (ushort) Flags + " " + String.Join(" ", Types.Select(RecordTypeHelper.ToShortString)); - } - - protected internal override int MaximumRecordDataLength => 7 + GetMaximumTypeBitmapLength(Types); - - internal static int GetMaximumTypeBitmapLength(List types) - { - int res = 0; - - int windowEnd = 255; - ushort lastType = 0; - - foreach (ushort type in types.Select(t => (ushort) t)) - { - if (type > windowEnd) - { - res += 3 + lastType % 256 / 8; - windowEnd = (type / 256 + 1) * 256 - 1; - } - - lastType = type; - } - - return res + 3 + lastType % 256 / 8; - } - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - DnsMessageBase.EncodeUInt(messageData, ref currentPosition, SerialNumber); - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, (ushort) Flags); - EncodeTypeBitmap(messageData, ref currentPosition, Types); - } - - internal static void EncodeTypeBitmap(byte[] messageData, ref int currentPosition, List types) - { - int windowEnd = 255; - byte[] windowData = new byte[32]; - int windowLength = 0; - - foreach (ushort type in types.Select(t => (ushort) t)) - { - if (type > windowEnd) - { - if (windowLength > 0) - { - messageData[currentPosition++] = (byte) (windowEnd / 256); - messageData[currentPosition++] = (byte) windowLength; - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, windowData, windowLength); - } - - windowEnd = (type / 256 + 1) * 256 - 1; - windowLength = 0; - } - - int typeLower = type % 256; - - int octetPos = typeLower / 8; - int bitPos = typeLower % 8; - - while (windowLength <= octetPos) - { - windowData[windowLength] = 0; - windowLength++; - } - - byte octet = windowData[octetPos]; - octet |= (byte) (1 << Math.Abs(bitPos - 7)); - windowData[octetPos] = octet; - } - - if (windowLength > 0) - { - messageData[currentPosition++] = (byte) (windowEnd / 256); - messageData[currentPosition++] = (byte) windowLength; - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, windowData, windowLength); - } - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/CertRecord.cs b/ARSoft.Tools.Net/Dns/DnsRecord/CertRecord.cs deleted file mode 100644 index 59c558f..0000000 --- a/ARSoft.Tools.Net/Dns/DnsRecord/CertRecord.cs +++ /dev/null @@ -1,217 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Certificate storage record - /// - /// Defined in - /// RFC 4398 - /// - /// - public class CertRecord : DnsRecordBase - { - /// - /// Type of cert - /// - public enum CertType : ushort - { - /// - /// None - /// - None = 0, - - /// - /// X.509 as per PKIX - /// - /// Defined in - /// RFC 4398 - /// - /// - Pkix = 1, - - /// - /// SPKI certificate - /// - /// Defined in - /// RFC 4398 - /// - /// - Spki = 2, - - /// - /// OpenPGP packet - /// - /// Defined in - /// RFC 4398 - /// - /// - Pgp = 3, - - /// - /// The URL of an X.509 data object - /// - /// Defined in - /// RFC 4398 - /// - /// - // ReSharper disable once InconsistentNaming - IPkix = 4, - - /// - /// The URL of an SPKI certificate - /// - /// Defined in - /// RFC 4398 - /// - /// - // ReSharper disable once InconsistentNaming - ISpki = 5, - - /// - /// The fingerprint and URL of an OpenPGP packet - /// - /// Defined in - /// RFC 4398 - /// - /// - // ReSharper disable once InconsistentNaming - IPgp = 6, - - /// - /// Attribute Certificate - /// - /// Defined in - /// RFC 4398 - /// - /// - Acpkix = 7, - - /// - /// The URL of an Attribute Certificate - /// - /// Defined in - /// RFC 4398 - /// - /// - // ReSharper disable once InconsistentNaming - IAcpkix = 8, - - /// - /// URI private - /// - /// Defined in - /// RFC 4398 - /// - /// - Uri = 253, - - /// - /// OID private - /// - /// Defined in - /// RFC 4398 - /// - /// - Oid = 254, - } - - /// - /// Type of the certificate data - /// - public CertType Type { get; private set; } - - /// - /// Key tag - /// - public ushort KeyTag { get; private set; } - - /// - /// Algorithm of the certificate - /// - public DnsSecAlgorithm Algorithm { get; private set; } - - /// - /// Binary data of the certificate - /// - public byte[] Certificate { get; private set; } - - internal CertRecord() {} - - /// - /// Creates a new instace of the CertRecord class - /// - /// Name of the record - /// Seconds the record should be cached at most - /// Type of the certificate data - /// Key tag - /// Algorithm of the certificate - /// Binary data of the certificate - public CertRecord(DomainName name, int timeToLive, CertType type, ushort keyTag, DnsSecAlgorithm algorithm, byte[] certificate) - : base(name, RecordType.Cert, RecordClass.INet, timeToLive) - { - Type = type; - KeyTag = keyTag; - Algorithm = algorithm; - Certificate = certificate ?? new byte[] { }; - } - - internal override void ParseRecordData(byte[] resultData, int startPosition, int length) - { - Type = (CertType) DnsMessageBase.ParseUShort(resultData, ref startPosition); - KeyTag = DnsMessageBase.ParseUShort(resultData, ref startPosition); - Algorithm = (DnsSecAlgorithm) resultData[startPosition++]; - Certificate = DnsMessageBase.ParseByteData(resultData, ref startPosition, length - 5); - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length < 4) - throw new FormatException(); - - Type = (CertType) UInt16.Parse(stringRepresentation[0]); - KeyTag = UInt16.Parse(stringRepresentation[1]); - Algorithm = (DnsSecAlgorithm) Byte.Parse(stringRepresentation[2]); - Certificate = String.Join(String.Empty, stringRepresentation.Skip(3)).FromBase64String(); - } - - internal override string RecordDataToString() - { - return (ushort) Type - + " " + KeyTag - + " " + (byte) Algorithm - + " " + Certificate.ToBase64String(); - } - - protected internal override int MaximumRecordDataLength => 5 + Certificate.Length; - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, (ushort) Type); - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, KeyTag); - messageData[currentPosition++] = (byte) Algorithm; - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, Certificate); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/DNameRecord.cs b/ARSoft.Tools.Net/Dns/DnsRecord/DNameRecord.cs deleted file mode 100644 index 63a75eb..0000000 --- a/ARSoft.Tools.Net/Dns/DnsRecord/DNameRecord.cs +++ /dev/null @@ -1,79 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// DNS Name Redirection record - /// - /// Defined in - /// RFC 6672 - /// - /// - public class DNameRecord : DnsRecordBase - { - /// - /// Target of the redirection - /// - public DomainName Target { get; private set; } - - internal DNameRecord() {} - - /// - /// Creates a new instance of the DNameRecord class - /// - /// Name of the record - /// Seconds the record should be cached at most - /// Target of the redirection - public DNameRecord(DomainName name, int timeToLive, DomainName target) - : base(name, RecordType.DName, RecordClass.INet, timeToLive) - { - Target = target ?? DomainName.Root; - } - - internal override void ParseRecordData(byte[] resultData, int startPosition, int length) - { - Target = DnsMessageBase.ParseDomainName(resultData, ref startPosition); - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length != 1) - throw new FormatException(); - - Target = ParseDomainName(origin, stringRepresentation[0]); - } - - internal override string RecordDataToString() - { - return Target.ToString(); - } - - protected internal override int MaximumRecordDataLength => Target.MaximumRecordDataLength + 2; - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - DnsMessageBase.EncodeDomainName(messageData, offset, ref currentPosition, Target, null, useCanonical); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/DhcidRecord.cs b/ARSoft.Tools.Net/Dns/DnsRecord/DhcidRecord.cs deleted file mode 100644 index a6e2a65..0000000 --- a/ARSoft.Tools.Net/Dns/DnsRecord/DhcidRecord.cs +++ /dev/null @@ -1,79 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Dynamic Host Configuration Protocol (DHCP) Information record - /// - /// Defined in - /// RFC 4701 - /// - /// - public class DhcidRecord : DnsRecordBase - { - /// - /// Record data - /// - public byte[] RecordData { get; private set; } - - internal DhcidRecord() {} - - /// - /// Creates a new instance of the DhcidRecord class - /// - /// Name of the record - /// Seconds the record should be cached at most - /// Record data - public DhcidRecord(DomainName name, int timeToLive, byte[] recordData) - : base(name, RecordType.Dhcid, RecordClass.INet, timeToLive) - { - RecordData = recordData ?? new byte[] { }; - } - - internal override void ParseRecordData(byte[] resultData, int startPosition, int length) - { - RecordData = DnsMessageBase.ParseByteData(resultData, ref startPosition, length); - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length < 1) - throw new FormatException(); - - RecordData = String.Join(String.Empty, stringRepresentation).FromBase64String(); - } - - internal override string RecordDataToString() - { - return RecordData.ToBase64String(); - } - - protected internal override int MaximumRecordDataLength => RecordData.Length; - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, RecordData); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/DnsRecordBase.cs b/ARSoft.Tools.Net/Dns/DnsRecord/DnsRecordBase.cs index 7022acc..5eb9b62 100644 --- a/ARSoft.Tools.Net/Dns/DnsRecord/DnsRecordBase.cs +++ b/ARSoft.Tools.Net/Dns/DnsRecord/DnsRecordBase.cs @@ -52,15 +52,8 @@ protected DnsRecordBase(DomainName name, RecordType recordType, RecordClass reco internal static DnsRecordBase Create(RecordType type, byte[] resultData, int recordDataPosition) { - if ((type == RecordType.Key) && (resultData[recordDataPosition + 3] == (byte) DnsSecAlgorithm.DiffieHellman)) - { - return new DiffieHellmanKeyRecord(); - } - else - { - return Create(type); - } - } + return Create(type); + } internal static DnsRecordBase Create(RecordType type) { @@ -74,36 +67,14 @@ internal static DnsRecordBase Create(RecordType type) return new CNameRecord(); case RecordType.Soa: return new SoaRecord(); - case RecordType.Wks: - return new WksRecord(); case RecordType.Ptr: return new PtrRecord(); - case RecordType.HInfo: - return new HInfoRecord(); case RecordType.Mx: return new MxRecord(); case RecordType.Txt: return new TxtRecord(); case RecordType.Rp: return new RpRecord(); - case RecordType.Afsdb: - return new AfsdbRecord(); - case RecordType.X25: - return new X25Record(); - case RecordType.Isdn: - return new IsdnRecord(); - case RecordType.Rt: - return new RtRecord(); - case RecordType.Nsap: - return new NsapRecord(); - case RecordType.Sig: - return new SigRecord(); - case RecordType.Key: - return new KeyRecord(); - case RecordType.Px: - return new PxRecord(); - case RecordType.GPos: - return new GPosRecord(); case RecordType.Aaaa: return new AaaaRecord(); case RecordType.Loc: @@ -112,72 +83,10 @@ internal static DnsRecordBase Create(RecordType type) return new SrvRecord(); case RecordType.Naptr: return new NaptrRecord(); - case RecordType.Kx: - return new KxRecord(); - case RecordType.Cert: - return new CertRecord(); - case RecordType.DName: - return new DNameRecord(); - case RecordType.Opt: - return new OptRecord(); - case RecordType.Apl: - return new AplRecord(); - case RecordType.Ds: - return new DsRecord(); - case RecordType.SshFp: - return new SshFpRecord(); - case RecordType.IpSecKey: - return new IpSecKeyRecord(); - case RecordType.RrSig: - return new RrSigRecord(); - case RecordType.NSec: - return new NSecRecord(); - case RecordType.DnsKey: - return new DnsKeyRecord(); - case RecordType.Dhcid: - return new DhcidRecord(); - case RecordType.NSec3: - return new NSec3Record(); - case RecordType.NSec3Param: - return new NSec3ParamRecord(); - case RecordType.Tlsa: - return new TlsaRecord(); - case RecordType.Hip: - return new HipRecord(); - case RecordType.CDs: - return new CDsRecord(); - case RecordType.CDnsKey: - return new CDnsKeyRecord(); - case RecordType.OpenPGPKey: - return new OpenPGPKeyRecord(); - case RecordType.CSync: - return new CSyncRecord(); -#pragma warning disable 0612 - case RecordType.Spf: - return new SpfRecord(); -#pragma warning restore 0612 - case RecordType.NId: - return new NIdRecord(); - case RecordType.L32: - return new L32Record(); - case RecordType.L64: - return new L64Record(); - case RecordType.LP: - return new LPRecord(); case RecordType.Eui48: return new Eui48Record(); case RecordType.Eui64: return new Eui64Record(); - case RecordType.TKey: - return new TKeyRecord(); - case RecordType.TSig: - return new TSigRecord(); - case RecordType.Uri: - return new UriRecord(); - case RecordType.CAA: - return new CAARecord(); - case RecordType.Dlv: - return new DlvRecord(); default: return new UnknownRecord(); diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/GPosRecord.cs b/ARSoft.Tools.Net/Dns/DnsRecord/GPosRecord.cs deleted file mode 100644 index ce3bbb2..0000000 --- a/ARSoft.Tools.Net/Dns/DnsRecord/GPosRecord.cs +++ /dev/null @@ -1,102 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Geographical position - /// - /// Defined in - /// RFC 1712 - /// - /// - public class GPosRecord : DnsRecordBase - { - /// - /// Longitude of the geographical position - /// - public double Longitude { get; private set; } - - /// - /// Latitude of the geographical position - /// - public double Latitude { get; private set; } - - /// - /// Altitude of the geographical position - /// - public double Altitude { get; private set; } - - internal GPosRecord() {} - - /// - /// Creates a new instance of the GPosRecord class - /// - /// Name of the record - /// Seconds the record should be cached at most - /// Longitude of the geographical position - /// Latitude of the geographical position - /// Altitude of the geographical position - public GPosRecord(DomainName name, int timeToLive, double longitude, double latitude, double altitude) - : base(name, RecordType.GPos, RecordClass.INet, timeToLive) - { - Longitude = longitude; - Latitude = latitude; - Altitude = altitude; - } - - internal override void ParseRecordData(byte[] resultData, int currentPosition, int length) - { - Longitude = Double.Parse(DnsMessageBase.ParseText(resultData, ref currentPosition), CultureInfo.InvariantCulture); - Latitude = Double.Parse(DnsMessageBase.ParseText(resultData, ref currentPosition), CultureInfo.InvariantCulture); - Altitude = Double.Parse(DnsMessageBase.ParseText(resultData, ref currentPosition), CultureInfo.InvariantCulture); - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length != 3) - throw new FormatException(); - - Longitude = Double.Parse(stringRepresentation[0], CultureInfo.InvariantCulture); - Latitude = Double.Parse(stringRepresentation[1], CultureInfo.InvariantCulture); - Altitude = Double.Parse(stringRepresentation[2], CultureInfo.InvariantCulture); - } - - internal override string RecordDataToString() - { - return Longitude.ToString(CultureInfo.InvariantCulture) - + " " + Latitude.ToString(CultureInfo.InvariantCulture) - + " " + Altitude.ToString(CultureInfo.InvariantCulture); - } - - protected internal override int MaximumRecordDataLength => 3 + Longitude.ToString(CultureInfo.InvariantCulture).Length + Latitude.ToString(CultureInfo.InvariantCulture).Length + Altitude.ToString(CultureInfo.InvariantCulture).Length; - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - DnsMessageBase.EncodeTextBlock(messageData, ref currentPosition, Longitude.ToString(CultureInfo.InvariantCulture)); - DnsMessageBase.EncodeTextBlock(messageData, ref currentPosition, Latitude.ToString(CultureInfo.InvariantCulture)); - DnsMessageBase.EncodeTextBlock(messageData, ref currentPosition, Altitude.ToString(CultureInfo.InvariantCulture)); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/HInfoRecord.cs b/ARSoft.Tools.Net/Dns/DnsRecord/HInfoRecord.cs deleted file mode 100644 index c6553a3..0000000 --- a/ARSoft.Tools.Net/Dns/DnsRecord/HInfoRecord.cs +++ /dev/null @@ -1,90 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Host information - /// - /// Defined in - /// RFC 1035 - /// - /// - public class HInfoRecord : DnsRecordBase - { - /// - /// Type of the CPU of the host - /// - public string Cpu { get; private set; } - - /// - /// Name of the operating system of the host - /// - public string OperatingSystem { get; private set; } - - internal HInfoRecord() {} - - /// - /// Creates a new instance of the HInfoRecord class - /// - /// Name of the host - /// Seconds the record should be cached at most - /// Type of the CPU of the host - /// Name of the operating system of the host - public HInfoRecord(DomainName name, int timeToLive, string cpu, string operatingSystem) - : base(name, RecordType.HInfo, RecordClass.INet, timeToLive) - { - Cpu = cpu ?? String.Empty; - OperatingSystem = operatingSystem ?? String.Empty; - } - - internal override void ParseRecordData(byte[] resultData, int startPosition, int length) - { - Cpu = DnsMessageBase.ParseText(resultData, ref startPosition); - OperatingSystem = DnsMessageBase.ParseText(resultData, ref startPosition); - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length != 2) - throw new FormatException(); - - Cpu = stringRepresentation[0]; - OperatingSystem = stringRepresentation[1]; - } - - internal override string RecordDataToString() - { - return "\"" + Cpu.ToMasterfileLabelRepresentation() + "\"" - + " \"" + OperatingSystem.ToMasterfileLabelRepresentation() + "\""; - } - - protected internal override int MaximumRecordDataLength => 2 + Cpu.Length + OperatingSystem.Length; - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - DnsMessageBase.EncodeTextBlock(messageData, ref currentPosition, Cpu); - DnsMessageBase.EncodeTextBlock(messageData, ref currentPosition, OperatingSystem); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/HipRecord.cs b/ARSoft.Tools.Net/Dns/DnsRecord/HipRecord.cs deleted file mode 100644 index 829b570..0000000 --- a/ARSoft.Tools.Net/Dns/DnsRecord/HipRecord.cs +++ /dev/null @@ -1,135 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Host identity protocol - /// - /// Defined in - /// RFC 5205 - /// - /// - public class HipRecord : DnsRecordBase - { - /// - /// Algorithm of the key - /// - public IpSecKeyRecord.IpSecAlgorithm Algorithm { get; private set; } - - /// - /// Host identity tag - /// - public byte[] Hit { get; private set; } - - /// - /// Binary data of the public key - /// - public byte[] PublicKey { get; private set; } - - /// - /// Possible rendezvous servers - /// - public List RendezvousServers { get; private set; } - - internal HipRecord() {} - - /// - /// Creates a new instace of the HipRecord class - /// - /// Name of the record - /// Seconds the record should be cached at most - /// Algorithm of the key - /// Host identity tag - /// Binary data of the public key - /// Possible rendezvous servers - public HipRecord(DomainName name, int timeToLive, IpSecKeyRecord.IpSecAlgorithm algorithm, byte[] hit, byte[] publicKey, List rendezvousServers) - : base(name, RecordType.Hip, RecordClass.INet, timeToLive) - { - Algorithm = algorithm; - Hit = hit ?? new byte[] { }; - PublicKey = publicKey ?? new byte[] { }; - RendezvousServers = rendezvousServers ?? new List(); - } - - internal override void ParseRecordData(byte[] resultData, int currentPosition, int length) - { - int endPosition = currentPosition + length; - - int hitLength = resultData[currentPosition++]; - Algorithm = (IpSecKeyRecord.IpSecAlgorithm) resultData[currentPosition++]; - int publicKeyLength = DnsMessageBase.ParseUShort(resultData, ref currentPosition); - Hit = DnsMessageBase.ParseByteData(resultData, ref currentPosition, hitLength); - PublicKey = DnsMessageBase.ParseByteData(resultData, ref currentPosition, publicKeyLength); - RendezvousServers = new List(); - while (currentPosition < endPosition) - { - RendezvousServers.Add(DnsMessageBase.ParseDomainName(resultData, ref currentPosition)); - } - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length < 3) - throw new FormatException(); - - Algorithm = (IpSecKeyRecord.IpSecAlgorithm) Byte.Parse(stringRepresentation[0]); - Hit = stringRepresentation[1].FromBase16String(); - PublicKey = stringRepresentation[2].FromBase64String(); - RendezvousServers = stringRepresentation.Skip(3).Select(x => ParseDomainName(origin, x)).ToList(); - } - - internal override string RecordDataToString() - { - return (byte) Algorithm - + " " + Hit.ToBase16String() - + " " + PublicKey.ToBase64String() - + " " + String.Join(" ", RendezvousServers.Select(s => s.ToString())); - } - - protected internal override int MaximumRecordDataLength - { - get - { - int res = 4; - res += Hit.Length; - res += PublicKey.Length; - res += RendezvousServers.Sum(s => s.MaximumRecordDataLength + 2); - return res; - } - } - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - messageData[currentPosition++] = (byte) Hit.Length; - messageData[currentPosition++] = (byte) Algorithm; - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, (ushort) PublicKey.Length); - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, Hit); - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, PublicKey); - foreach (DomainName server in RendezvousServers) - { - DnsMessageBase.EncodeDomainName(messageData, offset, ref currentPosition, server, null, false); - } - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/ITextRecord.cs b/ARSoft.Tools.Net/Dns/DnsRecord/ITextRecord.cs index 1582eea..16e3266 100644 --- a/ARSoft.Tools.Net/Dns/DnsRecord/ITextRecord.cs +++ b/ARSoft.Tools.Net/Dns/DnsRecord/ITextRecord.cs @@ -23,8 +23,8 @@ namespace ARSoft.Tools.Net.Dns { - internal interface ITextRecord - { - string TextData { get; } - } + internal interface ITextRecord + { + string TextData { get; } + } } \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/IpSecKeyRecord.cs b/ARSoft.Tools.Net/Dns/DnsRecord/IpSecKeyRecord.cs deleted file mode 100644 index 46cfdd8..0000000 --- a/ARSoft.Tools.Net/Dns/DnsRecord/IpSecKeyRecord.cs +++ /dev/null @@ -1,272 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Net.Sockets; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// IPsec key storage - /// - /// Defined in - /// RFC 4025 - /// - /// - public class IpSecKeyRecord : DnsRecordBase - { - /// - /// Algorithm of key - /// - public enum IpSecAlgorithm : byte - { - /// - /// None - /// - None = 0, - - /// - /// RSA - /// - /// Defined in - /// RFC 4025 - /// - /// - Rsa = 1, - - /// - /// DSA - /// - /// Defined in - /// RFC 4025 - /// - /// - Dsa = 2, - } - - /// - /// Type of gateway - /// - public enum IpSecGatewayType : byte - { - /// - /// None - /// - None = 0, - - /// - /// Gateway is a IPv4 address - /// - /// Defined in - /// RFC 4025 - /// - /// - IpV4 = 1, - - /// - /// Gateway is a IPv6 address - /// - /// Defined in - /// RFC 4025 - /// - /// - IpV6 = 2, - - /// - /// Gateway is a domain name - /// - /// Defined in - /// RFC 4025 - /// - /// - Domain = 3, - } - - /// - /// Precedence of the record - /// - public byte Precedence { get; private set; } - - /// - /// Type of gateway - /// - public IpSecGatewayType GatewayType { get; private set; } - - /// - /// Algorithm of the key - /// - public IpSecAlgorithm Algorithm { get; private set; } - - /// - /// Address of the gateway - /// - public string Gateway { get; private set; } - - /// - /// Binary data of the public key - /// - public byte[] PublicKey { get; private set; } - - internal IpSecKeyRecord() {} - - /// - /// Creates a new instance of the IpSecKeyRecord class - /// - /// Name of the record - /// Seconds the record should be cached at most - /// Precedence of the record - /// Algorithm of the key - /// Address of the gateway - /// Binary data of the public key - public IpSecKeyRecord(DomainName name, int timeToLive, byte precedence, IpSecAlgorithm algorithm, DomainName gateway, byte[] publicKey) - : base(name, RecordType.IpSecKey, RecordClass.INet, timeToLive) - { - Precedence = precedence; - GatewayType = IpSecGatewayType.Domain; - Algorithm = algorithm; - Gateway = (gateway ?? DomainName.Root).ToString(); - PublicKey = publicKey ?? new byte[] { }; - } - - /// - /// Creates a new instance of the IpSecKeyRecord class - /// - /// Name of the record - /// Seconds the record should be cached at most - /// Precedence of the record - /// Algorithm of the key - /// Address of the gateway - /// Binary data of the public key - public IpSecKeyRecord(DomainName name, int timeToLive, byte precedence, IpSecAlgorithm algorithm, IPAddress gateway, byte[] publicKey) - : base(name, RecordType.IpSecKey, RecordClass.INet, timeToLive) - { - Precedence = precedence; - GatewayType = (gateway.AddressFamily == AddressFamily.InterNetwork) ? IpSecGatewayType.IpV4 : IpSecGatewayType.IpV6; - Algorithm = algorithm; - Gateway = gateway.ToString(); - PublicKey = publicKey ?? new byte[] { }; - } - - internal override void ParseRecordData(byte[] resultData, int currentPosition, int length) - { - int startPosition = currentPosition; - - Precedence = resultData[currentPosition++]; - GatewayType = (IpSecGatewayType) resultData[currentPosition++]; - Algorithm = (IpSecAlgorithm) resultData[currentPosition++]; - switch (GatewayType) - { - case IpSecGatewayType.None: - Gateway = String.Empty; - break; - case IpSecGatewayType.IpV4: - Gateway = new IPAddress(DnsMessageBase.ParseByteData(resultData, ref currentPosition, 4)).ToString(); - break; - case IpSecGatewayType.IpV6: - Gateway = new IPAddress(DnsMessageBase.ParseByteData(resultData, ref currentPosition, 16)).ToString(); - break; - case IpSecGatewayType.Domain: - Gateway = DnsMessageBase.ParseDomainName(resultData, ref currentPosition).ToString(); - break; - } - PublicKey = DnsMessageBase.ParseByteData(resultData, ref currentPosition, length + startPosition - currentPosition); - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length < 5) - throw new FormatException(); - - Precedence = Byte.Parse(stringRepresentation[0]); - GatewayType = (IpSecGatewayType) Byte.Parse(stringRepresentation[1]); - Algorithm = (IpSecAlgorithm) Byte.Parse(stringRepresentation[2]); - Gateway = stringRepresentation[3]; - PublicKey = String.Join(String.Empty, stringRepresentation.Skip(4)).FromBase64String(); - } - - internal override string RecordDataToString() - { - return Precedence - + " " + (byte) GatewayType - + " " + (byte) Algorithm - + " " + GatewayToString() - + " " + PublicKey.ToBase64String(); - } - - private string GatewayToString() - { - switch (GatewayType) - { - case IpSecGatewayType.Domain: - return Gateway.ToMasterfileLabelRepresentation() + "."; - - case IpSecGatewayType.IpV4: - case IpSecGatewayType.IpV6: - return Gateway; - - default: - return "."; - } - } - - protected internal override int MaximumRecordDataLength - { - get - { - int res = 3; - switch (GatewayType) - { - case IpSecGatewayType.IpV4: - res += 4; - break; - case IpSecGatewayType.IpV6: - res += 16; - break; - case IpSecGatewayType.Domain: - res += 2 + Gateway.Length; - break; - } - res += PublicKey.Length; - return res; - } - } - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - messageData[currentPosition++] = Precedence; - messageData[currentPosition++] = (byte) GatewayType; - messageData[currentPosition++] = (byte) Algorithm; - switch (GatewayType) - { - case IpSecGatewayType.IpV4: - case IpSecGatewayType.IpV6: - byte[] addressBuffer = IPAddress.Parse(Gateway).GetAddressBytes(); - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, addressBuffer); - break; - case IpSecGatewayType.Domain: - DnsMessageBase.EncodeDomainName(messageData, offset, ref currentPosition, ParseDomainName(DomainName.Root, Gateway), null, false); - break; - } - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, PublicKey); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/IsdnRecord.cs b/ARSoft.Tools.Net/Dns/DnsRecord/IsdnRecord.cs deleted file mode 100644 index 4838244..0000000 --- a/ARSoft.Tools.Net/Dns/DnsRecord/IsdnRecord.cs +++ /dev/null @@ -1,103 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// ISDN address - /// - /// Defined in - /// RFC 1183 - /// - /// - public class IsdnRecord : DnsRecordBase - { - /// - /// ISDN number - /// - public string IsdnAddress { get; private set; } - - /// - /// Sub address - /// - public string SubAddress { get; private set; } - - internal IsdnRecord() {} - - /// - /// Creates a new instance of the IsdnRecord class - /// - /// Name of the record - /// Seconds the record should be cached at most - /// ISDN number - public IsdnRecord(DomainName name, int timeToLive, string isdnAddress) - : this(name, timeToLive, isdnAddress, String.Empty) {} - - /// - /// Creates a new instance of the IsdnRecord class - /// - /// Name of the record - /// Seconds the record should be cached at most - /// ISDN number - /// Sub address - public IsdnRecord(DomainName name, int timeToLive, string isdnAddress, string subAddress) - : base(name, RecordType.Isdn, RecordClass.INet, timeToLive) - { - IsdnAddress = isdnAddress ?? String.Empty; - SubAddress = subAddress ?? String.Empty; - } - - internal override void ParseRecordData(byte[] resultData, int currentPosition, int length) - { - int endPosition = currentPosition + length; - - IsdnAddress = DnsMessageBase.ParseText(resultData, ref currentPosition); - SubAddress = (currentPosition < endPosition) ? DnsMessageBase.ParseText(resultData, ref currentPosition) : String.Empty; - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length > 2) - throw new FormatException(); - - IsdnAddress = stringRepresentation[0]; - - if (stringRepresentation.Length > 1) - SubAddress = stringRepresentation[1]; - } - - internal override string RecordDataToString() - { - return IsdnAddress.ToMasterfileLabelRepresentation() - + (String.IsNullOrEmpty(SubAddress) ? String.Empty : " " + SubAddress.ToMasterfileLabelRepresentation()); - } - - protected internal override int MaximumRecordDataLength => 2 + IsdnAddress.Length + SubAddress.Length; - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - DnsMessageBase.EncodeTextBlock(messageData, ref currentPosition, IsdnAddress); - DnsMessageBase.EncodeTextBlock(messageData, ref currentPosition, SubAddress); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/KxRecord.cs b/ARSoft.Tools.Net/Dns/DnsRecord/KxRecord.cs deleted file mode 100644 index 7904f48..0000000 --- a/ARSoft.Tools.Net/Dns/DnsRecord/KxRecord.cs +++ /dev/null @@ -1,90 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Key exchanger record - /// - /// Defined in - /// RFC 2230 - /// - /// - public class KxRecord : DnsRecordBase - { - /// - /// Preference of the record - /// - public ushort Preference { get; private set; } - - /// - /// Domain name of the exchange host - /// - public DomainName Exchanger { get; private set; } - - internal KxRecord() {} - - /// - /// Creates a new instance of the KxRecord class - /// - /// Name of the record - /// Seconds the record should be cached at most - /// Preference of the record - /// Domain name of the exchange host - public KxRecord(DomainName name, int timeToLive, ushort preference, DomainName exchanger) - : base(name, RecordType.Kx, RecordClass.INet, timeToLive) - { - Preference = preference; - Exchanger = exchanger ?? DomainName.Root; - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length != 2) - throw new FormatException(); - - Preference = UInt16.Parse(stringRepresentation[0]); - Exchanger = ParseDomainName(origin, stringRepresentation[1]); - } - - internal override void ParseRecordData(byte[] resultData, int startPosition, int length) - { - Preference = DnsMessageBase.ParseUShort(resultData, ref startPosition); - Exchanger = DnsMessageBase.ParseDomainName(resultData, ref startPosition); - } - - internal override string RecordDataToString() - { - return Preference - + " " + Exchanger; - } - - protected internal override int MaximumRecordDataLength => Exchanger.MaximumRecordDataLength + 4; - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, Preference); - DnsMessageBase.EncodeDomainName(messageData, offset, ref currentPosition, Exchanger, domainNames, useCanonical); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/L32Record.cs b/ARSoft.Tools.Net/Dns/DnsRecord/L32Record.cs deleted file mode 100644 index f8cf52f..0000000 --- a/ARSoft.Tools.Net/Dns/DnsRecord/L32Record.cs +++ /dev/null @@ -1,90 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// L32 - /// - /// Defined in - /// RFC 6742 - /// - /// - public class L32Record : DnsRecordBase - { - /// - /// The preference - /// - public ushort Preference { get; private set; } - - /// - /// The Locator - /// - public uint Locator32 { get; private set; } - - internal L32Record() {} - - /// - /// Creates a new instance of the L32Record class - /// - /// Domain name of the host - /// Seconds the record should be cached at most - /// The preference - /// The Locator - public L32Record(DomainName name, int timeToLive, ushort preference, uint locator32) - : base(name, RecordType.L32, RecordClass.INet, timeToLive) - { - Preference = preference; - Locator32 = locator32; - } - - internal override void ParseRecordData(byte[] resultData, int startPosition, int length) - { - Preference = DnsMessageBase.ParseUShort(resultData, ref startPosition); - Locator32 = DnsMessageBase.ParseUInt(resultData, ref startPosition); - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length != 2) - throw new FormatException(); - - Preference = UInt16.Parse(stringRepresentation[0]); - Locator32 = UInt32.Parse(stringRepresentation[1]); - } - - internal override string RecordDataToString() - { - return Preference + " " + new IPAddress(Locator32); - } - - protected internal override int MaximumRecordDataLength => 6; - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, Preference); - DnsMessageBase.EncodeUInt(messageData, ref currentPosition, Locator32); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/L64Record.cs b/ARSoft.Tools.Net/Dns/DnsRecord/L64Record.cs deleted file mode 100644 index 657cd6c..0000000 --- a/ARSoft.Tools.Net/Dns/DnsRecord/L64Record.cs +++ /dev/null @@ -1,90 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// L64 - /// - /// Defined in - /// RFC 6742 - /// - /// - public class L64Record : DnsRecordBase - { - /// - /// The preference - /// - public ushort Preference { get; private set; } - - /// - /// The Locator - /// - public ulong Locator64 { get; private set; } - - internal L64Record() {} - - /// - /// Creates a new instance of the L64Record class - /// - /// Domain name of the host - /// Seconds the record should be cached at most - /// The preference - /// The Locator - public L64Record(DomainName name, int timeToLive, ushort preference, ulong locator64) - : base(name, RecordType.L64, RecordClass.INet, timeToLive) - { - Preference = preference; - Locator64 = locator64; - } - - internal override void ParseRecordData(byte[] resultData, int startPosition, int length) - { - Preference = DnsMessageBase.ParseUShort(resultData, ref startPosition); - Locator64 = DnsMessageBase.ParseULong(resultData, ref startPosition); - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length != 2) - throw new FormatException(); - - Preference = UInt16.Parse(stringRepresentation[0]); - Locator64 = UInt64.Parse(stringRepresentation[1]); - } - - internal override string RecordDataToString() - { - string locator = Locator64.ToString("x16"); - return Preference + " " + locator.Substring(0, 4) + ":" + locator.Substring(4, 4) + ":" + locator.Substring(8, 4) + ":" + locator.Substring(12); - } - - protected internal override int MaximumRecordDataLength => 10; - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, Preference); - DnsMessageBase.EncodeULong(messageData, ref currentPosition, Locator64); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/LPRecord.cs b/ARSoft.Tools.Net/Dns/DnsRecord/LPRecord.cs deleted file mode 100644 index 53ffc77..0000000 --- a/ARSoft.Tools.Net/Dns/DnsRecord/LPRecord.cs +++ /dev/null @@ -1,91 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// LP - /// - /// Defined in - /// RFC 6742 - /// - /// - // ReSharper disable once InconsistentNaming - public class LPRecord : DnsRecordBase - { - /// - /// The preference - /// - public ushort Preference { get; private set; } - - /// - /// The FQDN - /// - // ReSharper disable once InconsistentNaming - public DomainName FQDN { get; private set; } - - internal LPRecord() {} - - /// - /// Creates a new instance of the LpRecord class - /// - /// Domain name of the host - /// Seconds the record should be cached at most - /// The preference - /// The FQDN - public LPRecord(DomainName name, int timeToLive, ushort preference, DomainName fqdn) - : base(name, RecordType.LP, RecordClass.INet, timeToLive) - { - Preference = preference; - FQDN = fqdn; - } - - internal override void ParseRecordData(byte[] resultData, int startPosition, int length) - { - Preference = DnsMessageBase.ParseUShort(resultData, ref startPosition); - FQDN = DnsMessageBase.ParseDomainName(resultData, ref startPosition); - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length != 2) - throw new FormatException(); - - Preference = UInt16.Parse(stringRepresentation[0]); - FQDN = ParseDomainName(origin, stringRepresentation[1]); - } - - internal override string RecordDataToString() - { - return Preference + " " + FQDN; - } - - protected internal override int MaximumRecordDataLength => 4 + FQDN.MaximumRecordDataLength; - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, Preference); - DnsMessageBase.EncodeDomainName(messageData, offset, ref currentPosition, FQDN, null, false); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/NIdRecord.cs b/ARSoft.Tools.Net/Dns/DnsRecord/NIdRecord.cs deleted file mode 100644 index f20fc7a..0000000 --- a/ARSoft.Tools.Net/Dns/DnsRecord/NIdRecord.cs +++ /dev/null @@ -1,103 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// NID - /// - /// Defined in - /// RFC 6742 - /// - /// - public class NIdRecord : DnsRecordBase - { - /// - /// The preference - /// - public ushort Preference { get; private set; } - - /// - /// The Node ID - /// - public ulong NodeID { get; private set; } - - internal NIdRecord() {} - - /// - /// Creates a new instance of the NIdRecord class - /// - /// Domain name of the host - /// Seconds the record should be cached at most - /// The preference - /// The Node ID - public NIdRecord(DomainName name, int timeToLive, ushort preference, ulong nodeID) - : base(name, RecordType.NId, RecordClass.INet, timeToLive) - { - Preference = preference; - NodeID = nodeID; - } - - internal override void ParseRecordData(byte[] resultData, int startPosition, int length) - { - Preference = DnsMessageBase.ParseUShort(resultData, ref startPosition); - NodeID = DnsMessageBase.ParseULong(resultData, ref startPosition); - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length != 2) - throw new FormatException(); - - Preference = UInt16.Parse(stringRepresentation[0]); - - string[] nodeIDParts = stringRepresentation[1].Split(':'); - - if (nodeIDParts.Length != 4) - throw new FormatException(); - - for (int i = 0; i < 4; i++) - { - if (nodeIDParts[i].Length != 4) - throw new FormatException(); - - NodeID = NodeID << 16; - NodeID |= Convert.ToUInt16(nodeIDParts[i], 16); - } - } - - internal override string RecordDataToString() - { - string nodeID = NodeID.ToString("x16"); - return Preference + " " + nodeID.Substring(0, 4) + ":" + nodeID.Substring(4, 4) + ":" + nodeID.Substring(8, 4) + ":" + nodeID.Substring(12); - } - - protected internal override int MaximumRecordDataLength => 10; - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, Preference); - DnsMessageBase.EncodeULong(messageData, ref currentPosition, NodeID); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/NsapRecord.cs b/ARSoft.Tools.Net/Dns/DnsRecord/NsapRecord.cs deleted file mode 100644 index cf67ef5..0000000 --- a/ARSoft.Tools.Net/Dns/DnsRecord/NsapRecord.cs +++ /dev/null @@ -1,84 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// NSAP address, NSAP style A record - /// - /// Defined in - /// RFC 1706 - /// and - /// RFC 1348 - /// - /// - public class NsapRecord : DnsRecordBase - { - /// - /// Binary encoded NSAP data - /// - public byte[] RecordData { get; private set; } - - internal NsapRecord() {} - - /// - /// Creates a new instance of the NsapRecord class - /// - /// Name of the record - /// Seconds the record should be cached at most - /// Binary encoded NSAP data - public NsapRecord(DomainName name, int timeToLive, byte[] recordData) - : base(name, RecordType.Nsap, RecordClass.INet, timeToLive) - { - RecordData = recordData ?? new byte[] { }; - } - - internal override void ParseRecordData(byte[] resultData, int startPosition, int length) - { - RecordData = DnsMessageBase.ParseByteData(resultData, ref startPosition, length); - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length != 1) - throw new FormatException(); - - if (!stringRepresentation[0].StartsWith("0x", StringComparison.InvariantCultureIgnoreCase)) - throw new FormatException(); - - RecordData = stringRepresentation[0].Substring(2).Replace(".", String.Empty).FromBase16String(); - } - - internal override string RecordDataToString() - { - return "0x" + RecordData.ToBase16String(); - } - - protected internal override int MaximumRecordDataLength => RecordData.Length; - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, RecordData); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/OpenPGPKeyRecord.cs b/ARSoft.Tools.Net/Dns/DnsRecord/OpenPGPKeyRecord.cs deleted file mode 100644 index af49760..0000000 --- a/ARSoft.Tools.Net/Dns/DnsRecord/OpenPGPKeyRecord.cs +++ /dev/null @@ -1,78 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// OpenPGP Key - /// - /// Defined in - /// draft-ietf-dane-openpgpkey - /// - /// - // ReSharper disable once InconsistentNaming - public class OpenPGPKeyRecord : DnsRecordBase - { - /// - /// The Public Key - /// - public byte[] PublicKey { get; private set; } - - internal OpenPGPKeyRecord() {} - - /// - /// Creates a new instance of the OpenPGPKeyRecord class - /// - /// Domain name of the host - /// Seconds the record should be cached at most - /// The Public Key - public OpenPGPKeyRecord(DomainName name, int timeToLive, byte[] publicKey) - : base(name, RecordType.OpenPGPKey, RecordClass.INet, timeToLive) - { - PublicKey = publicKey ?? new byte[] { }; - } - - internal override void ParseRecordData(byte[] resultData, int startPosition, int length) - { - PublicKey = DnsMessageBase.ParseByteData(resultData, ref startPosition, length); - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length == 0) - throw new NotSupportedException(); - - PublicKey = String.Join(String.Empty, stringRepresentation).FromBase64String(); - } - - internal override string RecordDataToString() - { - return PublicKey.ToBase64String(); - } - - protected internal override int MaximumRecordDataLength => PublicKey.Length; - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, PublicKey); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/PxRecord.cs b/ARSoft.Tools.Net/Dns/DnsRecord/PxRecord.cs deleted file mode 100644 index a46c24d..0000000 --- a/ARSoft.Tools.Net/Dns/DnsRecord/PxRecord.cs +++ /dev/null @@ -1,101 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// X.400 mail mapping information record - /// - /// Defined in - /// RFC 2163 - /// - /// - public class PxRecord : DnsRecordBase - { - /// - /// Preference of the record - /// - public ushort Preference { get; private set; } - - /// - /// Domain name containing the RFC822 domain - /// - public DomainName Map822 { get; private set; } - - /// - /// Domain name containing the X.400 part - /// - public DomainName MapX400 { get; private set; } - - internal PxRecord() {} - - /// - /// Creates a new instance of the PxRecord class - /// - /// Name of the record - /// Seconds the record should be cached at most - /// Preference of the record - /// Domain name containing the RFC822 domain - /// Domain name containing the X.400 part - public PxRecord(DomainName name, int timeToLive, ushort preference, DomainName map822, DomainName mapX400) - : base(name, RecordType.Px, RecordClass.INet, timeToLive) - { - Preference = preference; - Map822 = map822 ?? DomainName.Root; - MapX400 = mapX400 ?? DomainName.Root; - } - - internal override void ParseRecordData(byte[] resultData, int startPosition, int length) - { - Preference = DnsMessageBase.ParseUShort(resultData, ref startPosition); - Map822 = DnsMessageBase.ParseDomainName(resultData, ref startPosition); - MapX400 = DnsMessageBase.ParseDomainName(resultData, ref startPosition); - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length != 3) - throw new FormatException(); - - Preference = UInt16.Parse(stringRepresentation[0]); - Map822 = ParseDomainName(origin, stringRepresentation[1]); - MapX400 = ParseDomainName(origin, stringRepresentation[2]); - } - - internal override string RecordDataToString() - { - return Preference - + " " + Map822 - + " " + MapX400; - } - - protected internal override int MaximumRecordDataLength => 6 + Map822.MaximumRecordDataLength + MapX400.MaximumRecordDataLength; - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, Preference); - DnsMessageBase.EncodeDomainName(messageData, offset, ref currentPosition, Map822, null, useCanonical); - DnsMessageBase.EncodeDomainName(messageData, offset, ref currentPosition, MapX400, null, useCanonical); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/RtRecord.cs b/ARSoft.Tools.Net/Dns/DnsRecord/RtRecord.cs deleted file mode 100644 index c505cff..0000000 --- a/ARSoft.Tools.Net/Dns/DnsRecord/RtRecord.cs +++ /dev/null @@ -1,90 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Route through record - /// - /// Defined in - /// RFC 1183 - /// - /// - public class RtRecord : DnsRecordBase - { - /// - /// Preference of the record - /// - public ushort Preference { get; private set; } - - /// - /// Name of the intermediate host - /// - public DomainName IntermediateHost { get; private set; } - - internal RtRecord() {} - - /// - /// Creates a new instance of the RtRecord class - /// - /// Name of the record - /// Seconds the record should be cached at most - /// Preference of the record - /// Name of the intermediate host - public RtRecord(DomainName name, int timeToLive, ushort preference, DomainName intermediateHost) - : base(name, RecordType.Rt, RecordClass.INet, timeToLive) - { - Preference = preference; - IntermediateHost = intermediateHost ?? DomainName.Root; - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length != 2) - throw new FormatException(); - - Preference = UInt16.Parse(stringRepresentation[0]); - IntermediateHost = ParseDomainName(origin, stringRepresentation[1]); - } - - internal override void ParseRecordData(byte[] resultData, int startPosition, int length) - { - Preference = DnsMessageBase.ParseUShort(resultData, ref startPosition); - IntermediateHost = DnsMessageBase.ParseDomainName(resultData, ref startPosition); - } - - internal override string RecordDataToString() - { - return Preference - + " " + IntermediateHost; - } - - protected internal override int MaximumRecordDataLength => IntermediateHost.MaximumRecordDataLength + 4; - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, Preference); - DnsMessageBase.EncodeDomainName(messageData, offset, ref currentPosition, IntermediateHost, null, useCanonical); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/SpfRecord.cs b/ARSoft.Tools.Net/Dns/DnsRecord/SpfRecord.cs deleted file mode 100644 index 4b84c8c..0000000 --- a/ARSoft.Tools.Net/Dns/DnsRecord/SpfRecord.cs +++ /dev/null @@ -1,58 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Sender Policy Framework - /// - /// Defined in - /// RFC 4408 - /// and - /// RFC 7208 - /// - /// - [Obsolete] - public class SpfRecord : TextRecordBase - { - internal SpfRecord() {} - - /// - /// Creates a new instance of the SpfRecord class - /// - /// Name of the record - /// Seconds the record should be cached at most - /// Text data of the record - public SpfRecord(DomainName name, int timeToLive, string textData) - : base(name, RecordType.Spf, timeToLive, textData) {} - - /// - /// Creates a new instance of the SpfRecord class - /// - /// Name of the record - /// Seconds the record should be cached at most - /// All parts of the text data - public SpfRecord(DomainName name, int timeToLive, IEnumerable textParts) - : base(name, RecordType.Spf, timeToLive, textParts) {} - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/SshFpRecord.cs b/ARSoft.Tools.Net/Dns/DnsRecord/SshFpRecord.cs deleted file mode 100644 index fcd59e3..0000000 --- a/ARSoft.Tools.Net/Dns/DnsRecord/SshFpRecord.cs +++ /dev/null @@ -1,177 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// SSH key fingerprint record - /// - /// Defined in - /// RFC 4255 - /// - /// - public class SshFpRecord : DnsRecordBase - { - /// - /// Algorithm of the fingerprint - /// - public enum SshFpAlgorithm : byte - { - /// - /// None - /// - None = 0, - - /// - /// RSA - /// - /// Defined in - /// RFC 4255 - /// - /// - Rsa = 1, - - /// - /// DSA - /// - /// Defined in - /// RFC 4255 - /// - /// - Dsa = 2, - - /// - /// ECDSA - /// - /// Defined in - /// RFC 6594 - /// - /// - EcDsa = 3, - - /// - /// Ed25519 - /// - /// Defined in - /// RFC 7479 - /// - /// - Ed25519 = 4, - } - - /// - /// Type of the fingerprint - /// - public enum SshFpFingerPrintType : byte - { - /// - /// None - /// - None = 0, - - /// - /// SHA-1 - /// - /// Defined in - /// RFC 4255 - /// - /// - Sha1 = 1, - - /// - /// SHA-1 - /// - /// Defined in - /// RFC 6594 - /// - /// - Sha256 = 2, - } - - /// - /// Algorithm of fingerprint - /// - public SshFpAlgorithm Algorithm { get; private set; } - - /// - /// Type of fingerprint - /// - public SshFpFingerPrintType FingerPrintType { get; private set; } - - /// - /// Binary data of the fingerprint - /// - public byte[] FingerPrint { get; private set; } - - internal SshFpRecord() {} - - /// - /// Creates a new instance of the SshFpRecord class - /// - /// Name of the record - /// Seconds the record should be cached at most - /// Algorithm of fingerprint - /// Type of fingerprint - /// Binary data of the fingerprint - public SshFpRecord(DomainName name, int timeToLive, SshFpAlgorithm algorithm, SshFpFingerPrintType fingerPrintType, byte[] fingerPrint) - : base(name, RecordType.SshFp, RecordClass.INet, timeToLive) - { - Algorithm = algorithm; - FingerPrintType = fingerPrintType; - FingerPrint = fingerPrint ?? new byte[] { }; - } - - internal override void ParseRecordData(byte[] resultData, int currentPosition, int length) - { - Algorithm = (SshFpAlgorithm) resultData[currentPosition++]; - FingerPrintType = (SshFpFingerPrintType) resultData[currentPosition++]; - FingerPrint = DnsMessageBase.ParseByteData(resultData, ref currentPosition, length - 2); - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length < 3) - throw new FormatException(); - - Algorithm = (SshFpAlgorithm) Byte.Parse(stringRepresentation[0]); - FingerPrintType = (SshFpFingerPrintType) Byte.Parse(stringRepresentation[1]); - FingerPrint = String.Join("", stringRepresentation.Skip(2)).FromBase16String(); - } - - internal override string RecordDataToString() - { - return (byte) Algorithm - + " " + (byte) FingerPrintType - + " " + FingerPrint.ToBase16String(); - } - - protected internal override int MaximumRecordDataLength => 2 + FingerPrint.Length; - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - messageData[currentPosition++] = (byte) Algorithm; - messageData[currentPosition++] = (byte) FingerPrintType; - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, FingerPrint); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/TKeyRecord.cs b/ARSoft.Tools.Net/Dns/DnsRecord/TKeyRecord.cs deleted file mode 100644 index be104af..0000000 --- a/ARSoft.Tools.Net/Dns/DnsRecord/TKeyRecord.cs +++ /dev/null @@ -1,204 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Transaction key - /// - /// Defined in - /// RFC 2930 - /// - /// - // ReSharper disable once InconsistentNaming - public class TKeyRecord : DnsRecordBase - { - /// - /// Mode of transaction - /// - // ReSharper disable once InconsistentNaming - public enum TKeyMode : ushort - { - /// - /// Server assignment - /// - /// Defined in - /// RFC 2930 - /// - /// - ServerAssignment = 1, // RFC2930 - - /// - /// Diffie-Hellman exchange - /// - /// Defined in - /// RFC 2930 - /// - /// - DiffieHellmanExchange = 2, // RFC2930 - - /// - /// GSS-API negotiation - /// - /// Defined in - /// RFC 2930 - /// - /// - GssNegotiation = 3, // RFC2930 - - /// - /// Resolver assignment - /// - /// Defined in - /// RFC 2930 - /// - /// - ResolverAssignment = 4, // RFC2930 - - /// - /// Key deletion - /// - /// Defined in - /// RFC 2930 - /// - /// - KeyDeletion = 5, // RFC2930 - } - - /// - /// Algorithm of the key - /// - public TSigAlgorithm Algorithm { get; private set; } - - /// - /// Date from which the key is valid - /// - public DateTime Inception { get; private set; } - - /// - /// Date to which the key is valid - /// - public DateTime Expiration { get; private set; } - - /// - /// Mode of transaction - /// - public TKeyMode Mode { get; private set; } - - /// - /// Error field - /// - public ReturnCode Error { get; private set; } - - /// - /// Binary data of the key - /// - public byte[] Key { get; private set; } - - /// - /// Binary other data - /// - public byte[] OtherData { get; private set; } - - internal TKeyRecord() {} - - /// - /// Creates a new instance of the TKeyRecord class - /// - /// Name of the record - /// Algorithm of the key - /// Date from which the key is valid - /// Date to which the key is valid - /// Mode of transaction - /// Error field - /// Binary data of the key - /// Binary other data - public TKeyRecord(DomainName name, TSigAlgorithm algorithm, DateTime inception, DateTime expiration, TKeyMode mode, ReturnCode error, byte[] key, byte[] otherData) - : base(name, RecordType.TKey, RecordClass.Any, 0) - { - Algorithm = algorithm; - Inception = inception; - Expiration = expiration; - Mode = mode; - Error = error; - Key = key ?? new byte[] { }; - OtherData = otherData ?? new byte[] { }; - } - - internal override void ParseRecordData(byte[] resultData, int startPosition, int length) - { - Algorithm = TSigAlgorithmHelper.GetAlgorithmByName(DnsMessageBase.ParseDomainName(resultData, ref startPosition)); - Inception = ParseDateTime(resultData, ref startPosition); - Expiration = ParseDateTime(resultData, ref startPosition); - Mode = (TKeyMode) DnsMessageBase.ParseUShort(resultData, ref startPosition); - Error = (ReturnCode) DnsMessageBase.ParseUShort(resultData, ref startPosition); - int keyLength = DnsMessageBase.ParseUShort(resultData, ref startPosition); - Key = DnsMessageBase.ParseByteData(resultData, ref startPosition, keyLength); - int otherDataLength = DnsMessageBase.ParseUShort(resultData, ref startPosition); - OtherData = DnsMessageBase.ParseByteData(resultData, ref startPosition, otherDataLength); - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - throw new NotSupportedException(); - } - - internal override string RecordDataToString() - { - return TSigAlgorithmHelper.GetDomainName(Algorithm) - + " " + (int) (Inception - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds - + " " + (int) (Expiration - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds - + " " + (ushort) Mode - + " " + (ushort) Error - + " " + Key.ToBase64String() - + " " + OtherData.ToBase64String(); - } - - protected internal override int MaximumRecordDataLength => 18 + TSigAlgorithmHelper.GetDomainName(Algorithm).MaximumRecordDataLength + Key.Length + OtherData.Length; - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - DnsMessageBase.EncodeDomainName(messageData, offset, ref currentPosition, TSigAlgorithmHelper.GetDomainName(Algorithm), null, false); - EncodeDateTime(messageData, ref currentPosition, Inception); - EncodeDateTime(messageData, ref currentPosition, Expiration); - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, (ushort) Mode); - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, (ushort) Error); - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, (ushort) Key.Length); - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, Key); - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, (ushort) OtherData.Length); - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, OtherData); - } - - internal static void EncodeDateTime(byte[] buffer, ref int currentPosition, DateTime value) - { - int timeStamp = (int) (value.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds; - DnsMessageBase.EncodeInt(buffer, ref currentPosition, timeStamp); - } - - private static DateTime ParseDateTime(byte[] buffer, ref int currentPosition) - { - int timeStamp = DnsMessageBase.ParseInt(buffer, ref currentPosition); - return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(timeStamp).ToLocalTime(); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/TlsaRecord.cs b/ARSoft.Tools.Net/Dns/DnsRecord/TlsaRecord.cs deleted file mode 100644 index 7457156..0000000 --- a/ARSoft.Tools.Net/Dns/DnsRecord/TlsaRecord.cs +++ /dev/null @@ -1,304 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Org.BouncyCastle.Crypto.Digests; -using Org.BouncyCastle.Security; -using Org.BouncyCastle.X509; -using X509Certificate = System.Security.Cryptography.X509Certificates.X509Certificate; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// TLSA - /// - /// Defined in - /// RFC 6698 - /// - /// - public class TlsaRecord : DnsRecordBase - { - /// - /// Certificate Usage - /// - public enum TlsaCertificateUsage : byte - { - /// - /// CA constraint - /// - /// Defined in - /// RFC 6698 - /// - /// - // ReSharper disable once InconsistentNaming - PkixTA = 0, - - /// - /// Service certificate constraint - /// - /// Defined in - /// RFC 6698 - /// - /// - // ReSharper disable once InconsistentNaming - PkixEE = 1, - - /// - /// Trust anchor assertion - /// - /// Defined in - /// RFC 6698 - /// - /// - // ReSharper disable once InconsistentNaming - DaneTA = 2, - - /// - /// - /// Domain-issued certificate - /// - /// - /// Defined in - /// RFC 6698 - /// - /// - // ReSharper disable once InconsistentNaming - DaneEE = 3, - - /// - /// - /// Reserved for Private Use - /// - /// - /// Defined in - /// RFC 6698 - /// - /// - PrivCert = 255, - } - - /// - /// Selector - /// - public enum TlsaSelector : byte - { - /// - /// Full certificate - /// - /// Defined in - /// RFC 6698 - /// - /// - FullCertificate = 0, - - /// - /// DER-encoded binary structure - /// - /// Defined in - /// RFC 6698 - /// - /// - SubjectPublicKeyInfo = 1, - } - - /// - /// Matching Type - /// - public enum TlsaMatchingType : byte - { - /// - /// No hash used - /// - /// Defined in - /// RFC 6698 - /// - /// - Full = 0, - - /// - /// SHA-256 hash - /// - /// Defined in - /// RFC 6698 - /// - /// - Sha256Hash = 1, - - /// - /// SHA-512 hash - /// - /// Defined in - /// RFC 6698 - /// - /// - Sha512Hash = 2, - - /// - /// Reserved for Private Use - /// - /// Defined in - /// RFC 6698 - /// - /// - PrivMatch = 255, - } - - /// - /// The certificate usage - /// - public TlsaCertificateUsage CertificateUsage { get; private set; } - - /// - /// The selector - /// - public TlsaSelector Selector { get; private set; } - - /// - /// The matching type - /// - public TlsaMatchingType MatchingType { get; private set; } - - /// - /// The certificate association data - /// - public byte[] CertificateAssociationData { get; private set; } - - internal TlsaRecord() {} - - /// - /// Creates a new instance of the TlsaRecord class - /// - /// Domain name of the host - /// Seconds the record should be cached at most - /// The certificate usage - /// The selector - /// The matching type - /// The certificate association data - public TlsaRecord(DomainName name, int timeToLive, TlsaCertificateUsage certificateUsage, TlsaSelector selector, TlsaMatchingType matchingType, byte[] certificateAssociationData) - : base(name, RecordType.Tlsa, RecordClass.INet, timeToLive) - { - CertificateUsage = certificateUsage; - Selector = selector; - MatchingType = matchingType; - CertificateAssociationData = certificateAssociationData ?? new byte[] { }; - } - - /// - /// Creates a new instance of the TlsaRecord class - /// - /// Domain name of the host - /// Seconds the record should be cached at most - /// The certificate usage - /// The selector - /// The matching type - /// The certificate to get the association data from - public TlsaRecord(DomainName name, int timeToLive, TlsaCertificateUsage certificateUsage, TlsaSelector selector, TlsaMatchingType matchingType, X509Certificate certificate) - : base(name, RecordType.Tlsa, RecordClass.INet, timeToLive) - { - CertificateUsage = certificateUsage; - Selector = selector; - MatchingType = matchingType; - CertificateAssociationData = GetCertificateAssocicationData(selector, matchingType, certificate); - } - - internal static byte[] GetCertificateAssocicationData(TlsaSelector selector, TlsaMatchingType matchingType, X509Certificate certificate) - { - byte[] selectedBytes; - switch (selector) - { - case TlsaSelector.FullCertificate: - selectedBytes = certificate.GetRawCertData(); - break; - - case TlsaSelector.SubjectPublicKeyInfo: - selectedBytes = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(DotNetUtilities.FromX509Certificate(certificate).GetPublicKey()).GetDerEncoded(); - break; - - default: - throw new NotSupportedException(); - } - - byte[] matchingBytes; - switch (matchingType) - { - case TlsaMatchingType.Full: - matchingBytes = selectedBytes; - break; - - case TlsaMatchingType.Sha256Hash: - Sha256Digest sha256Digest = new Sha256Digest(); - sha256Digest.BlockUpdate(selectedBytes, 0, selectedBytes.Length); - matchingBytes = new byte[sha256Digest.GetDigestSize()]; - sha256Digest.DoFinal(matchingBytes, 0); - break; - - case TlsaMatchingType.Sha512Hash: - Sha512Digest sha512Digest = new Sha512Digest(); - sha512Digest.BlockUpdate(selectedBytes, 0, selectedBytes.Length); - matchingBytes = new byte[sha512Digest.GetDigestSize()]; - sha512Digest.DoFinal(matchingBytes, 0); - break; - - default: - throw new NotSupportedException(); - } - - return matchingBytes; - } - - internal override void ParseRecordData(byte[] resultData, int startPosition, int length) - { - CertificateUsage = (TlsaCertificateUsage) resultData[startPosition++]; - Selector = (TlsaSelector) resultData[startPosition++]; - MatchingType = (TlsaMatchingType) resultData[startPosition++]; - CertificateAssociationData = DnsMessageBase.ParseByteData(resultData, ref startPosition, length - 3); - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length < 4) - throw new FormatException(); - - CertificateUsage = (TlsaCertificateUsage) Byte.Parse(stringRepresentation[0]); - Selector = (TlsaSelector) Byte.Parse(stringRepresentation[1]); - MatchingType = (TlsaMatchingType) Byte.Parse(stringRepresentation[2]); - CertificateAssociationData = String.Join(String.Empty, stringRepresentation.Skip(3)).FromBase16String(); - } - - internal override string RecordDataToString() - { - return (byte) CertificateUsage - + " " + (byte) Selector - + " " + (byte) MatchingType - + " " + String.Join(String.Empty, CertificateAssociationData.ToBase16String()); - } - - protected internal override int MaximumRecordDataLength => 3 + CertificateAssociationData.Length; - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - messageData[currentPosition++] = (byte) CertificateUsage; - messageData[currentPosition++] = (byte) Selector; - messageData[currentPosition++] = (byte) MatchingType; - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, CertificateAssociationData); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/UriRecord.cs b/ARSoft.Tools.Net/Dns/DnsRecord/UriRecord.cs deleted file mode 100644 index 971d162..0000000 --- a/ARSoft.Tools.Net/Dns/DnsRecord/UriRecord.cs +++ /dev/null @@ -1,100 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Uniform Resource Identifier - /// - /// Defined in - /// RFC 7553 - /// - /// - public class UriRecord : DnsRecordBase - { - /// - /// Priority - /// - public ushort Priority { get; private set; } - - /// - /// Weight - /// - public ushort Weight { get; private set; } - - /// - /// Target - /// - public string Target { get; private set; } - - internal UriRecord() {} - - /// - /// Creates a new instance of the MxRecord class - /// - /// Name of the zone - /// Seconds the record should be cached at most - /// Priority of the record - /// Weight of the record - /// Target of the record - public UriRecord(DomainName name, int timeToLive, ushort priority, ushort weight, string target) - : base(name, RecordType.Uri, RecordClass.INet, timeToLive) - { - Priority = priority; - Weight = weight; - Target = target ?? String.Empty; - } - - internal override void ParseRecordData(byte[] resultData, int startPosition, int length) - { - Priority = DnsMessageBase.ParseUShort(resultData, ref startPosition); - Weight = DnsMessageBase.ParseUShort(resultData, ref startPosition); - Target = DnsMessageBase.ParseText(resultData, ref startPosition, length - 4); - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length != 3) - throw new FormatException(); - - Priority = UInt16.Parse(stringRepresentation[0]); - Weight = UInt16.Parse(stringRepresentation[1]); - Target = stringRepresentation[2]; - } - - internal override string RecordDataToString() - { - return Priority + " " + Weight - + " \"" + Target + "\""; - } - - protected internal override int MaximumRecordDataLength => Target.Length + 4; - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, Priority); - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, Weight); - DnsMessageBase.EncodeTextWithoutLength(messageData, ref currentPosition, Target); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/WksRecord.cs b/ARSoft.Tools.Net/Dns/DnsRecord/WksRecord.cs deleted file mode 100644 index 8bf1a31..0000000 --- a/ARSoft.Tools.Net/Dns/DnsRecord/WksRecord.cs +++ /dev/null @@ -1,129 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Net.Sockets; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Well known services record - /// - /// Defined in - /// RFC 1035 - /// - /// - public class WksRecord : DnsRecordBase - { - /// - /// IP address of the host - /// - public IPAddress Address { get; private set; } - - /// - /// Type of the protocol - /// - public ProtocolType Protocol { get; private set; } - - /// - /// List of ports which are supported by the host - /// - public List Ports { get; private set; } - - internal WksRecord() {} - - /// - /// Creates a new instance of the WksRecord class - /// - /// Name of the host - /// Seconds the record should be cached at most - /// IP address of the host - /// Type of the protocol - /// List of ports which are supported by the host - public WksRecord(DomainName name, int timeToLive, IPAddress address, ProtocolType protocol, List ports) - : base(name, RecordType.Wks, RecordClass.INet, timeToLive) - { - Address = address ?? IPAddress.None; - Protocol = protocol; - Ports = ports ?? new List(); - } - - internal override void ParseRecordData(byte[] resultData, int currentPosition, int length) - { - int endPosition = currentPosition + length; - - Address = new IPAddress(DnsMessageBase.ParseByteData(resultData, ref currentPosition, 4)); - Protocol = (ProtocolType) resultData[currentPosition++]; - Ports = new List(); - - int octetNumber = 0; - while (currentPosition < endPosition) - { - byte octet = resultData[currentPosition++]; - - for (int bit = 0; bit < 8; bit++) - { - if ((octet & (1 << Math.Abs(bit - 7))) != 0) - { - Ports.Add((ushort) (octetNumber * 8 + bit)); - } - } - - octetNumber++; - } - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length < 2) - throw new FormatException(); - - Address = IPAddress.Parse(stringRepresentation[0]); - Ports = stringRepresentation.Skip(1).Select(UInt16.Parse).ToList(); - } - - internal override string RecordDataToString() - { - return Address - + " " + (byte) Protocol - + " " + String.Join(" ", Ports.Select(port => port.ToString())); - } - - protected internal override int MaximumRecordDataLength => 5 + Ports.Max() / 8 + 1; - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, Address.GetAddressBytes()); - messageData[currentPosition++] = (byte) Protocol; - - foreach (ushort port in Ports) - { - int octetPosition = port / 8 + currentPosition; - int bitPos = port % 8; - byte octet = messageData[octetPosition]; - octet |= (byte) (1 << Math.Abs(bitPos - 7)); - messageData[octetPosition] = octet; - } - currentPosition += Ports.Max() / 8 + 1; - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/X25Record.cs b/ARSoft.Tools.Net/Dns/DnsRecord/X25Record.cs deleted file mode 100644 index 0001cf2..0000000 --- a/ARSoft.Tools.Net/Dns/DnsRecord/X25Record.cs +++ /dev/null @@ -1,79 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// X.25 PSDN address record - /// - /// Defined in - /// RFC 1183 - /// - /// - public class X25Record : DnsRecordBase - { - /// - /// PSDN (Public Switched Data Network) address - /// - public string X25Address { get; protected set; } - - internal X25Record() {} - - /// - /// Creates a new instance of the X25Record class - /// - /// Name of the record - /// Seconds the record should be cached at most - /// PSDN (Public Switched Data Network) address - public X25Record(DomainName name, int timeToLive, string x25Address) - : base(name, RecordType.X25, RecordClass.INet, timeToLive) - { - X25Address = x25Address ?? String.Empty; - } - - internal override void ParseRecordData(byte[] resultData, int startPosition, int length) - { - X25Address += DnsMessageBase.ParseText(resultData, ref startPosition); - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length != 1) - throw new FormatException(); - - X25Address = stringRepresentation[0]; - } - - internal override string RecordDataToString() - { - return X25Address.ToMasterfileLabelRepresentation(); - } - - protected internal override int MaximumRecordDataLength => 1 + X25Address.Length; - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - DnsMessageBase.EncodeTextBlock(messageData, ref currentPosition, X25Address); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsSec/DiffieHellmanKeyRecord.cs b/ARSoft.Tools.Net/Dns/DnsSec/DiffieHellmanKeyRecord.cs deleted file mode 100644 index d8c7076..0000000 --- a/ARSoft.Tools.Net/Dns/DnsSec/DiffieHellmanKeyRecord.cs +++ /dev/null @@ -1,114 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Security Key record using Diffie Hellman algorithm - /// - /// Defined in - /// RFC 4034 - /// , - /// RFC 3755 - /// , - /// RFC 2535 - /// and - /// RFC 2930 - /// - /// - public class DiffieHellmanKeyRecord : KeyRecordBase - { - /// - /// Binary data of the prime of the key - /// - public byte[] Prime { get; private set; } - - /// - /// Binary data of the generator of the key - /// - public byte[] Generator { get; private set; } - - /// - /// Binary data of the public value - /// - public byte[] PublicValue { get; private set; } - - internal DiffieHellmanKeyRecord() {} - - /// - /// Creates a new instance of the DiffieHellmanKeyRecord class - /// - /// Name of the record - /// Class of the record - /// Seconds the record should be cached at most - /// Flags of the key - /// Protocol for which the key is used - /// Binary data of the prime of the key - /// Binary data of the generator of the key - /// Binary data of the public value - public DiffieHellmanKeyRecord(DomainName name, RecordClass recordClass, int timeToLive, ushort flags, ProtocolType protocol, byte[] prime, byte[] generator, byte[] publicValue) - : base(name, recordClass, timeToLive, flags, protocol, DnsSecAlgorithm.DiffieHellman) - { - Prime = prime ?? new byte[] { }; - Generator = generator ?? new byte[] { }; - PublicValue = publicValue ?? new byte[] { }; - } - - protected override void ParsePublicKey(byte[] resultData, int startPosition, int length) - { - int primeLength = DnsMessageBase.ParseUShort(resultData, ref startPosition); - Prime = DnsMessageBase.ParseByteData(resultData, ref startPosition, primeLength); - int generatorLength = DnsMessageBase.ParseUShort(resultData, ref startPosition); - Generator = DnsMessageBase.ParseByteData(resultData, ref startPosition, generatorLength); - int publicValueLength = DnsMessageBase.ParseUShort(resultData, ref startPosition); - PublicValue = DnsMessageBase.ParseByteData(resultData, ref startPosition, publicValueLength); - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - throw new NotSupportedException(); - } - - protected override string PublicKeyToString() - { - byte[] publicKey = new byte[MaximumPublicKeyLength]; - int currentPosition = 0; - - EncodePublicKey(publicKey, 0, ref currentPosition, null); - - return publicKey.ToBase64String(); - } - - protected override int MaximumPublicKeyLength => 3 + Prime.Length + Generator.Length + PublicValue.Length; - - protected override void EncodePublicKey(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames) - { - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, (ushort) Prime.Length); - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, Prime); - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, (ushort) Generator.Length); - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, Generator); - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, (ushort) PublicValue.Length); - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, PublicValue); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsSec/DlvRecord.cs b/ARSoft.Tools.Net/Dns/DnsSec/DlvRecord.cs deleted file mode 100644 index 00bf25f..0000000 --- a/ARSoft.Tools.Net/Dns/DnsSec/DlvRecord.cs +++ /dev/null @@ -1,113 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// DNSSEC lookaside validation - /// - /// Defined in - /// RFC 4431 - /// - /// - public class DlvRecord : DnsRecordBase - { - /// - /// Key tag - /// - public ushort KeyTag { get; private set; } - - /// - /// Algorithm used - /// - public DnsSecAlgorithm Algorithm { get; private set; } - - /// - /// Type of the digest - /// - public DnsSecDigestType DigestType { get; private set; } - - /// - /// Binary data of the digest - /// - public byte[] Digest { get; private set; } - - internal DlvRecord() {} - - /// - /// Creates a new instance of the DlvRecord class - /// - /// Name of the record - /// Class of the record - /// Seconds the record should be cached at most - /// Key tag - /// Algorithm used - /// Type of the digest - /// Binary data of the digest - public DlvRecord(DomainName name, RecordClass recordClass, int timeToLive, ushort keyTag, DnsSecAlgorithm algorithm, DnsSecDigestType digestType, byte[] digest) - : base(name, RecordType.Dlv, recordClass, timeToLive) - { - KeyTag = keyTag; - Algorithm = algorithm; - DigestType = digestType; - Digest = digest ?? new byte[] { }; - } - - internal override void ParseRecordData(byte[] resultData, int startPosition, int length) - { - KeyTag = DnsMessageBase.ParseUShort(resultData, ref startPosition); - Algorithm = (DnsSecAlgorithm) resultData[startPosition++]; - DigestType = (DnsSecDigestType) resultData[startPosition++]; - Digest = DnsMessageBase.ParseByteData(resultData, ref startPosition, length - 4); - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length < 4) - throw new FormatException(); - - KeyTag = UInt16.Parse(stringRepresentation[0]); - Algorithm = (DnsSecAlgorithm) Byte.Parse(stringRepresentation[1]); - DigestType = (DnsSecDigestType) Byte.Parse(stringRepresentation[2]); - Digest = String.Join(String.Empty, stringRepresentation.Skip(3)).FromBase16String(); - } - - internal override string RecordDataToString() - { - return KeyTag - + " " + (byte) Algorithm - + " " + (byte) DigestType - + " " + Digest.ToBase16String(); - } - - protected internal override int MaximumRecordDataLength => 4 + Digest.Length; - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, KeyTag); - messageData[currentPosition++] = (byte) Algorithm; - messageData[currentPosition++] = (byte) DigestType; - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, Digest); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsSec/DnsKeyFlags.cs b/ARSoft.Tools.Net/Dns/DnsSec/DnsKeyFlags.cs deleted file mode 100644 index ebb02e3..0000000 --- a/ARSoft.Tools.Net/Dns/DnsSec/DnsKeyFlags.cs +++ /dev/null @@ -1,57 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; - -namespace ARSoft.Tools.Net.Dns -{ - [Flags] - public enum DnsKeyFlags : ushort - { - /// - /// ZONE - /// - /// Defined in - /// RFC 3755 - /// and - /// RFC 4034 - /// - /// - Zone = 256, - - /// - /// REVOKE - /// - /// Defined in - /// RFC 5011 - /// - /// - Revoke = 128, - - /// - /// Secure Entry Point (SEP) - /// - /// Defined in - /// RFC 3755 - /// and - /// RFC 4034 - /// - /// - SecureEntryPoint = 1 - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsSec/DnsKeyRecord.cs b/ARSoft.Tools.Net/Dns/DnsSec/DnsKeyRecord.cs deleted file mode 100644 index ccd7c4e..0000000 --- a/ARSoft.Tools.Net/Dns/DnsSec/DnsKeyRecord.cs +++ /dev/null @@ -1,616 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Org.BouncyCastle.Asn1.CryptoPro; -using Org.BouncyCastle.Asn1.Nist; -using Org.BouncyCastle.Asn1.Sec; -using Org.BouncyCastle.Asn1.X9; -using Org.BouncyCastle.Crypto; -using Org.BouncyCastle.Crypto.Digests; -using Org.BouncyCastle.Crypto.Generators; -using Org.BouncyCastle.Crypto.Parameters; -using Org.BouncyCastle.Crypto.Prng; -using Org.BouncyCastle.Crypto.Signers; -using Org.BouncyCastle.Math; -using Org.BouncyCastle.Math.EC; -using Org.BouncyCastle.Pkcs; -using Org.BouncyCastle.Security; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// DNS Key record - /// - /// Defined in - /// RFC 4034 - /// and - /// RFC 3755 - /// - /// - public class DnsKeyRecord : DnsRecordBase - { - private static readonly SecureRandom _secureRandom = new SecureRandom(new CryptoApiRandomGenerator()); - - /// - /// Flags of the key - /// - public DnsKeyFlags Flags { get; private set; } - - /// - /// Protocol field - /// - public byte Protocol { get; private set; } - - /// - /// Algorithm of the key - /// - public DnsSecAlgorithm Algorithm { get; private set; } - - /// - /// Binary data of the public key - /// - public byte[] PublicKey { get; private set; } - - /// - /// Binary data of the private key - /// - public byte[] PrivateKey { get; } - - /// - /// Record holds a DNS zone key - /// - /// Defined in - /// RFC 4034 - /// and - /// RFC 3757 - /// - /// - public bool IsZoneKey - { - get { return (Flags & DnsKeyFlags.Zone) == DnsKeyFlags.Zone; } - set - { - if (value) - { - Flags |= DnsKeyFlags.Zone; - } - else - { - Flags &= ~DnsKeyFlags.Zone; - } - } - } - - /// - /// Key is intended for use as a secure entry point - /// - /// Defined in - /// RFC 4034 - /// and - /// RFC 3757 - /// - /// - public bool IsSecureEntryPoint - { - get { return (Flags & DnsKeyFlags.SecureEntryPoint) == DnsKeyFlags.SecureEntryPoint; } - set - { - if (value) - { - Flags |= DnsKeyFlags.SecureEntryPoint; - } - else - { - Flags &= ~DnsKeyFlags.SecureEntryPoint; - } - } - } - - /// - /// Key is intended for use as a secure entry point - /// - /// Defined in - /// RFC 5011 - /// - /// - public bool IsRevoked - { - get { return (Flags & DnsKeyFlags.Revoke) == DnsKeyFlags.Revoke; } - set - { - if (value) - { - Flags |= DnsKeyFlags.Revoke; - } - else - { - Flags &= ~DnsKeyFlags.Revoke; - } - } - } - - /// - /// Calculates the key tag - /// - /// Defined in - /// RFC 4034 - /// - /// - /// - public ushort CalculateKeyTag() - { - if (Algorithm == DnsSecAlgorithm.RsaMd5) - return (ushort) (PublicKey[PublicKey.Length - 4] & PublicKey[PublicKey.Length - 3] << 8); - - byte[] buffer = new byte[MaximumRecordDataLength]; - int currentPosition = 0; - EncodeRecordData(buffer, 0, ref currentPosition, null, false); - - ulong ac = 0; - - for (int i = 0; i < currentPosition; ++i) - { - ac += ((i & 1) == 1) ? buffer[i] : (ulong) buffer[i] << 8; - } - - ac += (ac >> 16) & 0xFFFF; - - ushort res = (ushort) (ac & 0xffff); - - return res; - } - - internal DnsKeyRecord() {} - - /// - /// Creates a new instance of the DnsKeyRecord class - /// - /// Name of the record - /// Class of the record - /// Seconds the record should be cached at most - /// Flags of the key - /// Protocol field - /// Algorithm of the key - /// Binary data of the public key - public DnsKeyRecord(DomainName name, RecordClass recordClass, int timeToLive, DnsKeyFlags flags, byte protocol, DnsSecAlgorithm algorithm, byte[] publicKey) - : this(name, recordClass, timeToLive, flags, protocol, algorithm, publicKey, null) {} - - /// - /// Creates a new instance of the DnsKeyRecord class - /// - /// Name of the record - /// Class of the record - /// Seconds the record should be cached at most - /// Flags of the key - /// Protocol field - /// Algorithm of the key - /// Binary data of the public key - /// Binary data of the private key - public DnsKeyRecord(DomainName name, RecordClass recordClass, int timeToLive, DnsKeyFlags flags, byte protocol, DnsSecAlgorithm algorithm, byte[] publicKey, byte[] privateKey) - : base(name, RecordType.DnsKey, recordClass, timeToLive) - { - Flags = flags; - Protocol = protocol; - Algorithm = algorithm; - PublicKey = publicKey; - PrivateKey = privateKey; - } - - internal override void ParseRecordData(byte[] resultData, int startPosition, int length) - { - Flags = (DnsKeyFlags) DnsMessageBase.ParseUShort(resultData, ref startPosition); - Protocol = resultData[startPosition++]; - Algorithm = (DnsSecAlgorithm) resultData[startPosition++]; - PublicKey = DnsMessageBase.ParseByteData(resultData, ref startPosition, length - 4); - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length < 4) - throw new FormatException(); - - Flags = (DnsKeyFlags) UInt16.Parse(stringRepresentation[0]); - Protocol = Byte.Parse(stringRepresentation[1]); - Algorithm = (DnsSecAlgorithm) Byte.Parse(stringRepresentation[2]); - PublicKey = String.Join(String.Empty, stringRepresentation.Skip(3)).FromBase64String(); - } - - internal override string RecordDataToString() - { - return (ushort) Flags - + " " + Protocol - + " " + (byte) Algorithm - + " " + PublicKey.ToBase64String(); - } - - protected internal override int MaximumRecordDataLength => 4 + PublicKey.Length; - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, (ushort) Flags); - messageData[currentPosition++] = Protocol; - messageData[currentPosition++] = (byte) Algorithm; - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, PublicKey); - } - - internal byte[] Sign(byte[] buffer, int length) - { - switch (Algorithm) - { - case DnsSecAlgorithm.RsaSha1: - case DnsSecAlgorithm.RsaSha1Nsec3Sha1: - return SignRsa(new Sha1Digest(), buffer, length); - - case DnsSecAlgorithm.RsaSha256: - return SignRsa(new Sha256Digest(), buffer, length); - - case DnsSecAlgorithm.RsaSha512: - return SignRsa(new Sha512Digest(), buffer, length); - - case DnsSecAlgorithm.Dsa: - case DnsSecAlgorithm.DsaNsec3Sha1: - return SignDsa(buffer, length); - - case DnsSecAlgorithm.EccGost: - return SignGost(buffer, length); - - case DnsSecAlgorithm.EcDsaP256Sha256: - return SignEcDsa(new Sha256Digest(), buffer, length); - - case DnsSecAlgorithm.EcDsaP384Sha384: - return SignEcDsa(new Sha384Digest(), buffer, length); - - default: - throw new NotSupportedException(); - } - } - - private byte[] SignRsa(IDigest digest, byte[] buffer, int length) - { - RsaDigestSigner signer = new RsaDigestSigner(digest); - - signer.Init(true, new ParametersWithRandom(PrivateKeyFactory.CreateKey(PrivateKey), _secureRandom)); - - signer.BlockUpdate(buffer, 0, length); - return signer.GenerateSignature(); - } - - private byte[] SignDsa(byte[] buffer, int length) - { - var signer = new DsaSigner(); - signer.Init(true, new ParametersWithRandom(PrivateKeyFactory.CreateKey(PrivateKey), _secureRandom)); - - var sha1 = new Sha1Digest(); - - sha1.BlockUpdate(buffer, 0, length); - byte[] hash = new byte[sha1.GetDigestSize()]; - sha1.DoFinal(hash, 0); - - var signature = signer.GenerateSignature(hash); - - byte[] res = new byte[41]; - - res[0] = PublicKey[0]; - - signature[0].ToByteArrayUnsigned().CopyTo(res, 1); - signature[1].ToByteArrayUnsigned().CopyTo(res, 21); - - return res; - } - - private byte[] SignGost(byte[] buffer, int length) - { - ECGost3410Signer signer = new ECGost3410Signer(); - signer.Init(true, new ParametersWithRandom(PrivateKeyFactory.CreateKey(PrivateKey), _secureRandom)); - - var digest = new Gost3411Digest(); - - digest.BlockUpdate(buffer, 0, length); - byte[] hash = new byte[digest.GetDigestSize()]; - digest.DoFinal(hash, 0); - - var signature = signer.GenerateSignature(hash); - - byte[] res = new byte[64]; - - signature[0].ToByteArrayUnsigned().CopyTo(res, 32); - signature[1].ToByteArrayUnsigned().CopyTo(res, 0); - - return res; - } - - private byte[] SignEcDsa(IDigest digest, byte[] buffer, int length) - { - int digestSize = digest.GetDigestSize(); - - ECDsaSigner signer = new ECDsaSigner(); - - signer.Init(true, new ParametersWithRandom(PrivateKeyFactory.CreateKey(PrivateKey), _secureRandom)); - - digest.BlockUpdate(buffer, 0, length); - byte[] hash = new byte[digest.GetDigestSize()]; - digest.DoFinal(hash, 0); - - var signature = signer.GenerateSignature(hash); - - byte[] res = new byte[digestSize * 2]; - - signature[0].ToByteArrayUnsigned().CopyTo(res, 0); - signature[1].ToByteArrayUnsigned().CopyTo(res, digestSize); - - return res; - } - - internal bool Verify(byte[] buffer, int length, byte[] signature) - { - switch (Algorithm) - { - case DnsSecAlgorithm.RsaSha1: - case DnsSecAlgorithm.RsaSha1Nsec3Sha1: - return VerifyRsa(new Sha1Digest(), buffer, length, signature); - - case DnsSecAlgorithm.RsaSha256: - return VerifyRsa(new Sha256Digest(), buffer, length, signature); - - case DnsSecAlgorithm.RsaSha512: - return VerifyRsa(new Sha512Digest(), buffer, length, signature); - - case DnsSecAlgorithm.Dsa: - case DnsSecAlgorithm.DsaNsec3Sha1: - return VerifyDsa(buffer, length, signature); - - case DnsSecAlgorithm.EccGost: - return VerifyGost(buffer, length, signature); - - case DnsSecAlgorithm.EcDsaP256Sha256: - return VerifyEcDsa(new Sha256Digest(), NistNamedCurves.GetByOid(SecObjectIdentifiers.SecP256r1), buffer, length, signature); - - case DnsSecAlgorithm.EcDsaP384Sha384: - return VerifyEcDsa(new Sha384Digest(), NistNamedCurves.GetByOid(SecObjectIdentifiers.SecP384r1), buffer, length, signature); - - default: - throw new NotSupportedException(); - } - } - - private bool VerifyRsa(IDigest digest, byte[] buffer, int length, byte[] signature) - { - RsaDigestSigner signer = new RsaDigestSigner(digest); - - int exponentOffset = 1; - int exponentLength = PublicKey[0] == 0 ? DnsMessageBase.ParseUShort(PublicKey, ref exponentOffset) : PublicKey[0]; - int moduloOffset = exponentOffset + exponentLength; - int moduloLength = PublicKey.Length - moduloOffset; - - RsaKeyParameters parameters = new RsaKeyParameters(false, new BigInteger(1, PublicKey, moduloOffset, moduloLength), new BigInteger(1, PublicKey, exponentOffset, exponentLength)); - - signer.Init(false, new ParametersWithRandom(parameters, _secureRandom)); - - signer.BlockUpdate(buffer, 0, length); - return signer.VerifySignature(signature); - } - - private bool VerifyDsa(byte[] buffer, int length, byte[] signature) - { - int numberSize = 64 + PublicKey[0] * 8; - - DsaPublicKeyParameters parameters = new DsaPublicKeyParameters( - new BigInteger(1, PublicKey, 21 + 2 * numberSize, numberSize), - new DsaParameters( - new BigInteger(1, PublicKey, 21, numberSize), - new BigInteger(1, PublicKey, 1, 20), - new BigInteger(1, PublicKey, 21 + numberSize, numberSize)) - ); - - var dsa = new DsaSigner(); - dsa.Init(false, parameters); - - var sha1 = new Sha1Digest(); - - sha1.BlockUpdate(buffer, 0, length); - byte[] hash = new byte[sha1.GetDigestSize()]; - sha1.DoFinal(hash, 0); - - return dsa.VerifySignature(hash, new BigInteger(1, signature, 1, 20), new BigInteger(1, signature, 21, 20)); - } - - private bool VerifyGost(byte[] buffer, int length, byte[] signature) - { - ECDomainParameters dParams = ECGost3410NamedCurves.GetByOid(CryptoProObjectIdentifiers.GostR3410x2001CryptoProA); - byte[] reversedPublicKey = PublicKey.Reverse().ToArray(); - ECPoint q = dParams.Curve.CreatePoint(new BigInteger(1, reversedPublicKey, 32, 32), new BigInteger(1, reversedPublicKey, 0, 32)); - ECPublicKeyParameters parameters = new ECPublicKeyParameters(q, dParams); - - var signer = new ECGost3410Signer(); - signer.Init(false, parameters); - - var digest = new Gost3411Digest(); - - digest.BlockUpdate(buffer, 0, length); - byte[] hash = new byte[digest.GetDigestSize()]; - digest.DoFinal(hash, 0); - - return signer.VerifySignature(hash, new BigInteger(1, signature, 32, 32), new BigInteger(1, signature, 0, 32)); - } - - private bool VerifyEcDsa(IDigest digest, X9ECParameters curveParameter, byte[] buffer, int length, byte[] signature) - { - int digestSize = digest.GetDigestSize(); - - ECDomainParameters dParams = new ECDomainParameters( - curveParameter.Curve, - curveParameter.G, - curveParameter.N, - curveParameter.H, - curveParameter.GetSeed()); - - ECPoint q = dParams.Curve.CreatePoint(new BigInteger(1, PublicKey, 0, digestSize), new BigInteger(1, PublicKey, digestSize, digestSize)); - - ECPublicKeyParameters parameters = new ECPublicKeyParameters(q, dParams); - - var signer = new ECDsaSigner(); - signer.Init(false, parameters); - - digest.BlockUpdate(buffer, 0, length); - byte[] hash = new byte[digest.GetDigestSize()]; - digest.DoFinal(hash, 0); - - return signer.VerifySignature(hash, new BigInteger(1, signature, 0, digestSize), new BigInteger(1, signature, digestSize, digestSize)); - } - - /// - /// Creates a new signing key pair - /// - /// The name of the key or zone - /// The record class of the DnsKeyRecord - /// The TTL in seconds to the DnsKeyRecord - /// The Flags of the DnsKeyRecord - /// The protocol version - /// The key algorithm - /// The key strength or 0 for default strength - /// - public static DnsKeyRecord CreateSigningKey(DomainName name, RecordClass recordClass, int timeToLive, DnsKeyFlags flags, byte protocol, DnsSecAlgorithm algorithm, int keyStrength = 0) - { - byte[] privateKey; - byte[] publicKey; - - switch (algorithm) - { - case DnsSecAlgorithm.RsaSha1: - case DnsSecAlgorithm.RsaSha1Nsec3Sha1: - case DnsSecAlgorithm.RsaSha256: - case DnsSecAlgorithm.RsaSha512: - if (keyStrength == 0) - keyStrength = (flags == (DnsKeyFlags.Zone | DnsKeyFlags.SecureEntryPoint)) ? 2048 : 1024; - - RsaKeyPairGenerator rsaKeyGen = new RsaKeyPairGenerator(); - rsaKeyGen.Init(new KeyGenerationParameters(_secureRandom, keyStrength)); - var rsaKey = rsaKeyGen.GenerateKeyPair(); - privateKey = PrivateKeyInfoFactory.CreatePrivateKeyInfo(rsaKey.Private).GetDerEncoded(); - var rsaPublicKey = (RsaKeyParameters) rsaKey.Public; - var rsaExponent = rsaPublicKey.Exponent.ToByteArrayUnsigned(); - var rsaModulus = rsaPublicKey.Modulus.ToByteArrayUnsigned(); - - int offset = 1; - if (rsaExponent.Length > 255) - { - publicKey = new byte[3 + rsaExponent.Length + rsaModulus.Length]; - DnsMessageBase.EncodeUShort(publicKey, ref offset, (ushort) publicKey.Length); - } - else - { - publicKey = new byte[1 + rsaExponent.Length + rsaModulus.Length]; - publicKey[0] = (byte) rsaExponent.Length; - } - DnsMessageBase.EncodeByteArray(publicKey, ref offset, rsaExponent); - DnsMessageBase.EncodeByteArray(publicKey, ref offset, rsaModulus); - break; - - case DnsSecAlgorithm.Dsa: - case DnsSecAlgorithm.DsaNsec3Sha1: - if (keyStrength == 0) - keyStrength = 1024; - - DsaParametersGenerator dsaParamsGen = new DsaParametersGenerator(); - dsaParamsGen.Init(keyStrength, 12, _secureRandom); - DsaKeyPairGenerator dsaKeyGen = new DsaKeyPairGenerator(); - dsaKeyGen.Init(new DsaKeyGenerationParameters(_secureRandom, dsaParamsGen.GenerateParameters())); - var dsaKey = dsaKeyGen.GenerateKeyPair(); - privateKey = PrivateKeyInfoFactory.CreatePrivateKeyInfo(dsaKey.Private).GetDerEncoded(); - var dsaPublicKey = (DsaPublicKeyParameters) dsaKey.Public; - - var dsaY = dsaPublicKey.Y.ToByteArrayUnsigned(); - var dsaP = dsaPublicKey.Parameters.P.ToByteArrayUnsigned(); - var dsaQ = dsaPublicKey.Parameters.Q.ToByteArrayUnsigned(); - var dsaG = dsaPublicKey.Parameters.G.ToByteArrayUnsigned(); - var dsaT = (byte) ((dsaY.Length - 64) / 8); - - publicKey = new byte[21 + 3 * dsaY.Length]; - publicKey[0] = dsaT; - dsaQ.CopyTo(publicKey, 1); - dsaP.CopyTo(publicKey, 21); - dsaG.CopyTo(publicKey, 21 + dsaY.Length); - dsaY.CopyTo(publicKey, 21 + 2 * dsaY.Length); - break; - - case DnsSecAlgorithm.EccGost: - ECDomainParameters gostEcDomainParameters = ECGost3410NamedCurves.GetByOid(CryptoProObjectIdentifiers.GostR3410x2001CryptoProA); - - var gostKeyGen = new ECKeyPairGenerator(); - gostKeyGen.Init(new ECKeyGenerationParameters(gostEcDomainParameters, _secureRandom)); - - var gostKey = gostKeyGen.GenerateKeyPair(); - privateKey = PrivateKeyInfoFactory.CreatePrivateKeyInfo(gostKey.Private).GetDerEncoded(); - var gostPublicKey = (ECPublicKeyParameters) gostKey.Public; - - publicKey = new byte[64]; - - gostPublicKey.Q.AffineXCoord.ToBigInteger().ToByteArrayUnsigned().CopyTo(publicKey, 32); - gostPublicKey.Q.AffineYCoord.ToBigInteger().ToByteArrayUnsigned().CopyTo(publicKey, 0); - - publicKey = publicKey.Reverse().ToArray(); - break; - - case DnsSecAlgorithm.EcDsaP256Sha256: - case DnsSecAlgorithm.EcDsaP384Sha384: - int ecDsaDigestSize; - X9ECParameters ecDsaCurveParameter; - - if (algorithm == DnsSecAlgorithm.EcDsaP256Sha256) - { - ecDsaDigestSize = new Sha256Digest().GetDigestSize(); - ecDsaCurveParameter = NistNamedCurves.GetByOid(SecObjectIdentifiers.SecP256r1); - } - else - { - ecDsaDigestSize = new Sha384Digest().GetDigestSize(); - ecDsaCurveParameter = NistNamedCurves.GetByOid(SecObjectIdentifiers.SecP384r1); - } - - ECDomainParameters ecDsaP384EcDomainParameters = new ECDomainParameters( - ecDsaCurveParameter.Curve, - ecDsaCurveParameter.G, - ecDsaCurveParameter.N, - ecDsaCurveParameter.H, - ecDsaCurveParameter.GetSeed()); - - var ecDsaKeyGen = new ECKeyPairGenerator(); - ecDsaKeyGen.Init(new ECKeyGenerationParameters(ecDsaP384EcDomainParameters, _secureRandom)); - - var ecDsaKey = ecDsaKeyGen.GenerateKeyPair(); - privateKey = PrivateKeyInfoFactory.CreatePrivateKeyInfo(ecDsaKey.Private).GetDerEncoded(); - var ecDsaPublicKey = (ECPublicKeyParameters) ecDsaKey.Public; - - publicKey = new byte[ecDsaDigestSize * 2]; - - ecDsaPublicKey.Q.AffineXCoord.ToBigInteger().ToByteArrayUnsigned().CopyTo(publicKey, 0); - ecDsaPublicKey.Q.AffineYCoord.ToBigInteger().ToByteArrayUnsigned().CopyTo(publicKey, ecDsaDigestSize); - break; - - default: - throw new NotSupportedException(); - } - - return new DnsKeyRecord(name, recordClass, timeToLive, flags, protocol, algorithm, publicKey, privateKey); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsSec/DnsSecAlgorithm.cs b/ARSoft.Tools.Net/Dns/DnsSec/DnsSecAlgorithm.cs deleted file mode 100644 index 5fb91c1..0000000 --- a/ARSoft.Tools.Net/Dns/DnsSec/DnsSecAlgorithm.cs +++ /dev/null @@ -1,250 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// DNSSEC algorithm type - /// - public enum DnsSecAlgorithm : byte - { - /// - /// RSA MD5 - /// - /// Defined in - /// RFC 3110 - /// and - /// RFC 4034 - /// - /// - RsaMd5 = 1, - - /// - /// Diffie Hellman - /// - /// Defined in - /// RFC 2539 - /// - /// - DiffieHellman = 2, - - /// - /// DSA/SHA-1 - /// - /// Defined in - /// RFC 3755 - /// and - /// RFC 4034 - /// - /// - Dsa = 3, - - /// - /// RSA/SHA-1 - /// - /// Defined in - /// RFC 3110 - /// and - /// RFC 4034 - /// - /// - RsaSha1 = 5, - - /// - /// DSA/SHA-1 using NSEC3 hashs - /// - /// Defined in - /// RFC 5155 - /// - /// - DsaNsec3Sha1 = 6, - - /// - /// RSA/SHA-1 using NSEC3 hashs - /// - /// Defined in - /// RFC 5155 - /// - /// - RsaSha1Nsec3Sha1 = 7, - - /// - /// RSA/SHA-256 - /// - /// Defined in - /// RFC 5702 - /// - /// - RsaSha256 = 8, - - /// - /// RSA/SHA-512 - /// - /// Defined in - /// RFC 5702 - /// - /// - RsaSha512 = 10, - - /// - /// GOST R 34.10-2001 - /// - /// Defined in - /// RFC 5933 - /// - /// - EccGost = 12, - - /// - /// ECDSA Curve P-256 with SHA-256 - /// - /// Defined in - /// RFC 6605 - /// - /// - EcDsaP256Sha256 = 13, - - /// - /// ECDSA Curve P-384 with SHA-384 - /// - /// Defined in - /// RFC 6605 - /// - /// - EcDsaP384Sha384 = 14, - - /// - /// Indirect - /// - /// Defined in - /// RFC 4034 - /// - /// - Indirect = 252, - - /// - /// Private key using named algorithm - /// - /// Defined in - /// RFC 4034 - /// - /// - PrivateDns = 253, - - /// - /// Private key using algorithm object identifier - /// - /// Defined in - /// RFC 4034 - /// - /// - PrivateOid = 254, - } - - internal static class DnsSecAlgorithmHelper - { - public static bool IsSupported(this DnsSecAlgorithm algorithm) - { - switch (algorithm) - { - case DnsSecAlgorithm.RsaSha1: - case DnsSecAlgorithm.Dsa: - case DnsSecAlgorithm.RsaSha1Nsec3Sha1: - case DnsSecAlgorithm.DsaNsec3Sha1: - case DnsSecAlgorithm.RsaSha256: - case DnsSecAlgorithm.RsaSha512: - case DnsSecAlgorithm.EccGost: - case DnsSecAlgorithm.EcDsaP256Sha256: - case DnsSecAlgorithm.EcDsaP384Sha384: - return true; - - default: - return false; - } - } - - public static int GetPriority(this DnsSecAlgorithm algorithm) - { - switch (algorithm) - { - case DnsSecAlgorithm.RsaSha1: - return 100; - case DnsSecAlgorithm.Dsa: - return 90; - case DnsSecAlgorithm.RsaSha1Nsec3Sha1: - return 100; - case DnsSecAlgorithm.DsaNsec3Sha1: - return 90; - case DnsSecAlgorithm.RsaSha256: - return 80; - case DnsSecAlgorithm.RsaSha512: - return 70; - case DnsSecAlgorithm.EccGost: - return 110; - case DnsSecAlgorithm.EcDsaP256Sha256: - return 60; - case DnsSecAlgorithm.EcDsaP384Sha384: - return 50; - - default: - throw new NotSupportedException(); - } - } - - public static bool IsCompatibleWithNSec(this DnsSecAlgorithm algorithm) - { - switch (algorithm) - { - case DnsSecAlgorithm.RsaSha1: - case DnsSecAlgorithm.Dsa: - case DnsSecAlgorithm.RsaSha256: - case DnsSecAlgorithm.RsaSha512: - case DnsSecAlgorithm.EccGost: - case DnsSecAlgorithm.EcDsaP256Sha256: - case DnsSecAlgorithm.EcDsaP384Sha384: - return true; - - default: - return false; - } - } - - public static bool IsCompatibleWithNSec3(this DnsSecAlgorithm algorithm) - { - switch (algorithm) - { - case DnsSecAlgorithm.RsaSha1Nsec3Sha1: - case DnsSecAlgorithm.DsaNsec3Sha1: - case DnsSecAlgorithm.RsaSha256: - case DnsSecAlgorithm.RsaSha512: - case DnsSecAlgorithm.EccGost: - case DnsSecAlgorithm.EcDsaP256Sha256: - case DnsSecAlgorithm.EcDsaP384Sha384: - return true; - - default: - return false; - } - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsSec/DnsSecDigestType.cs b/ARSoft.Tools.Net/Dns/DnsSec/DnsSecDigestType.cs deleted file mode 100644 index bd4c9fd..0000000 --- a/ARSoft.Tools.Net/Dns/DnsSec/DnsSecDigestType.cs +++ /dev/null @@ -1,67 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Type of DNSSEC digest - /// - public enum DnsSecDigestType : byte - { - /// - /// SHA-1 - /// - /// Defined in - /// RFC 3658 - /// - /// - Sha1 = 1, - - /// - /// SHA-256 - /// - /// Defined in - /// RFC 4509 - /// - /// - Sha256 = 2, - - /// - /// GOST R 34.11-94 - /// - /// Defined in - /// RFC 5933 - /// - /// - EccGost = 3, - - /// - /// SHA-384 - /// - /// Defined in - /// RFC 6605 - /// - /// - Sha384 = 4, - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsSec/DnsSecValidationException.cs b/ARSoft.Tools.Net/Dns/DnsSec/DnsSecValidationException.cs deleted file mode 100644 index 2ef71b2..0000000 --- a/ARSoft.Tools.Net/Dns/DnsSec/DnsSecValidationException.cs +++ /dev/null @@ -1,34 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// The exception that is thrown when a DNSSEC validation fails - /// - public class DnsSecValidationException : Exception - { - internal DnsSecValidationException(string message) - : base(message) {} - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsSec/DnsSecValidator.cs b/ARSoft.Tools.Net/Dns/DnsSec/DnsSecValidator.cs deleted file mode 100644 index 4b9fd28..0000000 --- a/ARSoft.Tools.Net/Dns/DnsSec/DnsSecValidator.cs +++ /dev/null @@ -1,275 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace ARSoft.Tools.Net.Dns -{ - internal class DnsSecValidator - { - private readonly IInternalDnsSecResolver _resolver; - private readonly IResolverHintStore _resolverHintStore; - - public DnsSecValidator(IInternalDnsSecResolver resolver, IResolverHintStore resolverHintStore) - { - _resolver = resolver; - _resolverHintStore = resolverHintStore; - } - - public async Task ValidateAsync(DomainName name, RecordType recordType, RecordClass recordClass, DnsMessage msg, List resultRecords, TState state, CancellationToken token) - where TRecord : DnsRecordBase - { - List rrSigRecords = msg - .AnswerRecords.OfType() - .Union(msg.AuthorityRecords.OfType()) - .Where(x => name.IsEqualOrSubDomainOf(x.SignersName) && (x.SignatureInception <= DateTime.Now) && (x.SignatureExpiration >= DateTime.Now)).ToList(); - - if (rrSigRecords.Count == 0) - { - return await ValidateOptOut(name, recordClass, state, token) ? DnsSecValidationResult.Unsigned : DnsSecValidationResult.Bogus; - } - - DomainName zoneApex = rrSigRecords.OrderByDescending(x => x.Labels).First().SignersName; - - if (resultRecords.Count != 0) - return await ValidateRrSigAsync(name, recordType, recordClass, resultRecords, rrSigRecords, zoneApex, msg, state, token); - - return await ValidateNonExistenceAsync(name, recordType, recordClass, rrSigRecords, DomainName.Asterisk + zoneApex, zoneApex, msg, state, token); - } - - private async Task ValidateOptOut(DomainName name, RecordClass recordClass, TState state, CancellationToken token) - { - while (name != DomainName.Root) - { - DnsMessage msg = await _resolver.ResolveMessageAsync(name, RecordType.Ds, recordClass, state, token); - - if ((msg == null) || ((msg.ReturnCode != ReturnCode.NoError) && (msg.ReturnCode != ReturnCode.NxDomain))) - { - throw new Exception("DNS request failed"); - } - - List rrSigRecords = msg - .AnswerRecords.OfType() - .Union(msg.AuthorityRecords.OfType()) - .Where(x => name.IsEqualOrSubDomainOf(x.SignersName) && (x.SignatureInception <= DateTime.Now) && (x.SignatureExpiration >= DateTime.Now)).ToList(); - - if (rrSigRecords.Count != 0) - { - DomainName zoneApex = rrSigRecords.OrderByDescending(x => x.Labels).First().SignersName; - - var nonExistenceValidation = await ValidateNonExistenceAsync(name, RecordType.Ds, recordClass, rrSigRecords, name, zoneApex, msg, state, token); - if ((nonExistenceValidation != DnsSecValidationResult.Bogus) && (nonExistenceValidation != DnsSecValidationResult.Indeterminate)) - return true; - } - - name = name.GetParentName(); - } - return false; - } - - private async Task ValidateNonExistenceAsync(DomainName name, RecordType recordType, RecordClass recordClass, List rrSigRecords, DomainName stop, DomainName zoneApex, DnsMessageBase msg, TState state, CancellationToken token) - { - var nsecRes = await ValidateNSecAsync(name, recordType, recordClass, rrSigRecords, stop, zoneApex, msg, state, token); - if (nsecRes == DnsSecValidationResult.Signed) - return nsecRes; - - var nsec3Res = await ValidateNSec3Async(name, recordType, recordClass, rrSigRecords, stop == DomainName.Asterisk + zoneApex, zoneApex, msg, state, token); - if (nsec3Res == DnsSecValidationResult.Signed) - return nsec3Res; - - if ((nsecRes == DnsSecValidationResult.Unsigned) || (nsec3Res == DnsSecValidationResult.Unsigned)) - return DnsSecValidationResult.Unsigned; - - if ((nsecRes == DnsSecValidationResult.Bogus) || (nsec3Res == DnsSecValidationResult.Bogus)) - return DnsSecValidationResult.Bogus; - - return DnsSecValidationResult.Indeterminate; - } - - private async Task ValidateNSecAsync(DomainName name, RecordType recordType, RecordClass recordClass, List rrSigRecords, DomainName stop, DomainName zoneApex, DnsMessageBase msg, TState state, CancellationToken token) - { - List nsecRecords = msg.AuthorityRecords.OfType().ToList(); - - if (nsecRecords.Count == 0) - return DnsSecValidationResult.Indeterminate; - - foreach (var nsecGroup in nsecRecords.GroupBy(x => x.Name)) - { - DnsSecValidationResult validationResult = await ValidateRrSigAsync(nsecGroup.Key, RecordType.NSec, recordClass, nsecGroup.ToList(), rrSigRecords, zoneApex, msg, state, token); - - if (validationResult != DnsSecValidationResult.Signed) - return validationResult; - } - - DomainName current = name; - - while (true) - { - if (current.Equals(stop)) - { - return DnsSecValidationResult.Signed; - } - - NSecRecord nsecRecord = nsecRecords.FirstOrDefault(x => x.Name.Equals(current)); - if (nsecRecord != null) - { - return nsecRecord.Types.Contains(recordType) ? DnsSecValidationResult.Bogus : DnsSecValidationResult.Signed; - } - else - { - nsecRecord = nsecRecords.FirstOrDefault(x => x.IsCovering(current, zoneApex)); - if (nsecRecord == null) - return DnsSecValidationResult.Bogus; - } - - current = DomainName.Asterisk + current.GetParentName(current.Labels[0] == "*" ? 2 : 1); - } - } - - private async Task ValidateNSec3Async(DomainName name, RecordType recordType, RecordClass recordClass, List rrSigRecords, bool checkWildcard, DomainName zoneApex, DnsMessageBase msg, TState state, CancellationToken token) - { - List nsecRecords = msg.AuthorityRecords.OfType().ToList(); - - if (nsecRecords.Count == 0) - return DnsSecValidationResult.Indeterminate; - - foreach (var nsecGroup in nsecRecords.GroupBy(x => x.Name)) - { - DnsSecValidationResult validationResult = await ValidateRrSigAsync(nsecGroup.Key, RecordType.NSec3, recordClass, nsecGroup.ToList(), rrSigRecords, zoneApex, msg, state, token); - - if (validationResult != DnsSecValidationResult.Signed) - return validationResult; - } - - var nsec3Parameter = nsecRecords.Where(x => x.Name.GetParentName().Equals(zoneApex)).Where(x => x.HashAlgorithm.IsSupported()).Select(x => new { x.HashAlgorithm, x.Iterations, x.Salt }).OrderBy(x => x.HashAlgorithm.GetPriority()).First(); - - DomainName hashedName = name.GetNsec3HashName(nsec3Parameter.HashAlgorithm, nsec3Parameter.Iterations, nsec3Parameter.Salt, zoneApex); - - if (recordType == RecordType.Ds && nsecRecords.Any(x => (x.Flags == 1) && (x.IsCovering(hashedName)))) - return DnsSecValidationResult.Unsigned; - - var directMatch = nsecRecords.FirstOrDefault(x => x.Name.Equals(hashedName)); - if (directMatch != null) - { - return directMatch.Types.Contains(recordType) ? DnsSecValidationResult.Bogus : DnsSecValidationResult.Signed; - } - - // find closest encloser - DomainName current = name; - DomainName previousHashedName = hashedName; - - while (true) - { - if (nsecRecords.Any(x => x.Name == hashedName)) - break; - - if (current == zoneApex) - return DnsSecValidationResult.Bogus; // closest encloser could not be found, but at least the zone apex must be found as - - current = current.GetParentName(); - previousHashedName = hashedName; - hashedName = current.GetNsec3HashName(nsec3Parameter.HashAlgorithm, nsec3Parameter.Iterations, nsec3Parameter.Salt, zoneApex); - } - - if (!nsecRecords.Any(x => x.IsCovering(previousHashedName))) - return DnsSecValidationResult.Bogus; - - if (checkWildcard) - { - DomainName wildcardHashName = (DomainName.Asterisk + current).GetNsec3HashName(nsec3Parameter.HashAlgorithm, nsec3Parameter.Iterations, nsec3Parameter.Salt, zoneApex); - - var wildcardDirectMatch = nsecRecords.FirstOrDefault(x => x.Name.Equals(wildcardHashName)); - if ((wildcardDirectMatch != null) && (!wildcardDirectMatch.Types.Contains(recordType))) - return wildcardDirectMatch.Types.Contains(recordType) ? DnsSecValidationResult.Bogus : DnsSecValidationResult.Signed; - - var wildcardCoveringMatch = nsecRecords.FirstOrDefault(x => x.IsCovering(wildcardHashName)); - return (wildcardCoveringMatch != null) ? DnsSecValidationResult.Signed : DnsSecValidationResult.Bogus; - } - else - { - return DnsSecValidationResult.Signed; - } - } - - private async Task ValidateRrSigAsync(DomainName name, RecordType recordType, RecordClass recordClass, List resultRecords, List rrSigRecords, DomainName zoneApex, DnsMessageBase msg, TState state, CancellationToken token) - where TRecord : DnsRecordBase - { - DnsSecValidationResult res = DnsSecValidationResult.Bogus; - - foreach (var record in rrSigRecords.Where(x => x.Name.Equals(name) && (x.TypeCovered == recordType))) - { - res = await VerifyAsync(record, resultRecords, recordClass, state, token); - if (res == DnsSecValidationResult.Signed) - { - if ((record.Labels == name.LabelCount) - || ((name.Labels[0] == "*") && (record.Labels == name.LabelCount - 1))) - return DnsSecValidationResult.Signed; - - if (await ValidateNonExistenceAsync(name, recordType, recordClass, rrSigRecords, DomainName.Asterisk + record.Name.GetParentName(record.Name.LabelCount - record.Labels), zoneApex, msg, state, token) == DnsSecValidationResult.Signed) - return DnsSecValidationResult.Signed; - } - } - - return res; - } - - private async Task VerifyAsync(RrSigRecord rrSigRecord, List coveredRecords, RecordClass recordClass, TState state, CancellationToken token) - where TRecord : DnsRecordBase - { - if (rrSigRecord.TypeCovered == RecordType.DnsKey) - { - List dsRecords; - - if (rrSigRecord.SignersName.Equals(DomainName.Root)) - { - dsRecords = _resolverHintStore.RootKeys; - } - else - { - var dsRecordResults = await _resolver.ResolveSecureAsync(rrSigRecord.SignersName, RecordType.Ds, recordClass, state, token); - - if ((dsRecordResults.ValidationResult == DnsSecValidationResult.Bogus) || (dsRecordResults.ValidationResult == DnsSecValidationResult.Indeterminate)) - throw new DnsSecValidationException("DS records could not be retrieved"); - - if (dsRecordResults.ValidationResult == DnsSecValidationResult.Unsigned) - return DnsSecValidationResult.Unsigned; - - dsRecords = dsRecordResults.Records; - } - - return dsRecords.Any(dsRecord => rrSigRecord.Verify(coveredRecords, coveredRecords.Cast().Where(dsRecord.IsCovering).ToList())) ? DnsSecValidationResult.Signed : DnsSecValidationResult.Bogus; - } - else - { - var dnsKeyRecordResults = await _resolver.ResolveSecureAsync(rrSigRecord.SignersName, RecordType.DnsKey, recordClass, state, token); - - if ((dnsKeyRecordResults.ValidationResult == DnsSecValidationResult.Bogus) || (dnsKeyRecordResults.ValidationResult == DnsSecValidationResult.Indeterminate)) - throw new DnsSecValidationException("DNSKEY records could not be retrieved"); - - if (dnsKeyRecordResults.ValidationResult == DnsSecValidationResult.Unsigned) - return DnsSecValidationResult.Unsigned; - - return rrSigRecord.Verify(coveredRecords, dnsKeyRecordResults.Records) ? DnsSecValidationResult.Signed : DnsSecValidationResult.Bogus; - } - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsSec/DsRecord.cs b/ARSoft.Tools.Net/Dns/DnsSec/DsRecord.cs deleted file mode 100644 index 8c1ae99..0000000 --- a/ARSoft.Tools.Net/Dns/DnsSec/DsRecord.cs +++ /dev/null @@ -1,186 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Org.BouncyCastle.Crypto; -using Org.BouncyCastle.Crypto.Digests; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Delegation signer - /// - /// Defined in - /// RFC 4034 - /// and - /// RFC 3658 - /// - /// - public class DsRecord : DnsRecordBase - { - /// - /// Key tag - /// - public ushort KeyTag { get; private set; } - - /// - /// Algorithm used - /// - public DnsSecAlgorithm Algorithm { get; private set; } - - /// - /// Type of the digest - /// - public DnsSecDigestType DigestType { get; private set; } - - /// - /// Binary data of the digest - /// - public byte[] Digest { get; private set; } - - internal DsRecord() {} - - /// - /// Creates a new instance of the DsRecord class - /// - /// Name of the record - /// Class of the record - /// Seconds the record should be cached at most - /// Key tag - /// Algorithm used - /// Type of the digest - /// Binary data of the digest - public DsRecord(DomainName name, RecordClass recordClass, int timeToLive, ushort keyTag, DnsSecAlgorithm algorithm, DnsSecDigestType digestType, byte[] digest) - : base(name, RecordType.Ds, recordClass, timeToLive) - { - KeyTag = keyTag; - Algorithm = algorithm; - DigestType = digestType; - Digest = digest ?? new byte[] { }; - } - - /// - /// Creates a new instance of the DsRecord class - /// - /// The key, that should be covered - /// Seconds the record should be cached at most - /// Type of the digest - public DsRecord(DnsKeyRecord key, int timeToLive, DnsSecDigestType digestType) - : base(key.Name, RecordType.Ds, key.RecordClass, timeToLive) - { - KeyTag = key.CalculateKeyTag(); - Algorithm = key.Algorithm; - DigestType = digestType; - Digest = CalculateKeyHash(key); - } - - internal override void ParseRecordData(byte[] resultData, int startPosition, int length) - { - KeyTag = DnsMessageBase.ParseUShort(resultData, ref startPosition); - Algorithm = (DnsSecAlgorithm) resultData[startPosition++]; - DigestType = (DnsSecDigestType) resultData[startPosition++]; - Digest = DnsMessageBase.ParseByteData(resultData, ref startPosition, length - 4); - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length < 4) - throw new FormatException(); - - KeyTag = UInt16.Parse(stringRepresentation[0]); - Algorithm = (DnsSecAlgorithm) Byte.Parse(stringRepresentation[1]); - DigestType = (DnsSecDigestType) Byte.Parse(stringRepresentation[2]); - Digest = String.Join(String.Empty, stringRepresentation.Skip(3)).FromBase16String(); - } - - internal override string RecordDataToString() - { - return KeyTag - + " " + (byte) Algorithm - + " " + (byte) DigestType - + " " + Digest.ToBase16String(); - } - - protected internal override int MaximumRecordDataLength => 4 + Digest.Length; - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, KeyTag); - messageData[currentPosition++] = (byte) Algorithm; - messageData[currentPosition++] = (byte) DigestType; - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, Digest); - } - - internal bool IsCovering(DnsKeyRecord dnsKeyRecord) - { - if (dnsKeyRecord.Algorithm != Algorithm) - return false; - - if (dnsKeyRecord.CalculateKeyTag() != KeyTag) - return false; - - byte[] hash = CalculateKeyHash(dnsKeyRecord); - - return StructuralComparisons.StructuralEqualityComparer.Equals(hash, Digest); - } - - private byte[] CalculateKeyHash(DnsKeyRecord dnsKeyRecord) - { - byte[] buffer = new byte[dnsKeyRecord.Name.MaximumRecordDataLength + 2 + dnsKeyRecord.MaximumRecordDataLength]; - - int currentPosition = 0; - - DnsMessageBase.EncodeDomainName(buffer, 0, ref currentPosition, dnsKeyRecord.Name, null, true); - dnsKeyRecord.EncodeRecordData(buffer, 0, ref currentPosition, null, true); - - var hashAlgorithm = GetHashAlgorithm(); - - hashAlgorithm.BlockUpdate(buffer, 0, currentPosition); - - byte[] hash = new byte[hashAlgorithm.GetDigestSize()]; - - hashAlgorithm.DoFinal(hash, 0); - return hash; - } - - private IDigest GetHashAlgorithm() - { - switch (DigestType) - { - case DnsSecDigestType.Sha1: - return new Sha1Digest(); - - case DnsSecDigestType.Sha256: - return new Sha256Digest(); - - case DnsSecDigestType.EccGost: - return new Gost3411Digest(); - - case DnsSecDigestType.Sha384: - return new Sha384Digest(); - - default: - throw new NotSupportedException(); - } - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsSec/IInternalDnsSecResolver.cs b/ARSoft.Tools.Net/Dns/DnsSec/IInternalDnsSecResolver.cs deleted file mode 100644 index 6f8d00a..0000000 --- a/ARSoft.Tools.Net/Dns/DnsSec/IInternalDnsSecResolver.cs +++ /dev/null @@ -1,35 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace ARSoft.Tools.Net.Dns -{ - internal interface IInternalDnsSecResolver - { - Task ResolveMessageAsync(DomainName name, RecordType recordType, RecordClass recordClass, TState state, CancellationToken token); - - Task> ResolveSecureAsync(DomainName name, RecordType recordType, RecordClass recordClass, TState state, CancellationToken token) - where TRecord : DnsRecordBase; - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsSec/KeyRecord.cs b/ARSoft.Tools.Net/Dns/DnsSec/KeyRecord.cs deleted file mode 100644 index a193580..0000000 --- a/ARSoft.Tools.Net/Dns/DnsSec/KeyRecord.cs +++ /dev/null @@ -1,89 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Security Key record - /// - /// Defined in - /// RFC 4034 - /// , - /// RFC 3755 - /// , - /// RFC 2535 - /// and - /// RFC 2930 - /// - /// - public class KeyRecord : KeyRecordBase - { - /// - /// Binary data of the public key - /// - public byte[] PublicKey { get; private set; } - - internal KeyRecord() {} - - /// - /// Creates of new instance of the KeyRecord class - /// - /// Name of the record - /// Class of the record - /// Seconds the record should be cached at most - /// Flags of the key - /// Protocol for which the key is used - /// Algorithm of the key - /// Binary data of the public key - public KeyRecord(DomainName name, RecordClass recordClass, int timeToLive, ushort flags, ProtocolType protocol, DnsSecAlgorithm algorithm, byte[] publicKey) - : base(name, recordClass, timeToLive, flags, protocol, algorithm) - { - PublicKey = publicKey ?? new byte[] { }; - } - - protected override void ParsePublicKey(byte[] resultData, int startPosition, int length) - { - PublicKey = DnsMessageBase.ParseByteData(resultData, ref startPosition, length); - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length < 1) - throw new FormatException(); - - PublicKey = String.Join(String.Empty, stringRepresentation).FromBase64String(); - } - - protected override string PublicKeyToString() - { - return PublicKey.ToBase64String(); - } - - protected override int MaximumPublicKeyLength => PublicKey.Length; - - protected override void EncodePublicKey(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames) - { - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, PublicKey); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsSec/KeyRecordBase.cs b/ARSoft.Tools.Net/Dns/DnsSec/KeyRecordBase.cs deleted file mode 100644 index 41d0cc8..0000000 --- a/ARSoft.Tools.Net/Dns/DnsSec/KeyRecordBase.cs +++ /dev/null @@ -1,358 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Security Key - /// - /// Defined in - /// RFC 4034 - /// , - /// RFC 3755 - /// , - /// RFC 2535 - /// and - /// RFC 2930 - /// - /// - public abstract class KeyRecordBase : DnsRecordBase - { - /// - /// Type of key - /// - public enum KeyTypeFlag : ushort - { - /// - /// Use of the key is prohibited for authentication - /// - /// Defined in - /// RFC 2535 - /// - /// - AuthenticationProhibited = 0x8000, - - /// - /// Use of the key is prohibited for confidentiality - /// - /// Defined in - /// RFC 2535 - /// - /// - ConfidentialityProhibited = 0x4000, - - /// - /// Use of the key for authentication and/or confidentiality is permitted - /// - /// Defined in - /// RFC 2535 - /// - /// - BothProhibited = 0x0000, - - /// - /// There is no key information - /// - /// Defined in - /// RFC 2535 - /// - /// - NoKey = 0xc000, - } - - /// - /// Type of name - /// - public enum NameTypeFlag : ushort - { - /// - /// Key is associated with a user or account - /// - /// Defined in - /// RFC 2535 - /// - /// - User = 0x0000, - - /// - /// Key is associated with a zone - /// - /// Defined in - /// RFC 2535 - /// - /// - Zone = 0x0100, - - /// - /// Key is associated with a host - /// - /// Defined in - /// RFC 2535 - /// - /// - Host = 0x0200, - - /// - /// Reserved - /// - /// Defined in - /// RFC 2535 - /// - /// - Reserved = 0x0300, - } - - /// - /// Protocol for which the key is used - /// - public enum ProtocolType : byte - { - /// - /// Use in connection with TLS - /// - /// Defined in - /// RFC 2535 - /// - /// - Tls = 1, - - /// - /// Use in connection with email - /// - /// Defined in - /// RFC 2535 - /// - /// - Email = 2, - - /// - /// Used for DNS security - /// - /// Defined in - /// RFC 2535 - /// - /// - DnsSec = 3, - - /// - /// Refer to the Oakley/IPSEC protocol - /// - /// Defined in - /// RFC 2535 - /// - /// - IpSec = 4, - - /// - /// Used in connection with any protocol - /// - /// Defined in - /// RFC 2535 - /// - /// - Any = 255, - } - - /// - /// Flags of the key - /// - public ushort Flags { get; private set; } - - /// - /// Protocol for which the key is used - /// - public ProtocolType Protocol { get; private set; } - - /// - /// Algorithm of the key - /// - public DnsSecAlgorithm Algorithm { get; private set; } - - #region Flags - /// - /// Type of key - /// - public KeyTypeFlag Type - { - get { return (KeyTypeFlag) (Flags & 0xc000); } - set - { - ushort clearedOp = (ushort) (Flags & 0x3fff); - Flags = (ushort) (clearedOp | (ushort) value); - } - } - - /// - /// True, if a second flag field should be added - /// - public bool IsExtendedFlag - { - get { return (Flags & 0x1000) != 0; } - set - { - if (value) - { - Flags |= 0x1000; - } - else - { - Flags &= 0xefff; - } - } - } - - /// - /// Type of name - /// - public NameTypeFlag NameType - { - get { return (NameTypeFlag) (Flags & 0x0300); } - set - { - ushort clearedOp = (ushort) (Flags & 0xfcff); - Flags = (ushort) (clearedOp | (ushort) value); - } - } - - /// - /// Is the key authorized for zone updates - /// - public bool IsZoneSignatory - { - get { return (Flags & 0x0008) != 0; } - set - { - if (value) - { - Flags |= 0x0008; - } - else - { - Flags &= 0xfff7; - } - } - } - - /// - /// Is the key authorized for updates of records signed with other key - /// - public bool IsStrongSignatory - { - get { return (Flags & 0x0004) != 0; } - set - { - if (value) - { - Flags |= 0x0004; - } - else - { - Flags &= 0xfffb; - } - } - } - - /// - /// Is the key only authorized for update of records with the same record name as the key - /// - public bool IsUniqueSignatory - { - get { return (Flags & 0x0002) != 0; } - set - { - if (value) - { - Flags |= 0x0002; - } - else - { - Flags &= 0xfffd; - } - } - } - - /// - /// Is the key an update key - /// - public bool IsGeneralSignatory - { - get { return (Flags & 0x0001) != 0; } - set - { - if (value) - { - Flags |= 0x0001; - } - else - { - Flags &= 0xfffe; - } - } - } - #endregion - - protected KeyRecordBase() {} - - protected KeyRecordBase(DomainName name, RecordClass recordClass, int timeToLive, ushort flags, ProtocolType protocol, DnsSecAlgorithm algorithm) - : base(name, RecordType.Key, recordClass, timeToLive) - { - Flags = flags; - Protocol = protocol; - Algorithm = algorithm; - } - - internal override sealed void ParseRecordData(byte[] resultData, int startPosition, int length) - { - Flags = DnsMessageBase.ParseUShort(resultData, ref startPosition); - Protocol = (ProtocolType) resultData[startPosition++]; - Algorithm = (DnsSecAlgorithm) resultData[startPosition++]; - ParsePublicKey(resultData, startPosition, length - 4); - } - - protected abstract void ParsePublicKey(byte[] resultData, int startPosition, int length); - - internal override sealed string RecordDataToString() - { - return Flags - + " " + (byte) Protocol - + " " + (byte) Algorithm - + " " + PublicKeyToString(); - } - - protected abstract string PublicKeyToString(); - - protected internal override sealed int MaximumRecordDataLength => 4 + MaximumPublicKeyLength; - - protected abstract int MaximumPublicKeyLength { get; } - - protected internal override sealed void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, Flags); - messageData[currentPosition++] = (byte) Protocol; - messageData[currentPosition++] = (byte) Algorithm; - EncodePublicKey(messageData, offset, ref currentPosition, domainNames); - } - - protected abstract void EncodePublicKey(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames); - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsSec/NSec3HashAlgorithm.cs b/ARSoft.Tools.Net/Dns/DnsSec/NSec3HashAlgorithm.cs deleted file mode 100644 index 2c9a61f..0000000 --- a/ARSoft.Tools.Net/Dns/DnsSec/NSec3HashAlgorithm.cs +++ /dev/null @@ -1,64 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// DNSSEC algorithm type - /// - public enum NSec3HashAlgorithm : byte - { - /// - /// RSA MD5 - /// - /// Defined in - /// RFC 5155 - /// - /// - Sha1 = 1, - } - - internal static class NSec3HashAlgorithmHelper - { - public static bool IsSupported(this NSec3HashAlgorithm algorithm) - { - switch (algorithm) - { - case NSec3HashAlgorithm.Sha1: - return true; - - default: - return false; - } - } - - public static int GetPriority(this NSec3HashAlgorithm algorithm) - { - switch (algorithm) - { - case NSec3HashAlgorithm.Sha1: - return 1; - - default: - throw new NotSupportedException(); - } - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsSec/NSec3ParamRecord.cs b/ARSoft.Tools.Net/Dns/DnsSec/NSec3ParamRecord.cs deleted file mode 100644 index 2e81812..0000000 --- a/ARSoft.Tools.Net/Dns/DnsSec/NSec3ParamRecord.cs +++ /dev/null @@ -1,115 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Hashed next owner parameter record - /// - /// Defined in - /// RFC 5155 - /// - /// - public class NSec3ParamRecord : DnsRecordBase - { - /// - /// Algorithm of the hash - /// - public NSec3HashAlgorithm HashAlgorithm { get; private set; } - - /// - /// Flags of the record - /// - public byte Flags { get; private set; } - - /// - /// Number of iterations - /// - public ushort Iterations { get; private set; } - - /// - /// Binary data of salt - /// - public byte[] Salt { get; private set; } - - internal NSec3ParamRecord() {} - - /// - /// Creates a new instance of the NSec3ParamRecord class - /// - /// Name of the record - /// Class of the record - /// Seconds the record should be cached at most - /// Algorithm of hash - /// Flags of the record - /// Number of iterations - /// Binary data of salt - public NSec3ParamRecord(DomainName name, RecordClass recordClass, int timeToLive, NSec3HashAlgorithm hashAlgorithm, byte flags, ushort iterations, byte[] salt) - : base(name, RecordType.NSec3Param, recordClass, timeToLive) - { - HashAlgorithm = hashAlgorithm; - Flags = flags; - Iterations = iterations; - Salt = salt ?? new byte[] { }; - } - - internal override void ParseRecordData(byte[] resultData, int currentPosition, int length) - { - HashAlgorithm = (NSec3HashAlgorithm) resultData[currentPosition++]; - Flags = resultData[currentPosition++]; - Iterations = DnsMessageBase.ParseUShort(resultData, ref currentPosition); - int saltLength = resultData[currentPosition++]; - Salt = DnsMessageBase.ParseByteData(resultData, ref currentPosition, saltLength); - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length != 4) - throw new FormatException(); - - HashAlgorithm = (NSec3HashAlgorithm) Byte.Parse(stringRepresentation[0]); - Flags = Byte.Parse(stringRepresentation[1]); - Iterations = UInt16.Parse(stringRepresentation[2]); - Salt = (stringRepresentation[3] == "-") ? new byte[] { } : stringRepresentation[3].FromBase16String(); - } - - internal override string RecordDataToString() - { - return (byte) HashAlgorithm - + " " + Flags - + " " + Iterations - + " " + ((Salt.Length == 0) ? "-" : Salt.ToBase16String()); - } - - protected internal override int MaximumRecordDataLength => 5 + Salt.Length; - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - messageData[currentPosition++] = (byte) HashAlgorithm; - messageData[currentPosition++] = Flags; - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, Iterations); - messageData[currentPosition++] = (byte) Salt.Length; - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, Salt); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsSec/NSecRecord.cs b/ARSoft.Tools.Net/Dns/DnsSec/NSecRecord.cs deleted file mode 100644 index 956c4f2..0000000 --- a/ARSoft.Tools.Net/Dns/DnsSec/NSecRecord.cs +++ /dev/null @@ -1,200 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Next owner - /// - /// Defined in - /// RFC 4034 - /// and - /// RFC 3755 - /// - /// - public class NSecRecord : DnsRecordBase - { - /// - /// Name of next owner - /// - public DomainName NextDomainName { get; internal set; } - - /// - /// Record types of the next owner - /// - public List Types { get; private set; } - - internal NSecRecord() {} - - /// - /// Creates a new instance of the NSecRecord class - /// - /// Name of the record - /// Class of the record - /// Seconds the record should be cached at most - /// Name of next owner - /// Record types of the next owner - public NSecRecord(DomainName name, RecordClass recordClass, int timeToLive, DomainName nextDomainName, List types) - : base(name, RecordType.NSec, recordClass, timeToLive) - { - NextDomainName = nextDomainName ?? DomainName.Root; - - if ((types == null) || (types.Count == 0)) - { - Types = new List(); - } - else - { - Types = types.Distinct().OrderBy(x => x).ToList(); - } - } - - internal override void ParseRecordData(byte[] resultData, int currentPosition, int length) - { - int endPosition = currentPosition + length; - - NextDomainName = DnsMessageBase.ParseDomainName(resultData, ref currentPosition); - - Types = ParseTypeBitMap(resultData, ref currentPosition, endPosition); - } - - internal static List ParseTypeBitMap(byte[] resultData, ref int currentPosition, int endPosition) - { - List types = new List(); - while (currentPosition < endPosition) - { - byte windowNumber = resultData[currentPosition++]; - byte windowLength = resultData[currentPosition++]; - - for (int i = 0; i < windowLength; i++) - { - byte bitmap = resultData[currentPosition++]; - - for (int bit = 0; bit < 8; bit++) - { - if ((bitmap & (1 << Math.Abs(bit - 7))) != 0) - { - types.Add((RecordType) (windowNumber * 256 + i * 8 + bit)); - } - } - } - } - return types; - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length < 2) - throw new FormatException(); - - NextDomainName = ParseDomainName(origin, stringRepresentation[0]); - Types = stringRepresentation.Skip(1).Select(RecordTypeHelper.ParseShortString).ToList(); - } - - internal override string RecordDataToString() - { - return NextDomainName - + " " + String.Join(" ", Types.Select(RecordTypeHelper.ToShortString)); - } - - protected internal override int MaximumRecordDataLength => 2 + NextDomainName.MaximumRecordDataLength + GetMaximumTypeBitmapLength(Types); - - internal static int GetMaximumTypeBitmapLength(List types) - { - int res = 0; - - int windowEnd = 255; - ushort lastType = 0; - - foreach (ushort type in types.Select(t => (ushort) t)) - { - if (type > windowEnd) - { - res += 3 + lastType % 256 / 8; - windowEnd = (type / 256 + 1) * 256 - 1; - } - - lastType = type; - } - - return res + 3 + lastType % 256 / 8; - } - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - DnsMessageBase.EncodeDomainName(messageData, offset, ref currentPosition, NextDomainName, null, useCanonical); - EncodeTypeBitmap(messageData, ref currentPosition, Types); - } - - internal static void EncodeTypeBitmap(byte[] messageData, ref int currentPosition, List types) - { - int windowEnd = 255; - byte[] windowData = new byte[32]; - int windowLength = 0; - - foreach (ushort type in types.Select(t => (ushort) t)) - { - if (type > windowEnd) - { - if (windowLength > 0) - { - messageData[currentPosition++] = (byte) (windowEnd / 256); - messageData[currentPosition++] = (byte) windowLength; - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, windowData, windowLength); - } - - windowEnd = (type / 256 + 1) * 256 - 1; - windowLength = 0; - } - - int typeLower = type % 256; - - int octetPos = typeLower / 8; - int bitPos = typeLower % 8; - - while (windowLength <= octetPos) - { - windowData[windowLength] = 0; - windowLength++; - } - - byte octet = windowData[octetPos]; - octet |= (byte) (1 << Math.Abs(bitPos - 7)); - windowData[octetPos] = octet; - } - - if (windowLength > 0) - { - messageData[currentPosition++] = (byte) (windowEnd / 256); - messageData[currentPosition++] = (byte) windowLength; - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, windowData, windowLength); - } - } - - internal bool IsCovering(DomainName name, DomainName zone) - { - return ((name.CompareTo(Name) > 0) && (name.CompareTo(NextDomainName) < 0)) // within zone - || ((name.CompareTo(Name) > 0) && NextDomainName.Equals(zone)); // behind zone - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsSec/Nsec3Record.cs b/ARSoft.Tools.Net/Dns/DnsSec/Nsec3Record.cs deleted file mode 100644 index 28d344e..0000000 --- a/ARSoft.Tools.Net/Dns/DnsSec/Nsec3Record.cs +++ /dev/null @@ -1,158 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Hashed next owner - /// - /// Defined in - /// RFC 5155 - /// - /// - public class NSec3Record : DnsRecordBase - { - /// - /// Algorithm of hash - /// - public NSec3HashAlgorithm HashAlgorithm { get; private set; } - - /// - /// Flags of the record - /// - public byte Flags { get; private set; } - - /// - /// Number of iterations - /// - public ushort Iterations { get; private set; } - - /// - /// Binary data of salt - /// - public byte[] Salt { get; private set; } - - /// - /// Binary data of hash of next owner - /// - public byte[] NextHashedOwnerName { get; internal set; } - - /// - /// Types of next owner - /// - public List Types { get; private set; } - - internal NSec3Record() {} - - /// - /// Creates of new instance of the NSec3Record class - /// - /// Name of the record - /// Class of the record - /// Seconds the record should be cached at most - /// Algorithm of hash - /// Flags of the record - /// Number of iterations - /// Binary data of salt - /// Binary data of hash of next owner - /// Types of next owner - public NSec3Record(DomainName name, RecordClass recordClass, int timeToLive, NSec3HashAlgorithm hashAlgorithm, byte flags, ushort iterations, byte[] salt, byte[] nextHashedOwnerName, List types) - : base(name, RecordType.NSec3, recordClass, timeToLive) - { - HashAlgorithm = hashAlgorithm; - Flags = flags; - Iterations = iterations; - Salt = salt ?? new byte[] { }; - NextHashedOwnerName = nextHashedOwnerName ?? new byte[] { }; - - if ((types == null) || (types.Count == 0)) - { - Types = new List(); - } - else - { - Types = types.Distinct().OrderBy(x => x).ToList(); - } - } - - internal override void ParseRecordData(byte[] resultData, int currentPosition, int length) - { - int endPosition = currentPosition + length; - - HashAlgorithm = (NSec3HashAlgorithm) resultData[currentPosition++]; - Flags = resultData[currentPosition++]; - Iterations = DnsMessageBase.ParseUShort(resultData, ref currentPosition); - int saltLength = resultData[currentPosition++]; - Salt = DnsMessageBase.ParseByteData(resultData, ref currentPosition, saltLength); - int hashLength = resultData[currentPosition++]; - NextHashedOwnerName = DnsMessageBase.ParseByteData(resultData, ref currentPosition, hashLength); - Types = NSecRecord.ParseTypeBitMap(resultData, ref currentPosition, endPosition); - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length < 5) - throw new FormatException(); - - HashAlgorithm = (NSec3HashAlgorithm) Byte.Parse(stringRepresentation[0]); - Flags = Byte.Parse(stringRepresentation[1]); - Iterations = UInt16.Parse(stringRepresentation[2]); - Salt = (stringRepresentation[3] == "-") ? new byte[] { } : stringRepresentation[3].FromBase16String(); - NextHashedOwnerName = stringRepresentation[4].FromBase32HexString(); - Types = stringRepresentation.Skip(5).Select(RecordTypeHelper.ParseShortString).ToList(); - } - - internal override string RecordDataToString() - { - return (byte) HashAlgorithm - + " " + Flags - + " " + Iterations - + " " + ((Salt.Length == 0) ? "-" : Salt.ToBase16String()) - + " " + NextHashedOwnerName.ToBase32HexString() - + " " + String.Join(" ", Types.Select(RecordTypeHelper.ToShortString)); - } - - protected internal override int MaximumRecordDataLength => 6 + Salt.Length + NextHashedOwnerName.Length + NSecRecord.GetMaximumTypeBitmapLength(Types); - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - messageData[currentPosition++] = (byte) HashAlgorithm; - messageData[currentPosition++] = Flags; - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, Iterations); - messageData[currentPosition++] = (byte) Salt.Length; - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, Salt); - messageData[currentPosition++] = (byte) NextHashedOwnerName.Length; - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, NextHashedOwnerName); - - if (Types.Count > 0) - NSecRecord.EncodeTypeBitmap(messageData, ref currentPosition, Types); - } - - internal bool IsCovering(DomainName name) - { - DomainName nextDomainName = new DomainName(NextHashedOwnerName.ToBase32HexString(), name.GetParentName()); - - return ((name.CompareTo(Name) > 0) && (name.CompareTo(nextDomainName) < 0)); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsSec/RrSigRecord.cs b/ARSoft.Tools.Net/Dns/DnsSec/RrSigRecord.cs deleted file mode 100644 index f0d8b76..0000000 --- a/ARSoft.Tools.Net/Dns/DnsSec/RrSigRecord.cs +++ /dev/null @@ -1,257 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Record signature record - /// - /// Defined in - /// RFC 4034 - /// and - /// RFC 3755 - /// - /// - public class RrSigRecord : DnsRecordBase - { - /// - /// Record type that is covered by this record - /// - public RecordType TypeCovered { get; private set; } - - /// - /// Algorithm that is used for signature - /// - public DnsSecAlgorithm Algorithm { get; private set; } - - /// - /// Label count of original record that is covered by this record - /// - public byte Labels { get; private set; } - - /// - /// Original time to live value of original record that is covered by this record - /// - public int OriginalTimeToLive { get; private set; } - - /// - /// Signature is valid until this date - /// - public DateTime SignatureExpiration { get; private set; } - - /// - /// Signature is valid from this date - /// - public DateTime SignatureInception { get; private set; } - - /// - /// Key tag - /// - public ushort KeyTag { get; private set; } - - /// - /// Domain name of generator of the signature - /// - public DomainName SignersName { get; private set; } - - /// - /// Binary data of the signature - /// - public byte[] Signature { get; internal set; } - - internal RrSigRecord() {} - - /// - /// Creates a new instance of the RrSigRecord class - /// - /// Name of the record - /// Class of the record - /// Seconds the record should be cached at most - /// - /// Record type that is covered by this record - /// - /// - /// Algorithm that is used for signature - /// - /// Label count of original record that is covered by this record - /// Original time to live value of original record that is covered by this record - /// Signature is valid until this date - /// Signature is valid from this date - /// Key tag - /// Domain name of generator of the signature - /// Binary data of the signature - public RrSigRecord(DomainName name, RecordClass recordClass, int timeToLive, RecordType typeCovered, DnsSecAlgorithm algorithm, byte labels, int originalTimeToLive, DateTime signatureExpiration, DateTime signatureInception, ushort keyTag, DomainName signersName, byte[] signature) - : base(name, RecordType.RrSig, recordClass, timeToLive) - { - TypeCovered = typeCovered; - Algorithm = algorithm; - Labels = labels; - OriginalTimeToLive = originalTimeToLive; - SignatureExpiration = signatureExpiration; - SignatureInception = signatureInception; - KeyTag = keyTag; - SignersName = signersName ?? DomainName.Root; - Signature = signature ?? new byte[] { }; - } - - internal RrSigRecord(List records, DnsKeyRecord key, DateTime inception, DateTime expiration) - : base(records[0].Name, RecordType.RrSig, records[0].RecordClass, records[0].TimeToLive) - { - TypeCovered = records[0].RecordType; - Algorithm = key.Algorithm; - Labels = (byte) (records[0].Name.Labels[0] == DomainName.Asterisk.Labels[0] ? records[0].Name.LabelCount - 1 : records[0].Name.LabelCount); - OriginalTimeToLive = records[0].TimeToLive; - SignatureExpiration = expiration; - SignatureInception = inception; - KeyTag = key.CalculateKeyTag(); - SignersName = key.Name; - Signature = new byte[] { }; - - byte[] signBuffer; - int signBufferLength; - EncodeSigningBuffer(records, out signBuffer, out signBufferLength); - - Signature = key.Sign(signBuffer, signBufferLength); - } - - internal override void ParseRecordData(byte[] resultData, int startPosition, int length) - { - int currentPosition = startPosition; - - TypeCovered = (RecordType) DnsMessageBase.ParseUShort(resultData, ref currentPosition); - Algorithm = (DnsSecAlgorithm) resultData[currentPosition++]; - Labels = resultData[currentPosition++]; - OriginalTimeToLive = DnsMessageBase.ParseInt(resultData, ref currentPosition); - SignatureExpiration = ParseDateTime(resultData, ref currentPosition); - SignatureInception = ParseDateTime(resultData, ref currentPosition); - KeyTag = DnsMessageBase.ParseUShort(resultData, ref currentPosition); - SignersName = DnsMessageBase.ParseDomainName(resultData, ref currentPosition); - Signature = DnsMessageBase.ParseByteData(resultData, ref currentPosition, length + startPosition - currentPosition); - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length < 9) - throw new FormatException(); - - TypeCovered = RecordTypeHelper.ParseShortString(stringRepresentation[0]); - Algorithm = (DnsSecAlgorithm) Byte.Parse(stringRepresentation[1]); - Labels = Byte.Parse(stringRepresentation[2]); - OriginalTimeToLive = Int32.Parse(stringRepresentation[3]); - SignatureExpiration = DateTime.ParseExact(stringRepresentation[4], "yyyyMMddHHmmss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal); - SignatureInception = DateTime.ParseExact(stringRepresentation[5], "yyyyMMddHHmmss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal); - KeyTag = UInt16.Parse(stringRepresentation[6]); - SignersName = ParseDomainName(origin, stringRepresentation[7]); - Signature = String.Join(String.Empty, stringRepresentation.Skip(8)).FromBase64String(); - } - - internal override string RecordDataToString() - { - return TypeCovered.ToShortString() - + " " + (byte) Algorithm - + " " + Labels - + " " + OriginalTimeToLive - + " " + SignatureExpiration.ToUniversalTime().ToString("yyyyMMddHHmmss") - + " " + SignatureInception.ToUniversalTime().ToString("yyyyMMddHHmmss") - + " " + KeyTag - + " " + SignersName - + " " + Signature.ToBase64String(); - } - - protected internal override int MaximumRecordDataLength => 20 + SignersName.MaximumRecordDataLength + Signature.Length; - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - EncodeRecordData(messageData, offset, ref currentPosition, domainNames, useCanonical, true); - } - - internal void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical, bool encodeSignature) - { - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, (ushort) TypeCovered); - messageData[currentPosition++] = (byte) Algorithm; - messageData[currentPosition++] = Labels; - DnsMessageBase.EncodeInt(messageData, ref currentPosition, OriginalTimeToLive); - EncodeDateTime(messageData, ref currentPosition, SignatureExpiration); - EncodeDateTime(messageData, ref currentPosition, SignatureInception); - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, KeyTag); - DnsMessageBase.EncodeDomainName(messageData, offset, ref currentPosition, SignersName, null, useCanonical); - - if (encodeSignature) - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, Signature); - } - - internal static void EncodeDateTime(byte[] buffer, ref int currentPosition, DateTime value) - { - int timeStamp = (int) (value.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds; - DnsMessageBase.EncodeInt(buffer, ref currentPosition, timeStamp); - } - - private static DateTime ParseDateTime(byte[] buffer, ref int currentPosition) - { - int timeStamp = DnsMessageBase.ParseInt(buffer, ref currentPosition); - return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(timeStamp).ToLocalTime(); - } - - internal bool Verify(List coveredRecords, IEnumerable dnsKeys) - where T : DnsRecordBase - { - byte[] messageData; - int length; - - EncodeSigningBuffer(coveredRecords, out messageData, out length); - - return dnsKeys - .Where(x => x.IsZoneKey && (x.Protocol == 3) && x.Algorithm.IsSupported() && (KeyTag == x.CalculateKeyTag())) - .Any(x => x.Verify(messageData, length, Signature)); - } - - private void EncodeSigningBuffer(List records, out byte[] messageData, out int length) - where T : DnsRecordBase - { - messageData = new byte[2 + MaximumRecordDataLength - Signature.Length + records.Sum(x => x.MaximumLength)]; - length = 0; - EncodeRecordData(messageData, 0, ref length, null, true, false); - foreach (var record in records.OrderBy(x => x)) - { - if (record.Name.LabelCount == Labels) - { - DnsMessageBase.EncodeDomainName(messageData, 0, ref length, record.Name, null, true); - } - else if (record.Name.LabelCount > Labels) - { - DnsMessageBase.EncodeDomainName(messageData, 0, ref length, DomainName.Asterisk + record.Name.GetParentName(record.Name.LabelCount - Labels), null, true); - } - else - { - throw new Exception("Encoding of records with less labels than RrSigRecord is not allowed"); - } - DnsMessageBase.EncodeUShort(messageData, ref length, (ushort) record.RecordType); - DnsMessageBase.EncodeUShort(messageData, ref length, (ushort) record.RecordClass); - DnsMessageBase.EncodeInt(messageData, ref length, OriginalTimeToLive); - - record.EncodeRecordBody(messageData, 0, ref length, null, true); - } - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsSec/SigRecord.cs b/ARSoft.Tools.Net/Dns/DnsSec/SigRecord.cs deleted file mode 100644 index fe984e4..0000000 --- a/ARSoft.Tools.Net/Dns/DnsSec/SigRecord.cs +++ /dev/null @@ -1,193 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Security signature record - /// - /// Defined in - /// RFC 4034 - /// , - /// RFC 3755 - /// , - /// RFC 2535 - /// and - /// RFC 2931 - /// - /// - public class SigRecord : DnsRecordBase - { - /// - /// Record type that is covered by this record - /// - public RecordType TypeCovered { get; private set; } - - /// - /// Algorithm that is used for signature - /// - public DnsSecAlgorithm Algorithm { get; private set; } - - /// - /// Label count of original record that is covered by this record - /// - public byte Labels { get; private set; } - - /// - /// Original time to live value of original record that is covered by this record - /// - public int OriginalTimeToLive { get; private set; } - - /// - /// Signature is valid until this date - /// - public DateTime SignatureExpiration { get; private set; } - - /// - /// Signature is valid from this date - /// - public DateTime SignatureInception { get; private set; } - - /// - /// Key tag - /// - public ushort KeyTag { get; private set; } - - /// - /// Domain name of generator of the signature - /// - public DomainName SignersName { get; private set; } - - /// - /// Binary data of the signature - /// - public byte[] Signature { get; private set; } - - internal SigRecord() {} - - /// - /// Creates a new instance of the SigRecord class - /// - /// Name of the record - /// Class of the record - /// Seconds the record should be cached at most - /// - /// Record type that is covered by this record - /// - /// - /// Algorithm that is used for signature - /// - /// Label count of original record that is covered by this record - /// Original time to live value of original record that is covered by this record - /// Signature is valid until this date - /// Signature is valid from this date - /// Key tag - /// Domain name of generator of the signature - /// Binary data of the signature - public SigRecord(DomainName name, RecordClass recordClass, int timeToLive, RecordType typeCovered, DnsSecAlgorithm algorithm, byte labels, int originalTimeToLive, DateTime signatureExpiration, DateTime signatureInception, ushort keyTag, DomainName signersName, byte[] signature) - : base(name, RecordType.Sig, recordClass, timeToLive) - { - TypeCovered = typeCovered; - Algorithm = algorithm; - Labels = labels; - OriginalTimeToLive = originalTimeToLive; - SignatureExpiration = signatureExpiration; - SignatureInception = signatureInception; - KeyTag = keyTag; - SignersName = signersName ?? DomainName.Root; - Signature = signature ?? new byte[] { }; - } - - internal override void ParseRecordData(byte[] resultData, int startPosition, int length) - { - int currentPosition = startPosition; - - TypeCovered = (RecordType) DnsMessageBase.ParseUShort(resultData, ref currentPosition); - Algorithm = (DnsSecAlgorithm) resultData[currentPosition++]; - Labels = resultData[currentPosition++]; - OriginalTimeToLive = DnsMessageBase.ParseInt(resultData, ref currentPosition); - SignatureExpiration = ParseDateTime(resultData, ref currentPosition); - SignatureInception = ParseDateTime(resultData, ref currentPosition); - KeyTag = DnsMessageBase.ParseUShort(resultData, ref currentPosition); - SignersName = DnsMessageBase.ParseDomainName(resultData, ref currentPosition); - Signature = DnsMessageBase.ParseByteData(resultData, ref currentPosition, length + startPosition - currentPosition); - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - if (stringRepresentation.Length < 9) - throw new FormatException(); - - TypeCovered = RecordTypeHelper.ParseShortString(stringRepresentation[0]); - Algorithm = (DnsSecAlgorithm) Byte.Parse(stringRepresentation[1]); - Labels = Byte.Parse(stringRepresentation[2]); - OriginalTimeToLive = Int32.Parse(stringRepresentation[3]); - SignatureExpiration = DateTime.ParseExact(stringRepresentation[4], "yyyyMMddHHmmss", CultureInfo.InvariantCulture); - SignatureInception = DateTime.ParseExact(stringRepresentation[5], "yyyyMMddHHmmss", CultureInfo.InvariantCulture); - KeyTag = UInt16.Parse(stringRepresentation[6]); - SignersName = ParseDomainName(origin, stringRepresentation[7]); - Signature = String.Join(String.Empty, stringRepresentation.Skip(8)).FromBase64String(); - } - - internal override string RecordDataToString() - { - return TypeCovered.ToShortString() - + " " + (byte) Algorithm - + " " + Labels - + " " + OriginalTimeToLive - + " " + SignatureExpiration.ToString("yyyyMMddHHmmss") - + " " + SignatureInception.ToString("yyyyMMddHHmmss") - + " " + KeyTag - + " " + SignersName - + " " + Signature.ToBase64String(); - } - - protected internal override int MaximumRecordDataLength => 20 + SignersName.MaximumRecordDataLength + Signature.Length; - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, (ushort) TypeCovered); - messageData[currentPosition++] = (byte) Algorithm; - messageData[currentPosition++] = Labels; - DnsMessageBase.EncodeInt(messageData, ref currentPosition, OriginalTimeToLive); - EncodeDateTime(messageData, ref currentPosition, SignatureExpiration); - EncodeDateTime(messageData, ref currentPosition, SignatureInception); - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, KeyTag); - DnsMessageBase.EncodeDomainName(messageData, offset, ref currentPosition, SignersName, null, useCanonical); - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, Signature); - } - - internal static void EncodeDateTime(byte[] buffer, ref int currentPosition, DateTime value) - { - int timeStamp = (int) (value.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds; - DnsMessageBase.EncodeInt(buffer, ref currentPosition, timeStamp); - } - - private static DateTime ParseDateTime(byte[] buffer, ref int currentPosition) - { - int timeStamp = DnsMessageBase.ParseInt(buffer, ref currentPosition); - return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(timeStamp).ToLocalTime(); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsServer.cs b/ARSoft.Tools.Net/Dns/DnsServer.cs index 334d8e5..2999a69 100644 --- a/ARSoft.Tools.Net/Dns/DnsServer.cs +++ b/ARSoft.Tools.Net/Dns/DnsServer.cs @@ -33,14 +33,6 @@ namespace ARSoft.Tools.Net.Dns /// public class DnsServer : IDisposable { - /// - /// Represents the method, that will be called to get the keydata for processing a tsig signed message - /// - /// The algorithm which is used in the message - /// The keyname which is used in the message - /// Binary representation of the key - public delegate byte[] SelectTsigKey(TSigAlgorithm algorithm, DomainName keyName); - private const int _DNS_PORT = 53; private readonly object _listenerLock = new object(); @@ -57,11 +49,6 @@ public class DnsServer : IDisposable private int _availableTcpListener; private bool _hasActiveTcpListener; - /// - /// Method that will be called to get the keydata for processing a tsig signed message - /// - public SelectTsigKey TsigKeySelector; - /// /// Gets or sets the timeout for sending and receiving data /// @@ -144,39 +131,6 @@ public void Stop() private async Task ProcessMessageAsync(DnsMessageBase query, ProtocolType protocolType, IPEndPoint remoteEndpoint) { - if (query.TSigOptions != null) - { - switch (query.TSigOptions.ValidationResult) - { - case ReturnCode.BadKey: - case ReturnCode.BadSig: - query.IsQuery = false; - query.ReturnCode = ReturnCode.NotAuthoritive; - query.TSigOptions.Error = query.TSigOptions.ValidationResult; - query.TSigOptions.KeyData = null; - -#pragma warning disable 4014 - InvalidSignedMessageReceived.RaiseAsync(this, new InvalidSignedMessageEventArgs(query, protocolType, remoteEndpoint)); -#pragma warning restore 4014 - - return query; - - case ReturnCode.BadTime: - query.IsQuery = false; - query.ReturnCode = ReturnCode.NotAuthoritive; - query.TSigOptions.Error = query.TSigOptions.ValidationResult; - query.TSigOptions.OtherData = new byte[6]; - int tmp = 0; - TSigRecord.EncodeDateTime(query.TSigOptions.OtherData, ref tmp, DateTime.Now); - -#pragma warning disable 4014 - InvalidSignedMessageReceived.RaiseAsync(this, new InvalidSignedMessageEventArgs(query, protocolType, remoteEndpoint)); -#pragma warning restore 4014 - - return query; - } - } - QueryReceivedEventArgs eventArgs = new QueryReceivedEventArgs(query, protocolType, remoteEndpoint); await QueryReceived.RaiseAsync(this, eventArgs); return eventArgs.Response; @@ -230,11 +184,9 @@ private async void HandleUdpListenerAsync() byte[] buffer = receiveResult.Buffer; DnsMessageBase query; - byte[] originalMac; try { - query = DnsMessageBase.CreateByFlag(buffer, TsigKeySelector, null); - originalMac = query.TSigOptions?.Mac; + query = DnsMessageBase.CreateByFlag(buffer); } catch (Exception e) { @@ -259,7 +211,7 @@ private async void HandleUdpListenerAsync() query.ReturnCode = ReturnCode.ServerFailure; } - int length = response.Encode(false, originalMac, out buffer); + int length = response.Encode(false, out buffer); #region Truncating DnsMessage message = response as DnsMessage; @@ -267,28 +219,9 @@ private async void HandleUdpListenerAsync() if (message != null) { int maxLength = 512; - if (query.IsEDnsEnabled && message.IsEDnsEnabled) - { - maxLength = Math.Max(512, (int) message.EDnsOptions.UdpPayloadSize); - } while (length > maxLength) { - // First step: remove data from additional records except the opt record - if ((message.IsEDnsEnabled && (message.AdditionalRecords.Count > 1)) || (!message.IsEDnsEnabled && (message.AdditionalRecords.Count > 0))) - { - for (int i = message.AdditionalRecords.Count - 1; i >= 0; i--) - { - if (message.AdditionalRecords[i].RecordType != RecordType.Opt) - { - message.AdditionalRecords.RemoveAt(i); - } - } - - length = message.Encode(false, originalMac, out buffer); - continue; - } - int savedLength = 0; if (message.AuthorityRecords.Count > 0) { @@ -305,7 +238,7 @@ private async void HandleUdpListenerAsync() message.IsTruncated = true; - length = message.Encode(false, originalMac, out buffer); + length = message.Encode(false, out buffer); continue; } @@ -324,7 +257,7 @@ private async void HandleUdpListenerAsync() message.IsTruncated = true; - length = message.Encode(false, originalMac, out buffer); + length = message.Encode(false, out buffer); continue; } @@ -343,7 +276,7 @@ private async void HandleUdpListenerAsync() message.IsTruncated = true; - length = message.Encode(false, originalMac, out buffer); + length = message.Encode(false, out buffer); } } } @@ -425,11 +358,10 @@ private async void HandleTcpListenerAsync() } DnsMessageBase query; - byte[] tsigMac; + try { - query = DnsMessageBase.CreateByFlag(buffer, TsigKeySelector, null); - tsigMac = query.TSigOptions?.Mac; + query = DnsMessageBase.CreateByFlag(buffer); } catch (Exception e) { @@ -445,7 +377,7 @@ private async void HandleTcpListenerAsync() { OnExceptionThrownAsync(ex); - response = DnsMessageBase.CreateByFlag(buffer, TsigKeySelector, null); + response = DnsMessageBase.CreateByFlag(buffer); response.IsQuery = false; response.AdditionalRecords.Clear(); response.AuthorityRecords.Clear(); @@ -454,7 +386,7 @@ private async void HandleTcpListenerAsync() byte[] newTsigMac; - length = response.Encode(true, tsigMac, false, out buffer, out newTsigMac); + length = response.Encode(true, false, out buffer); if (length <= 65535) { @@ -466,13 +398,13 @@ private async void HandleTcpListenerAsync() { OnExceptionThrownAsync(new ArgumentException("The length of the serialized response is greater than 65,535 bytes")); - response = DnsMessageBase.CreateByFlag(buffer, TsigKeySelector, null); + response = DnsMessageBase.CreateByFlag(buffer); response.IsQuery = false; response.AdditionalRecords.Clear(); response.AuthorityRecords.Clear(); response.ReturnCode = ReturnCode.ServerFailure; - length = response.Encode(true, tsigMac, false, out buffer, out newTsigMac); + length = response.Encode(true, false, out buffer); await stream.WriteAsync(buffer, 0, length); } else @@ -491,7 +423,7 @@ private async void HandleTcpListenerAsync() nextPacketRecords.InsertRange(0, response.AnswerRecords.GetRange(lastIndex, removeCount)); response.AnswerRecords.RemoveRange(lastIndex, removeCount); - length = response.Encode(true, tsigMac, isSubSequentResponse, out buffer, out newTsigMac); + length = response.Encode(true, isSubSequentResponse, out buffer); } await stream.WriteAsync(buffer, 0, length); @@ -500,16 +432,11 @@ private async void HandleTcpListenerAsync() break; isSubSequentResponse = true; - tsigMac = newTsigMac; response.AnswerRecords = nextPacketRecords; - length = response.Encode(true, tsigMac, true, out buffer, out newTsigMac); + length = response.Encode(true, true, out buffer); } } } - - // Since support for multiple tsig signed messages is not finished, just close connection after response to first signed query - if (newTsigMac != null) - break; } } } diff --git a/ARSoft.Tools.Net/Dns/DynamicUpdate/DnsUpdateMessage.cs b/ARSoft.Tools.Net/Dns/DynamicUpdate/DnsUpdateMessage.cs index 48a7c14..aa546e6 100644 --- a/ARSoft.Tools.Net/Dns/DynamicUpdate/DnsUpdateMessage.cs +++ b/ARSoft.Tools.Net/Dns/DynamicUpdate/DnsUpdateMessage.cs @@ -89,18 +89,11 @@ public DnsUpdateMessage CreateResponseInstance() DnsUpdateMessage result = new DnsUpdateMessage() { TransactionID = TransactionID, - IsEDnsEnabled = IsEDnsEnabled, IsQuery = false, OperationCode = OperationCode, Questions = new List(Questions), }; - if (IsEDnsEnabled) - { - result.EDnsOptions.Version = EDnsOptions.Version; - result.EDnsOptions.UdpPayloadSize = EDnsOptions.UdpPayloadSize; - } - return result; } diff --git a/ARSoft.Tools.Net/Dns/EDns/ClientSubnetOption.cs b/ARSoft.Tools.Net/Dns/EDns/ClientSubnetOption.cs deleted file mode 100644 index 5432580..0000000 --- a/ARSoft.Tools.Net/Dns/EDns/ClientSubnetOption.cs +++ /dev/null @@ -1,111 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Net.Sockets; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// EDNS0 Client Subnet Option - /// - /// Defined in - /// draft-vandergaast-edns-client-subnet - /// - /// - public class ClientSubnetOption : EDnsOptionBase - { - /// - /// The address family - /// - public AddressFamily Family => Address.AddressFamily; - - /// - /// The source subnet mask - /// - public byte SourceNetmask { get; private set; } - - /// - /// The scope subnet mask - /// - public byte ScopeNetmask { get; private set; } - - /// - /// The address - /// - public IPAddress Address { get; private set; } - - internal ClientSubnetOption() - : base(EDnsOptionType.ClientSubnet) {} - - /// - /// Creates a new instance of the OwnerOption class - /// - /// The source subnet mask - /// The address - public ClientSubnetOption(byte sourceNetmask, IPAddress address) - : this(sourceNetmask, 0, address) {} - - /// - /// Creates a new instance of the OwnerOption class - /// - /// The source subnet mask - /// The scope subnet mask - /// The address - public ClientSubnetOption(byte sourceNetmask, byte scopeNetmask, IPAddress address) - : this() - { - SourceNetmask = sourceNetmask; - ScopeNetmask = scopeNetmask; - Address = address; - } - - internal override void ParseData(byte[] resultData, int startPosition, int length) - { - ushort family = DnsMessageBase.ParseUShort(resultData, ref startPosition); - SourceNetmask = resultData[startPosition++]; - ScopeNetmask = resultData[startPosition++]; - - byte[] addressData = new byte[family == 1 ? 4 : 16]; - Buffer.BlockCopy(resultData, startPosition, addressData, 0, GetAddressLength()); - - Address = new IPAddress(addressData); - } - - internal override ushort DataLength => (ushort) (4 + GetAddressLength()); - - internal override void EncodeData(byte[] messageData, ref int currentPosition) - { - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, (ushort) (Family == AddressFamily.InterNetwork ? 1 : 2)); - messageData[currentPosition++] = SourceNetmask; - messageData[currentPosition++] = ScopeNetmask; - - byte[] data = Address.GetAddressBytes(); - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, data, GetAddressLength()); - } - - private int GetAddressLength() - { - return (int) Math.Ceiling(SourceNetmask / 8d); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/EDns/CookieOption.cs b/ARSoft.Tools.Net/Dns/EDns/CookieOption.cs deleted file mode 100644 index 2cec763..0000000 --- a/ARSoft.Tools.Net/Dns/EDns/CookieOption.cs +++ /dev/null @@ -1,85 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Cookie Option - /// - /// Defined in - /// draft-ietf-dnsop-cookies - /// - /// - public class CookieOption : EDnsOptionBase - { - private byte[] _clientCookie; - - /// - /// Client cookie - /// - public byte[] ClientCookie - { - get { return _clientCookie; } - private set - { - if ((value == null) || (value.Length != 8)) - throw new ArgumentException("Client cookie must contain 8 bytes"); - _clientCookie = value; - } - } - - /// - /// Server cookie - /// - public byte[] ServerCookie { get; private set; } - - /// - /// Creates a new instance of the ClientCookie class - /// - public CookieOption() - : base(EDnsOptionType.Cookie) {} - - /// - /// Creates a new instance of the ClientCookie class - /// - /// The client cookie - /// The server cookie - public CookieOption(byte[] clientCookie, byte[] serverCookie = null) - : this() - { - ClientCookie = clientCookie; - ServerCookie = serverCookie ?? new byte[] { }; - } - - internal override void ParseData(byte[] resultData, int startPosition, int length) - { - ClientCookie = DnsMessageBase.ParseByteData(resultData, ref startPosition, 8); - ServerCookie = DnsMessageBase.ParseByteData(resultData, ref startPosition, length - 8); - } - - internal override ushort DataLength => (ushort) (8 + ServerCookie.Length); - - internal override void EncodeData(byte[] messageData, ref int currentPosition) - { - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, ClientCookie); - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, ServerCookie); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/EDns/DnssecAlgorithmUnderstoodOption.cs b/ARSoft.Tools.Net/Dns/EDns/DnssecAlgorithmUnderstoodOption.cs deleted file mode 100644 index a18aed4..0000000 --- a/ARSoft.Tools.Net/Dns/EDns/DnssecAlgorithmUnderstoodOption.cs +++ /dev/null @@ -1,72 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// DNSSEC Algorithm Understood option - /// - /// Defined in - /// RFC 6975 - /// - /// - public class DnssecAlgorithmUnderstoodOption : EDnsOptionBase - { - /// - /// List of Algorithms - /// - public List Algorithms { get; private set; } - - internal DnssecAlgorithmUnderstoodOption() - : base(EDnsOptionType.DnssecAlgorithmUnderstood) {} - - /// - /// Creates a new instance of the DnssecAlgorithmUnderstoodOption class - /// - /// The list of algorithms - public DnssecAlgorithmUnderstoodOption(List algorithms) - : this() - { - Algorithms = algorithms; - } - - internal override void ParseData(byte[] resultData, int startPosition, int length) - { - Algorithms = new List(length); - for (int i = 0; i < length; i++) - { - Algorithms.Add((DnsSecAlgorithm) resultData[startPosition++]); - } - } - - internal override ushort DataLength => (ushort) (Algorithms?.Count ?? 0); - - internal override void EncodeData(byte[] messageData, ref int currentPosition) - { - foreach (var algorithm in Algorithms) - { - messageData[currentPosition++] = (byte) algorithm; - } - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/EDns/DsHashUnderstoodOption.cs b/ARSoft.Tools.Net/Dns/EDns/DsHashUnderstoodOption.cs deleted file mode 100644 index 44320c9..0000000 --- a/ARSoft.Tools.Net/Dns/EDns/DsHashUnderstoodOption.cs +++ /dev/null @@ -1,72 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// DS Hash Understood option - /// - /// Defined in - /// RFC 6975 - /// - /// - public class DsHashUnderstoodOption : EDnsOptionBase - { - /// - /// List of Algorithms - /// - public List Algorithms { get; private set; } - - internal DsHashUnderstoodOption() - : base(EDnsOptionType.DsHashUnderstood) {} - - /// - /// Creates a new instance of the DsHashUnderstoodOption class - /// - /// The list of algorithms - public DsHashUnderstoodOption(List algorithms) - : this() - { - Algorithms = algorithms; - } - - internal override void ParseData(byte[] resultData, int startPosition, int length) - { - Algorithms = new List(length); - for (int i = 0; i < length; i++) - { - Algorithms.Add((DnsSecAlgorithm) resultData[startPosition++]); - } - } - - internal override ushort DataLength => (ushort) (Algorithms?.Count ?? 0); - - internal override void EncodeData(byte[] messageData, ref int currentPosition) - { - foreach (var algorithm in Algorithms) - { - messageData[currentPosition++] = (byte) algorithm; - } - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/EDns/EDnsOptionBase.cs b/ARSoft.Tools.Net/Dns/EDns/EDnsOptionBase.cs deleted file mode 100644 index 6b1ff3a..0000000 --- a/ARSoft.Tools.Net/Dns/EDns/EDnsOptionBase.cs +++ /dev/null @@ -1,45 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Base class of EDNS options - /// - public abstract class EDnsOptionBase - { - /// - /// Type of the option - /// - public EDnsOptionType Type { get; internal set; } - - internal EDnsOptionBase(EDnsOptionType optionType) - { - Type = optionType; - } - - internal abstract void ParseData(byte[] resultData, int startPosition, int length); - internal abstract ushort DataLength { get; } - internal abstract void EncodeData(byte[] messageData, ref int currentPosition); - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/EDns/EDnsOptionType.cs b/ARSoft.Tools.Net/Dns/EDns/EDnsOptionType.cs deleted file mode 100644 index b78a6eb..0000000 --- a/ARSoft.Tools.Net/Dns/EDns/EDnsOptionType.cs +++ /dev/null @@ -1,121 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// ENDS Option types - /// - public enum EDnsOptionType : ushort - { - /// - /// Update Lease - /// - /// Defined in - /// draft-sekar-dns-llq - /// - /// - LongLivedQuery = 1, - - /// - /// Update Lease - /// - /// Defined in - /// draft-sekar-dns-ul - /// - /// - UpdateLease = 2, - - /// - /// Name server ID - /// - /// Defined in - /// RFC 5001 - /// - /// - NsId = 3, - - /// - /// Owner - /// - /// Defined in - /// draft-cheshire-edns0-owner-option - /// - /// - Owner = 4, - - /// - /// DNSSEC Algorithm Understood - /// - /// Defined in - /// RFC 6975 - /// - /// - DnssecAlgorithmUnderstood = 5, - - /// - /// DS Hash Understood - /// - /// Defined in - /// RFC 6975 - /// - /// - DsHashUnderstood = 6, - - /// - /// NSEC3 Hash Understood - /// - /// Defined in - /// RFC 6975 - /// - /// - Nsec3HashUnderstood = 7, - - /// - /// ClientSubnet - /// - /// Defined in - /// draft-vandergaast-edns-client-subnet - /// - /// - ClientSubnet = 8, - - /// - /// Expire EDNS Option - /// - /// Defined in - /// RFC 7314 - /// - /// - Expire = 9, - - /// - /// Cookie Option - /// - /// Defined in - /// draft-ietf-dnsop-cookies - /// - /// - Cookie = 10, - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/EDns/ExpireOption.cs b/ARSoft.Tools.Net/Dns/EDns/ExpireOption.cs deleted file mode 100644 index 346cef6..0000000 --- a/ARSoft.Tools.Net/Dns/EDns/ExpireOption.cs +++ /dev/null @@ -1,70 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Expire EDNS Option - /// - /// Defined in - /// RFC 7314 - /// - /// - public class ExpireOption : EDnsOptionBase - { - /// - /// The expiration of the SOA record in seconds. Should be null on queries. - /// - public int? SoaExpire { get; private set; } - - /// - /// Creates a new instance of the ExpireOption class - /// - public ExpireOption() - : base(EDnsOptionType.Expire) {} - - /// - /// Creates a new instance of the ExpireOption class - /// - /// The expiration of the SOA record in seconds - public ExpireOption(int soaExpire) - : this() - { - SoaExpire = soaExpire; - } - - internal override void ParseData(byte[] resultData, int startPosition, int length) - { - if (length == 4) - SoaExpire = DnsMessageBase.ParseInt(resultData, ref startPosition); - } - - internal override ushort DataLength => (ushort) (SoaExpire.HasValue ? 4 : 0); - - internal override void EncodeData(byte[] messageData, ref int currentPosition) - { - if (SoaExpire.HasValue) - DnsMessageBase.EncodeInt(messageData, ref currentPosition, SoaExpire.Value); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/EDns/LongLivedQueryOption.cs b/ARSoft.Tools.Net/Dns/EDns/LongLivedQueryOption.cs deleted file mode 100644 index 5c5121d..0000000 --- a/ARSoft.Tools.Net/Dns/EDns/LongLivedQueryOption.cs +++ /dev/null @@ -1,174 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Long lived query option - /// - /// Defined in - /// draft-sekar-dns-llq - /// - /// - public class LongLivedQueryOption : EDnsOptionBase - { - /// - /// Long lived query operation codes - /// - public enum LlqOperationCode : ushort - { - /// - /// Setup a LLQ - /// - Setup = 1, - - /// - /// Refresh a LLQ - /// - Refresh = 2, - - /// - /// LLQ event - /// - Event = 3, - } - - /// - /// Long lived query error codes - /// - public enum LlqErrorCode : ushort - { - /// - /// The LLQ Setup Request was successful. - /// - NoError = 0, - - /// - /// The server cannot grant the LLQ request because it is overloaded, or the request exceeds the server's rate limit. - /// - ServerFull = 1, - - /// - /// The data for this name and type is not expected to change frequently, and the server therefore does not support the - /// requested LLQ. - /// - Static = 2, - - /// - /// The LLQ was improperly formatted - /// - FormatError = 3, - - /// - /// The requested LLQ is expired or non-existent - /// - NoSuchLlq = 4, - - /// - /// The protocol version specified in the client's request is not supported by the server. - /// - BadVersion = 5, - - /// - /// The LLQ was not granted for an unknown reason. - /// - UnknownError = 6, - } - - /// - /// Version of LLQ protocol implemented - /// - public ushort Version { get; private set; } - - /// - /// Identifies LLQ operation - /// - public LlqOperationCode OperationCode { get; private set; } - - /// - /// Identifies LLQ errors - /// - public LlqErrorCode ErrorCode { get; private set; } - - /// - /// Identifier for an LLQ - /// - public ulong Id { get; private set; } - - /// - /// Requested or granted life of LLQ - /// - public TimeSpan LeaseTime { get; private set; } - - internal LongLivedQueryOption() - : base(EDnsOptionType.LongLivedQuery) {} - - /// - /// Creates a new instance of the LongLivedQueryOption class - /// - /// Identifies LLQ operation - /// Identifies LLQ errors - /// Identifier for an LLQ - /// Requested or granted life of LLQ - public LongLivedQueryOption(LlqOperationCode operationCode, LlqErrorCode errorCode, ulong id, TimeSpan leaseTime) - : this(0, operationCode, errorCode, id, leaseTime) {} - - /// - /// Creates a new instance of the LongLivedQueryOption class - /// - /// Version of LLQ protocol implemented - /// Identifies LLQ operation - /// Identifies LLQ errors - /// Identifier for an LLQ - /// Requested or granted life of LLQ - public LongLivedQueryOption(ushort version, LlqOperationCode operationCode, LlqErrorCode errorCode, ulong id, TimeSpan leaseTime) - : this() - { - Version = version; - OperationCode = operationCode; - ErrorCode = errorCode; - Id = id; - LeaseTime = leaseTime; - } - - internal override void ParseData(byte[] resultData, int startPosition, int length) - { - Version = DnsMessageBase.ParseUShort(resultData, ref startPosition); - OperationCode = (LlqOperationCode) DnsMessageBase.ParseUShort(resultData, ref startPosition); - ErrorCode = (LlqErrorCode) DnsMessageBase.ParseUShort(resultData, ref startPosition); - Id = DnsMessageBase.ParseULong(resultData, ref startPosition); - LeaseTime = TimeSpan.FromSeconds(DnsMessageBase.ParseUInt(resultData, ref startPosition)); - } - - internal override ushort DataLength => 18; - - internal override void EncodeData(byte[] messageData, ref int currentPosition) - { - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, Version); - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, (ushort) OperationCode); - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, (ushort) ErrorCode); - DnsMessageBase.EncodeULong(messageData, ref currentPosition, Id); - DnsMessageBase.EncodeUInt(messageData, ref currentPosition, (uint) LeaseTime.TotalSeconds); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/EDns/NsIdOption.cs b/ARSoft.Tools.Net/Dns/EDns/NsIdOption.cs deleted file mode 100644 index 72f240a..0000000 --- a/ARSoft.Tools.Net/Dns/EDns/NsIdOption.cs +++ /dev/null @@ -1,64 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Name server ID option - /// - /// Defined in - /// RFC 5001 - /// - /// - public class NsIdOption : EDnsOptionBase - { - /// - /// Binary data of the payload - /// - public byte[] Payload { get; private set; } - - internal NsIdOption() - : base(EDnsOptionType.NsId) {} - - /// - /// Creates a new instance of the NsIdOption class - /// - public NsIdOption(byte[] payload) - : this() - { - Payload = payload; - } - - internal override void ParseData(byte[] resultData, int startPosition, int length) - { - Payload = DnsMessageBase.ParseByteData(resultData, ref startPosition, length); - } - - internal override ushort DataLength => (ushort) (Payload?.Length ?? 0); - - internal override void EncodeData(byte[] messageData, ref int currentPosition) - { - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, Payload); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/EDns/Nsec3HashUnderstoodOption.cs b/ARSoft.Tools.Net/Dns/EDns/Nsec3HashUnderstoodOption.cs deleted file mode 100644 index 9ebf53d..0000000 --- a/ARSoft.Tools.Net/Dns/EDns/Nsec3HashUnderstoodOption.cs +++ /dev/null @@ -1,72 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// NSEC3 Hash Unterstood option - /// - /// Defined in - /// RFC 6975 - /// - /// - public class Nsec3HashUnderstoodOption : EDnsOptionBase - { - /// - /// List of Algorithms - /// - public List Algorithms { get; private set; } - - internal Nsec3HashUnderstoodOption() - : base(EDnsOptionType.Nsec3HashUnderstood) {} - - /// - /// Creates a new instance of the Nsec3HashUnderstoodOption class - /// - /// The list of algorithms - public Nsec3HashUnderstoodOption(List algorithms) - : this() - { - Algorithms = algorithms; - } - - internal override void ParseData(byte[] resultData, int startPosition, int length) - { - Algorithms = new List(length); - for (int i = 0; i < length; i++) - { - Algorithms.Add((DnsSecAlgorithm) resultData[startPosition++]); - } - } - - internal override ushort DataLength => (ushort) (Algorithms?.Count ?? 0); - - internal override void EncodeData(byte[] messageData, ref int currentPosition) - { - foreach (var algorithm in Algorithms) - { - messageData[currentPosition++] = (byte) algorithm; - } - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/EDns/OptRecord.cs b/ARSoft.Tools.Net/Dns/EDns/OptRecord.cs deleted file mode 100644 index f079793..0000000 --- a/ARSoft.Tools.Net/Dns/EDns/OptRecord.cs +++ /dev/null @@ -1,223 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// OPT record - /// - /// Defined in - /// RFC 2671 - /// - /// - public class OptRecord : DnsRecordBase - { - /// - /// Gets or set the sender's UDP payload size - /// - public ushort UdpPayloadSize - { - get { return (ushort) RecordClass; } - set { RecordClass = (RecordClass) value; } - } - - /// - /// Gets or sets the high bits of return code (EXTENDED-RCODE) - /// - public ReturnCode ExtendedReturnCode - { - get { return (ReturnCode) ((TimeToLive & 0xff000000) >> 20); } - set - { - int clearedTtl = (TimeToLive & 0x00ffffff); - TimeToLive = (clearedTtl | ((int) value << 20)); - } - } - - /// - /// Gets or set the EDNS version - /// - public byte Version - { - get { return (byte) ((TimeToLive & 0x00ff0000) >> 16); } - set - { - int clearedTtl = (int) ((uint) TimeToLive & 0xff00ffff); - TimeToLive = clearedTtl | (value << 16); - } - } - - /// - /// Gets or sets the DNSSEC OK (DO) flag - /// - /// Defined in - /// RFC 4035 - /// and - /// RFC 3225 - /// - /// - public bool IsDnsSecOk - { - get { return (TimeToLive & 0x8000) != 0; } - set - { - if (value) - { - TimeToLive |= 0x8000; - } - else - { - TimeToLive &= 0x7fff; - } - } - } - - /// - /// Gets or set additional EDNS options - /// - public List Options { get; private set; } - - /// - /// Creates a new instance of the OptRecord - /// - public OptRecord() - : base(DomainName.Root, RecordType.Opt, unchecked((RecordClass) 512), 0) - { - UdpPayloadSize = 4096; - Options = new List(); - } - - internal override void ParseRecordData(byte[] resultData, int startPosition, int length) - { - int endPosition = startPosition + length; - - Options = new List(); - while (startPosition < endPosition) - { - EDnsOptionType type = (EDnsOptionType) DnsMessageBase.ParseUShort(resultData, ref startPosition); - ushort dataLength = DnsMessageBase.ParseUShort(resultData, ref startPosition); - - EDnsOptionBase option; - - switch (type) - { - case EDnsOptionType.LongLivedQuery: - option = new LongLivedQueryOption(); - break; - - case EDnsOptionType.UpdateLease: - option = new UpdateLeaseOption(); - break; - - case EDnsOptionType.NsId: - option = new NsIdOption(); - break; - - case EDnsOptionType.Owner: - option = new OwnerOption(); - break; - - case EDnsOptionType.DnssecAlgorithmUnderstood: - option = new DnssecAlgorithmUnderstoodOption(); - break; - - case EDnsOptionType.DsHashUnderstood: - option = new DsHashUnderstoodOption(); - break; - - case EDnsOptionType.Nsec3HashUnderstood: - option = new Nsec3HashUnderstoodOption(); - break; - - case EDnsOptionType.ClientSubnet: - option = new ClientSubnetOption(); - break; - - case EDnsOptionType.Expire: - option = new ExpireOption(); - break; - - case EDnsOptionType.Cookie: - option = new CookieOption(); - break; - - default: - option = new UnknownOption(type); - break; - } - - option.ParseData(resultData, startPosition, dataLength); - Options.Add(option); - startPosition += dataLength; - } - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - throw new NotSupportedException(); - } - - /// - /// Returns the textual representation of the OptRecord - /// - /// The textual representation - public override string ToString() - { - return RecordDataToString(); - } - - internal override string RecordDataToString() - { - string flags = IsDnsSecOk ? "DO" : ""; - return String.Format("; EDNS version: {0}; flags: {1}; udp: {2}", Version, flags, UdpPayloadSize); - } - - protected internal override int MaximumRecordDataLength - { - get - { - if ((Options == null) || (Options.Count == 0)) - { - return 0; - } - else - { - return Options.Sum(option => option.DataLength + 4); - } - } - } - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - if ((Options != null) && (Options.Count != 0)) - { - foreach (EDnsOptionBase option in Options) - { - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, (ushort) option.Type); - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, option.DataLength); - option.EncodeData(messageData, ref currentPosition); - } - } - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/EDns/OwnerOption.cs b/ARSoft.Tools.Net/Dns/EDns/OwnerOption.cs deleted file mode 100644 index abfdf6b..0000000 --- a/ARSoft.Tools.Net/Dns/EDns/OwnerOption.cs +++ /dev/null @@ -1,151 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.NetworkInformation; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// EDNS0 Owner Option - /// - /// Defined in - /// draft-cheshire-edns0-owner-option - /// - /// - public class OwnerOption : EDnsOptionBase - { - /// - /// The version - /// - public byte Version { get; private set; } - - /// - /// The sequence number - /// - public byte Sequence { get; private set; } - - /// - /// The primary MAC address - /// - public PhysicalAddress PrimaryMacAddress { get; private set; } - - /// - /// The Wakeup MAC address - /// - public PhysicalAddress WakeupMacAddress { get; private set; } - - /// - /// The password, should be empty, 4 bytes long or 6 bytes long - /// - public byte[] Password { get; private set; } - - internal OwnerOption() - : base(EDnsOptionType.Owner) {} - - /// - /// Creates a new instance of the OwnerOption class - /// - /// The sequence number - /// The primary MAC address - public OwnerOption(byte sequence, PhysicalAddress primaryMacAddress) - : this(0, sequence, primaryMacAddress, null) {} - - /// - /// Creates a new instance of the OwnerOption class - /// - /// The version - /// The sequence number - /// The primary MAC address - public OwnerOption(byte version, byte sequence, PhysicalAddress primaryMacAddress) - : this(version, sequence, primaryMacAddress, null) {} - - /// - /// Creates a new instance of the OwnerOption class - /// - /// The sequence number - /// The primary MAC address - /// The wakeup MAC address - public OwnerOption(byte sequence, PhysicalAddress primaryMacAddress, PhysicalAddress wakeupMacAddress) - : this(0, sequence, primaryMacAddress, wakeupMacAddress) {} - - /// - /// Creates a new instance of the OwnerOption class - /// - /// The version - /// The sequence number - /// The primary MAC address - /// The wakeup MAC address - public OwnerOption(byte version, byte sequence, PhysicalAddress primaryMacAddress, PhysicalAddress wakeupMacAddress) - : this(version, sequence, primaryMacAddress, wakeupMacAddress, null) {} - - /// - /// Creates a new instance of the OwnerOption class - /// - /// The sequence number - /// The primary MAC address - /// The wakeup MAC address - /// The password, should be empty, 4 bytes long or 6 bytes long - public OwnerOption(byte sequence, PhysicalAddress primaryMacAddress, PhysicalAddress wakeupMacAddress, byte[] password) - : this(0, sequence, primaryMacAddress, wakeupMacAddress, password) {} - - /// - /// Creates a new instance of the OwnerOption class - /// - /// The version - /// The sequence number - /// The primary MAC address - /// The wakeup MAC address - /// The password, should be empty, 4 bytes long or 6 bytes long - public OwnerOption(byte version, byte sequence, PhysicalAddress primaryMacAddress, PhysicalAddress wakeupMacAddress, byte[] password) - : this() - { - Version = version; - Sequence = sequence; - PrimaryMacAddress = primaryMacAddress; - WakeupMacAddress = wakeupMacAddress; - Password = password; - } - - internal override void ParseData(byte[] resultData, int startPosition, int length) - { - Version = resultData[startPosition++]; - Sequence = resultData[startPosition++]; - PrimaryMacAddress = new PhysicalAddress(DnsMessageBase.ParseByteData(resultData, ref startPosition, 6)); - if (length > 8) - WakeupMacAddress = new PhysicalAddress(DnsMessageBase.ParseByteData(resultData, ref startPosition, 6)); - if (length > 14) - Password = DnsMessageBase.ParseByteData(resultData, ref startPosition, length - 14); - } - - internal override ushort DataLength => (ushort) (8 + (WakeupMacAddress != null ? 6 : 0) + (Password?.Length ?? 0)); - - internal override void EncodeData(byte[] messageData, ref int currentPosition) - { - messageData[currentPosition++] = Version; - messageData[currentPosition++] = Sequence; - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, PrimaryMacAddress.GetAddressBytes()); - if (WakeupMacAddress != null) - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, WakeupMacAddress.GetAddressBytes()); - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, Password); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/EDns/UnknownOption.cs b/ARSoft.Tools.Net/Dns/EDns/UnknownOption.cs deleted file mode 100644 index 832a7d3..0000000 --- a/ARSoft.Tools.Net/Dns/EDns/UnknownOption.cs +++ /dev/null @@ -1,62 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Unknown EDNS option - /// - public class UnknownOption : EDnsOptionBase - { - /// - /// Binary data of the option - /// - public byte[] Data { get; private set; } - - internal UnknownOption(EDnsOptionType type) - : base(type) {} - - /// - /// Creates a new instance of the UnknownOption class - /// - /// Type of the option - /// The data of the option - public UnknownOption(EDnsOptionType type, byte[] data) - : this(type) - { - Data = data; - } - - internal override void ParseData(byte[] resultData, int startPosition, int length) - { - Data = DnsMessageBase.ParseByteData(resultData, ref startPosition, length); - } - - internal override ushort DataLength => (ushort) (Data?.Length ?? 0); - - internal override void EncodeData(byte[] messageData, ref int currentPosition) - { - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, Data); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/EDns/UpdateLeaseOption.cs b/ARSoft.Tools.Net/Dns/EDns/UpdateLeaseOption.cs deleted file mode 100644 index ea04003..0000000 --- a/ARSoft.Tools.Net/Dns/EDns/UpdateLeaseOption.cs +++ /dev/null @@ -1,64 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Update lease option - /// - /// Defined in - /// draft-sekar-dns-ul - /// - /// - public class UpdateLeaseOption : EDnsOptionBase - { - /// - /// Desired lease (request) or granted lease (response) - /// - public TimeSpan LeaseTime { get; private set; } - - internal UpdateLeaseOption() - : base(EDnsOptionType.UpdateLease) {} - - /// - /// Creates a new instance of the UpdateLeaseOption class - /// - public UpdateLeaseOption(TimeSpan leaseTime) - : this() - { - LeaseTime = leaseTime; - } - - internal override void ParseData(byte[] resultData, int startPosition, int length) - { - LeaseTime = TimeSpan.FromSeconds(DnsMessageBase.ParseInt(resultData, ref startPosition)); - } - - internal override ushort DataLength => 4; - - internal override void EncodeData(byte[] messageData, ref int currentPosition) - { - DnsMessageBase.EncodeInt(messageData, ref currentPosition, (int) LeaseTime.TotalSeconds); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/LlmnrClient.cs b/ARSoft.Tools.Net/Dns/LlmnrClient.cs deleted file mode 100644 index 6bf125c..0000000 --- a/ARSoft.Tools.Net/Dns/LlmnrClient.cs +++ /dev/null @@ -1,111 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Net.NetworkInformation; -using System.Threading; -using System.Threading.Tasks; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Provides a client for querying LLMNR (link-local multicast name resolution) as defined in - /// - /// RFC 4795 - /// - /// . - /// - public sealed class LlmnrClient : DnsClientBase - { - private static readonly List _addresses = new List { IPAddress.Parse("FF02::1:3"), IPAddress.Parse("224.0.0.252") }; - - /// - /// Provides a new instance with a timeout of 1 second - /// - public LlmnrClient() - : this(1000) {} - - /// - /// Provides a new instance with a custom timeout - /// - /// Query timeout in milliseconds - public LlmnrClient(int queryTimeout) - : base(_addresses, queryTimeout, 5355) - { - int maximumMessageSize = 0; - - try - { - maximumMessageSize = NetworkInterface.GetAllNetworkInterfaces() - .Where(n => n.SupportsMulticast && (n.NetworkInterfaceType != NetworkInterfaceType.Loopback) && (n.OperationalStatus == OperationalStatus.Up) && (n.Supports(NetworkInterfaceComponent.IPv4))) - .Select(n => n.GetIPProperties()) - .Min(p => Math.Min(p.GetIPv4Properties().Mtu, p.GetIPv6Properties().Mtu)); - } - catch - { - // ignored - } - - MaximumQueryMessageSize = Math.Max(512, maximumMessageSize); - - IsUdpEnabled = true; - IsTcpEnabled = false; - } - - protected override int MaximumQueryMessageSize { get; } - - /// - /// Queries for specified records. - /// - /// Name, that should be queried - /// Type the should be queried - /// All available responses on the local network - public List Resolve(DomainName name, RecordType recordType = RecordType.A) - { - if (name == null) - throw new ArgumentNullException(nameof(name), "Name must be provided"); - - LlmnrMessage message = new LlmnrMessage { IsQuery = true, OperationCode = OperationCode.Query }; - message.Questions.Add(new DnsQuestion(name, recordType, RecordClass.INet)); - - return SendMessageParallel(message); - } - - /// - /// Queries for specified records as an asynchronous operation. - /// - /// Name, that should be queried - /// Type the should be queried - /// The token to monitor cancellation requests - /// All available responses on the local network - public Task> ResolveAsync(DomainName name, RecordType recordType = RecordType.A, CancellationToken token = default(CancellationToken)) - { - if (name == null) - throw new ArgumentNullException(nameof(name), "Name must be provided"); - - LlmnrMessage message = new LlmnrMessage { IsQuery = true, OperationCode = OperationCode.Query }; - message.Questions.Add(new DnsQuestion(name, recordType, RecordClass.INet)); - - return SendMessageParallelAsync(message, token); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/LlmnrMessage.cs b/ARSoft.Tools.Net/Dns/LlmnrMessage.cs deleted file mode 100644 index 0b81232..0000000 --- a/ARSoft.Tools.Net/Dns/LlmnrMessage.cs +++ /dev/null @@ -1,148 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Message returned as result to a LLMNR query - /// - public class LlmnrMessage : DnsMessageBase - { - /// - /// Parses a the contents of a byte array as LlmnrMessage - /// - /// Buffer, that contains the message data - /// A new instance of the LlmnrMessage class - public static LlmnrMessage Parse(byte[] data) - { - return Parse(data); - } - - #region Header - /// - /// Gets or sets the conflict (C) flag - /// - /// Defined in - /// RFC 4795 - /// - /// - public bool IsConflict - { - get { return (Flags & 0x0400) != 0; } - set - { - if (value) - { - Flags |= 0x0400; - } - else - { - Flags &= 0xfbff; - } - } - } - - /// - /// Gets or sets the truncated response (TC) flag - /// - /// Defined in - /// RFC 4795 - /// - /// - public bool IsTruncated - { - get { return (Flags & 0x0200) != 0; } - set - { - if (value) - { - Flags |= 0x0200; - } - else - { - Flags &= 0xfdff; - } - } - } - - /// - /// Gets or sets the tentive (T) flag - /// - /// Defined in - /// RFC 4795 - /// - /// - public bool IsTentive - { - get { return (Flags & 0x0100) != 0; } - set - { - if (value) - { - Flags |= 0x0100; - } - else - { - Flags &= 0xfeff; - } - } - } - #endregion - - /// - /// Gets or sets the entries in the question section - /// - public new List Questions - { - get { return base.Questions; } - set { base.Questions = (value ?? new List()); } - } - - /// - /// Gets or sets the entries in the answer records section - /// - public new List AnswerRecords - { - get { return base.AnswerRecords; } - set { base.AnswerRecords = (value ?? new List()); } - } - - /// - /// Gets or sets the entries in the authority records section - /// - public new List AuthorityRecords - { - get { return base.AuthorityRecords; } - set { base.AuthorityRecords = (value ?? new List()); } - } - - internal override bool IsTcpUsingRequested => (Questions.Count > 0) && ((Questions[0].RecordType == RecordType.Axfr) || (Questions[0].RecordType == RecordType.Ixfr)); - - internal override bool IsTcpResendingRequested => IsTruncated; - - internal override bool IsTcpNextMessageWaiting(bool isSubsequentResponseMessage) - { - return false; - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/MulticastDnsMessage.cs b/ARSoft.Tools.Net/Dns/MulticastDnsMessage.cs deleted file mode 100644 index 117da3d..0000000 --- a/ARSoft.Tools.Net/Dns/MulticastDnsMessage.cs +++ /dev/null @@ -1,217 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Message returned as result to a dns query - /// - public class MulticastDnsMessage : DnsMessageBase - { - /// - /// Parses a the contents of a byte array as MulticastDnsMessage - /// - /// Buffer, that contains the message data - /// A new instance of the MulticastDnsMessage class - public static MulticastDnsMessage Parse(byte[] data) - { - return Parse(data); - } - - #region Header - /// - /// Gets or sets the autoritive answer (AA) flag - /// - /// Defined in - /// RFC 1035 - /// - /// - public bool IsAuthoritiveAnswer - { - get { return (Flags & 0x0400) != 0; } - set - { - if (value) - { - Flags |= 0x0400; - } - else - { - Flags &= 0xfbff; - } - } - } - - /// - /// Gets or sets the truncated response (TC) flag - /// - /// Defined in - /// RFC 1035 - /// - /// - public bool IsTruncated - { - get { return (Flags & 0x0200) != 0; } - set - { - if (value) - { - Flags |= 0x0200; - } - else - { - Flags &= 0xfdff; - } - } - } - - /// - /// Gets or sets the recursion desired (RD) flag - /// - /// Defined in - /// RFC 1035 - /// - /// - public bool IsRecursionDesired - { - get { return (Flags & 0x0100) != 0; } - set - { - if (value) - { - Flags |= 0x0100; - } - else - { - Flags &= 0xfeff; - } - } - } - - /// - /// Gets or sets the recursion allowed (RA) flag - /// - /// Defined in - /// RFC 1035 - /// - /// - public bool IsRecursionAllowed - { - get { return (Flags & 0x0080) != 0; } - set - { - if (value) - { - Flags |= 0x0080; - } - else - { - Flags &= 0xff7f; - } - } - } - - /// - /// Gets or sets the authentic data (AD) flag - /// - /// Defined in - /// RFC 4035 - /// - /// - public bool IsAuthenticData - { - get { return (Flags & 0x0020) != 0; } - set - { - if (value) - { - Flags |= 0x0020; - } - else - { - Flags &= 0xffdf; - } - } - } - - /// - /// Gets or sets the checking disabled (CD) flag - /// - /// Defined in - /// RFC 4035 - /// - /// - public bool IsCheckingDisabled - { - get { return (Flags & 0x0010) != 0; } - set - { - if (value) - { - Flags |= 0x0010; - } - else - { - Flags &= 0xffef; - } - } - } - #endregion - - /// - /// Gets or sets the entries in the question section - /// - public new List Questions - { - get { return base.Questions; } - set { base.Questions = (value ?? new List()); } - } - - /// - /// Gets or sets the entries in the answer records section - /// - public new List AnswerRecords - { - get { return base.AnswerRecords; } - set { base.AnswerRecords = (value ?? new List()); } - } - - /// - /// Gets or sets the entries in the authority records section - /// - public new List AuthorityRecords - { - get { return base.AuthorityRecords; } - set { base.AuthorityRecords = (value ?? new List()); } - } - - internal override bool IsTcpUsingRequested => (Questions.Count > 0) && ((Questions[0].RecordType == RecordType.Axfr) || (Questions[0].RecordType == RecordType.Ixfr)); - - internal override bool IsTcpResendingRequested => IsTruncated; - - internal override bool IsTcpNextMessageWaiting(bool isSubsequentResponseMessage) - { - return false; - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/MulticastDnsOneShotClient.cs b/ARSoft.Tools.Net/Dns/MulticastDnsOneShotClient.cs deleted file mode 100644 index be0c703..0000000 --- a/ARSoft.Tools.Net/Dns/MulticastDnsOneShotClient.cs +++ /dev/null @@ -1,111 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Net.NetworkInformation; -using System.Threading; -using System.Threading.Tasks; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Provides a one/shot client for querying Multicast DNS as defined in - /// - /// RFC 6762 - /// - /// . - /// - public sealed class MulticastDnsOneShotClient : DnsClientBase - { - private static readonly List _addresses = new List { IPAddress.Parse("FF02::FB"), IPAddress.Parse("224.0.0.251") }; - - /// - /// Provides a new instance with a timeout of 2.5 seconds - /// - public MulticastDnsOneShotClient() - : this(2500) {} - - /// - /// Provides a new instance with a custom timeout - /// - /// Query timeout in milliseconds - public MulticastDnsOneShotClient(int queryTimeout) - : base(_addresses, queryTimeout, 5353) - { - int maximumMessageSize = 0; - - try - { - maximumMessageSize = NetworkInterface.GetAllNetworkInterfaces() - .Where(n => n.SupportsMulticast && (n.NetworkInterfaceType != NetworkInterfaceType.Loopback) && (n.OperationalStatus == OperationalStatus.Up) && (n.Supports(NetworkInterfaceComponent.IPv4))) - .Select(n => n.GetIPProperties()) - .Min(p => Math.Min(p.GetIPv4Properties().Mtu, p.GetIPv6Properties().Mtu)); - } - catch - { - // ignored - } - - MaximumQueryMessageSize = Math.Max(512, maximumMessageSize); - - IsUdpEnabled = true; - IsTcpEnabled = false; - } - - protected override int MaximumQueryMessageSize { get; } - - /// - /// Queries for specified records. - /// - /// Name, that should be queried - /// Type the should be queried - /// All available responses on the local network - public List Resolve(DomainName name, RecordType recordType = RecordType.Any) - { - if (name == null) - throw new ArgumentNullException(nameof(name), "Name must be provided"); - - MulticastDnsMessage message = new MulticastDnsMessage { IsQuery = true, OperationCode = OperationCode.Query }; - message.Questions.Add(new DnsQuestion(name, recordType, RecordClass.INet)); - - return SendMessageParallel(message); - } - - /// - /// Queries for specified records as an asynchronous operation. - /// - /// Name, that should be queried - /// Type the should be queried - /// The token to monitor cancellation requests - /// All available responses on the local network - public Task> ResolveAsync(DomainName name, RecordType recordType = RecordType.Any, CancellationToken token = default(CancellationToken)) - { - if (name == null) - throw new ArgumentNullException(nameof(name), "Name must be provided"); - - MulticastDnsMessage message = new MulticastDnsMessage { IsQuery = true, OperationCode = OperationCode.Query }; - message.Questions.Add(new DnsQuestion(name, recordType, RecordClass.INet)); - - return SendMessageParallelAsync(message, token); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/Resolver/DnsResolverExtensions.cs b/ARSoft.Tools.Net/Dns/Resolver/DnsResolverExtensions.cs deleted file mode 100644 index a9a6f1b..0000000 --- a/ARSoft.Tools.Net/Dns/Resolver/DnsResolverExtensions.cs +++ /dev/null @@ -1,156 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Extension methods for DNS resolvers - /// - public static class DnsResolverExtensions - { - /// - /// Queries a dns resolver for IP addresses of a host. - /// - /// The resolver instance, that should be used for queries - /// Host name, that should be queried - /// A list of matching host addresses - public static List ResolveHost(this IDnsResolver resolver, DomainName name) - { - List result = new List(); - - List aaaaRecords = resolver.Resolve(name, RecordType.Aaaa); - if (aaaaRecords != null) - result.AddRange(aaaaRecords.Select(x => x.Address)); - - List aRecords = resolver.Resolve(name); - if (aRecords != null) - result.AddRange(aRecords.Select(x => x.Address)); - - return result; - } - - /// - /// Queries a dns resolver for IP addresses of a host. - /// - /// The resolver instance, that should be used for queries - /// Host name, that should be queried - /// A list of matching host addresses - public static List ResolveHost(this IDnsResolver resolver, string name) - { - return resolver.ResolveHost(DomainName.Parse(name)); - } - - /// - /// Queries a dns resolver for IP addresses of a host as an asynchronous operation. - /// - /// The resolver instance, that should be used for queries - /// Host name, that should be queried - /// The token to monitor cancellation requests - /// A list of matching host addresses - public static async Task> ResolveHostAsync(this IDnsResolver resolver, DomainName name, CancellationToken token = default(CancellationToken)) - { - List result = new List(); - - List aaaaRecords = await resolver.ResolveAsync(name, RecordType.Aaaa, token: token); - if (aaaaRecords != null) - result.AddRange(aaaaRecords.Select(x => x.Address)); - - List aRecords = await resolver.ResolveAsync(name, token: token); - if (aRecords != null) - result.AddRange(aRecords.Select(x => x.Address)); - - return result; - } - - /// - /// Queries a dns resolver for IP addresses of a host as an asynchronous operation. - /// - /// The resolver instance, that should be used for queries - /// Host name, that should be queried - /// The token to monitor cancellation requests - /// A list of matching host addresses - public static Task> ResolveHostAsync(this IDnsResolver resolver, string name, CancellationToken token = default(CancellationToken)) - { - return resolver.ResolveHostAsync(DomainName.Parse(name), token); - } - - /// - /// Queries a dns resolver for reverse name of an IP address. - /// - /// The resolver instance, that should be used for queries - /// The address, that should be queried - /// The reverse name of the IP address - public static DomainName ResolvePtr(this IDnsResolver resolver, IPAddress address) - { - List ptrRecords = resolver.Resolve(address.GetReverseLookupDomain(), RecordType.Ptr); - return ptrRecords.Select(x => x.PointerDomainName).FirstOrDefault(); - } - - /// - /// Queries a dns resolver for reverse name of an IP address as an asynchronous operation. - /// - /// The resolver instance, that should be used for queries - /// The address, that should be queried - /// The token to monitor cancellation requests - /// The reverse name of the IP address - public static async Task ResolvePtrAsync(this IDnsResolver resolver, IPAddress address, CancellationToken token = default(CancellationToken)) - { - List ptrRecords = await resolver.ResolveAsync(address.GetReverseLookupDomain(), RecordType.Ptr, token: token); - return ptrRecords.Select(x => x.PointerDomainName).FirstOrDefault(); - } - - /// - /// Queries a dns resolver for specified records. - /// - /// Type of records, that should be returned - /// The resolver instance, that should be used for queries - /// Domain, that should be queried - /// Type the should be queried - /// Class the should be queried - /// A list of matching records - public static List Resolve(this IDnsResolver resolver, string name, RecordType recordType = RecordType.A, RecordClass recordClass = RecordClass.INet) - where T : DnsRecordBase - { - return resolver.Resolve(DomainName.Parse(name), recordType, recordClass); - } - - /// - /// Queries a dns resolver for specified records as an asynchronous operation. - /// - /// Type of records, that should be returned - /// The resolver instance, that should be used for queries - /// Domain, that should be queried - /// Type the should be queried - /// Class the should be queried - /// The token to monitor cancellation requests - /// A list of matching records - public static Task> ResolveAsync(this IDnsResolver resolver, string name, RecordType recordType = RecordType.A, RecordClass recordClass = RecordClass.INet, CancellationToken token = default(CancellationToken)) - where T : DnsRecordBase - { - return resolver.ResolveAsync(DomainName.Parse(name), recordType, recordClass, token); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/Resolver/DnsSecRecursiveDnsResolver.cs b/ARSoft.Tools.Net/Dns/Resolver/DnsSecRecursiveDnsResolver.cs deleted file mode 100644 index 06ba90d..0000000 --- a/ARSoft.Tools.Net/Dns/Resolver/DnsSecRecursiveDnsResolver.cs +++ /dev/null @@ -1,361 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Net.Sockets; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Recursive resolver - /// - /// Defined in - /// RFC 1035 - /// - /// - public class DnsSecRecursiveDnsResolver : IDnsSecResolver, IInternalDnsSecResolver - { - private class State - { - public int QueryCount; - } - - private DnsCache _cache = new DnsCache(); - private readonly DnsSecValidator _validator; - private NameserverCache _nameserverCache = new NameserverCache(); - - private readonly IResolverHintStore _resolverHintStore; - - /// - /// Provides a new instance with custom root server hints - /// - /// The resolver hint store with the IP addresses of the root server and root DnsKey hints - public DnsSecRecursiveDnsResolver(IResolverHintStore resolverHintStore = null) - { - _resolverHintStore = resolverHintStore ?? new StaticResolverHintStore(); - _validator = new DnsSecValidator(this, _resolverHintStore); - IsResponseValidationEnabled = true; - QueryTimeout = 2000; - MaximumReferalCount = 20; - } - - /// - /// Gets or sets a value indicating how much referals for a single query could be performed - /// - public int MaximumReferalCount { get; set; } - - /// - /// Milliseconds after which a query times out. - /// - public int QueryTimeout { get; set; } - - /// - /// Gets or set a value indicating whether the response is validated as described in - /// - /// draft-vixie-dnsext-dns0x20-00 - /// - /// - public bool IsResponseValidationEnabled { get; set; } - - /// - /// Gets or set a value indicating whether the query labels are used for additional validation as described in - /// - /// draft-vixie-dnsext-dns0x20-00 - /// - /// - // ReSharper disable once InconsistentNaming - public bool Is0x20ValidationEnabled { get; set; } - - /// - /// Clears the record cache - /// - public void ClearCache() - { - _cache = new DnsCache(); - _nameserverCache = new NameserverCache(); - } - - /// - /// Resolves specified records. - /// - /// Type of records, that should be returned - /// Domain, that should be queried - /// Type the should be queried - /// Class the should be queried - /// A list of matching records - public List Resolve(DomainName name, RecordType recordType = RecordType.A, RecordClass recordClass = RecordClass.INet) - where T : DnsRecordBase - { - var res = ResolveAsync(name, recordType, recordClass); - res.Wait(); - return res.Result; - } - - /// - /// Resolves specified records as an asynchronous operation. - /// - /// Type of records, that should be returned - /// Domain, that should be queried - /// Type the should be queried - /// Class the should be queried - /// The token to monitor cancellation requests - /// A list of matching records - public async Task> ResolveAsync(DomainName name, RecordType recordType = RecordType.A, RecordClass recordClass = RecordClass.INet, CancellationToken token = default(CancellationToken)) - where T : DnsRecordBase - { - var res = await ResolveSecureAsync(name, recordType, recordClass, token); - return res.Records; - } - - /// - /// Resolves specified records. - /// - /// Type of records, that should be returned - /// Domain, that should be queried - /// Type the should be queried - /// Class the should be queried - /// A list of matching records - public DnsSecResult ResolveSecure(DomainName name, RecordType recordType = RecordType.A, RecordClass recordClass = RecordClass.INet) - where T : DnsRecordBase - { - var res = ResolveSecureAsync(name, recordType, recordClass); - res.Wait(); - return res.Result; - } - - /// - /// Resolves specified records as an asynchronous operation. - /// - /// Type of records, that should be returned - /// Domain, that should be queried - /// Type the should be queried - /// Class the should be queried - /// The token to monitor cancellation requests - /// A list of matching records - public Task> ResolveSecureAsync(DomainName name, RecordType recordType = RecordType.A, RecordClass recordClass = RecordClass.INet, CancellationToken token = default(CancellationToken)) - where T : DnsRecordBase - { - if (name == null) - throw new ArgumentNullException(nameof(name), "Name must be provided"); - - return ResolveAsyncInternal(name, recordType, recordClass, new State(), token); - } - - private async Task ResolveMessageAsync(DomainName name, RecordType recordType, RecordClass recordClass, State state, CancellationToken token) - { - for (; state.QueryCount <= MaximumReferalCount; state.QueryCount++) - { - DnsMessage msg = await new DnsClient(GetBestNameservers(recordType == RecordType.Ds ? name.GetParentName() : name), QueryTimeout) - { - IsResponseValidationEnabled = IsResponseValidationEnabled, - Is0x20ValidationEnabled = Is0x20ValidationEnabled - }.ResolveAsync(name, recordType, recordClass, new DnsQueryOptions() - { - IsRecursionDesired = false, - IsEDnsEnabled = true, - IsDnsSecOk = true, - IsCheckingDisabled = true - }, token); - - if ((msg != null) && ((msg.ReturnCode == ReturnCode.NoError) || (msg.ReturnCode == ReturnCode.NxDomain))) - { - if (msg.IsAuthoritiveAnswer) - return msg; - - List referalRecords = msg.AuthorityRecords - .Where(x => - (x.RecordType == RecordType.Ns) - && (name.Equals(x.Name) || name.IsSubDomainOf(x.Name))) - .OfType() - .ToList(); - - if (referalRecords.Count > 0) - { - if (referalRecords.GroupBy(x => x.Name).Count() == 1) - { - var newServers = referalRecords.Join(msg.AdditionalRecords.OfType(), x => x.NameServer, x => x.Name, (x, y) => new { y.Address, TimeToLive = Math.Min(x.TimeToLive, y.TimeToLive) }).ToList(); - - if (newServers.Count > 0) - { - DomainName zone = referalRecords.First().Name; - - foreach (var newServer in newServers) - { - _nameserverCache.Add(zone, newServer.Address, newServer.TimeToLive); - } - - continue; - } - else - { - NsRecord firstReferal = referalRecords.First(); - - var newLookedUpServers = await ResolveHostWithTtlAsync(firstReferal.NameServer, state, token); - - foreach (var newServer in newLookedUpServers) - { - _nameserverCache.Add(firstReferal.Name, newServer.Item1, Math.Min(firstReferal.TimeToLive, newServer.Item2)); - } - - if (newLookedUpServers.Count > 0) - continue; - } - } - } - - // Response of best known server is not authoritive and has no referrals --> No chance to get a result - throw new Exception("Could not resolve " + name); - } - } - - // query limit reached without authoritive answer - throw new Exception("Could not resolve " + name); - } - - private async Task> ResolveAsyncInternal(DomainName name, RecordType recordType, RecordClass recordClass, State state, CancellationToken token) - where T : DnsRecordBase - { - DnsCacheRecordList cachedResults; - if (_cache.TryGetRecords(name, recordType, recordClass, out cachedResults)) - { - return new DnsSecResult(cachedResults, cachedResults.ValidationResult); - } - - DnsCacheRecordList cachedCNames; - if (_cache.TryGetRecords(name, RecordType.CName, recordClass, out cachedCNames)) - { - var cNameResult = await ResolveAsyncInternal(cachedCNames.First().CanonicalName, recordType, recordClass, state, token); - return new DnsSecResult(cNameResult.Records, cachedCNames.ValidationResult == cNameResult.ValidationResult ? cachedCNames.ValidationResult : DnsSecValidationResult.Unsigned); - } - - DnsMessage msg = await ResolveMessageAsync(name, recordType, recordClass, state, token); - - // check for cname - List cNameRecords = msg.AnswerRecords.Where(x => (x.RecordType == RecordType.CName) && (x.RecordClass == recordClass) && x.Name.Equals(name)).ToList(); - if (cNameRecords.Count > 0) - { - DnsSecValidationResult cNameValidationResult = await _validator.ValidateAsync(name, RecordType.CName, recordClass, msg, cNameRecords, state, token); - if ((cNameValidationResult == DnsSecValidationResult.Bogus) || (cNameValidationResult == DnsSecValidationResult.Indeterminate)) - throw new DnsSecValidationException("CNAME record could not be validated"); - - _cache.Add(name, RecordType.CName, recordClass, cNameRecords, cNameValidationResult, cNameRecords.Min(x => x.TimeToLive)); - - DomainName canonicalName = ((CNameRecord) cNameRecords.First()).CanonicalName; - - List matchingAdditionalRecords = msg.AnswerRecords.Where(x => (x.RecordType == recordType) && (x.RecordClass == recordClass) && x.Name.Equals(canonicalName)).ToList(); - if (matchingAdditionalRecords.Count > 0) - { - DnsSecValidationResult matchingValidationResult = await _validator.ValidateAsync(canonicalName, recordType, recordClass, msg, matchingAdditionalRecords, state, token); - if ((matchingValidationResult == DnsSecValidationResult.Bogus) || (matchingValidationResult == DnsSecValidationResult.Indeterminate)) - throw new DnsSecValidationException("CNAME matching records could not be validated"); - - DnsSecValidationResult validationResult = cNameValidationResult == matchingValidationResult ? cNameValidationResult : DnsSecValidationResult.Unsigned; - _cache.Add(canonicalName, recordType, recordClass, matchingAdditionalRecords, validationResult, matchingAdditionalRecords.Min(x => x.TimeToLive)); - - return new DnsSecResult(matchingAdditionalRecords.OfType().ToList(), validationResult); - } - - var cNameResults = await ResolveAsyncInternal(canonicalName, recordType, recordClass, state, token); - return new DnsSecResult(cNameResults.Records, cNameValidationResult == cNameResults.ValidationResult ? cNameValidationResult : DnsSecValidationResult.Unsigned); - } - - // check for "normal" answer - List answerRecords = msg.AnswerRecords.Where(x => (x.RecordType == recordType) && (x.RecordClass == recordClass) && x.Name.Equals(name)).ToList(); - if (answerRecords.Count > 0) - { - DnsSecValidationResult validationResult = await _validator.ValidateAsync(name, recordType, recordClass, msg, answerRecords, state, token); - if ((validationResult == DnsSecValidationResult.Bogus) || (validationResult == DnsSecValidationResult.Indeterminate)) - throw new DnsSecValidationException("Response records could not be validated"); - - _cache.Add(name, recordType, recordClass, answerRecords, validationResult, answerRecords.Min(x => x.TimeToLive)); - return new DnsSecResult(answerRecords.OfType().ToList(), validationResult); - } - - // check for negative answer - SoaRecord soaRecord = msg.AuthorityRecords - .Where(x => - (x.RecordType == RecordType.Soa) - && (name.Equals(x.Name) || name.IsSubDomainOf(x.Name))) - .OfType() - .FirstOrDefault(); - - if (soaRecord != null) - { - DnsSecValidationResult validationResult = await _validator.ValidateAsync(name, recordType, recordClass, msg, answerRecords, state, token); - if ((validationResult == DnsSecValidationResult.Bogus) || (validationResult == DnsSecValidationResult.Indeterminate)) - throw new DnsSecValidationException("Negative answer could not be validated"); - - _cache.Add(name, recordType, recordClass, new List(), validationResult, soaRecord.NegativeCachingTTL); - return new DnsSecResult(new List(), validationResult); - } - - // authoritive response does not contain answer - throw new Exception("Could not resolve " + name); - } - - - private async Task>> ResolveHostWithTtlAsync(DomainName name, State state, CancellationToken token) - { - List> result = new List>(); - - var aaaaRecords = await ResolveAsyncInternal(name, RecordType.Aaaa, RecordClass.INet, state, token); - result.AddRange(aaaaRecords.Records.Select(x => new Tuple(x.Address, x.TimeToLive))); - - var aRecords = await ResolveAsyncInternal(name, RecordType.A, RecordClass.INet, state, token); - result.AddRange(aRecords.Records.Select(x => new Tuple(x.Address, x.TimeToLive))); - - return result; - } - - private IEnumerable GetBestNameservers(DomainName name) - { - Random rnd = new Random(); - - while (name.LabelCount > 0) - { - List cachedAddresses; - if (_nameserverCache.TryGetAddresses(name, out cachedAddresses)) - { - return cachedAddresses.OrderBy(x => x.AddressFamily == AddressFamily.InterNetworkV6 ? 0 : 1).ThenBy(x => rnd.Next()); - } - - name = name.GetParentName(); - } - - return _resolverHintStore.RootServers.OrderBy(x => x.AddressFamily == AddressFamily.InterNetworkV6 ? 0 : 1).ThenBy(x => rnd.Next()); - } - - Task IInternalDnsSecResolver.ResolveMessageAsync(DomainName name, RecordType recordType, RecordClass recordClass, State state, CancellationToken token) - { - return ResolveMessageAsync(name, recordType, recordClass, state, token); - } - - Task> IInternalDnsSecResolver.ResolveSecureAsync(DomainName name, RecordType recordType, RecordClass recordClass, State state, CancellationToken token) - { - return ResolveAsyncInternal(name, recordType, recordClass, state, token); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/Resolver/DnsSecResolverExtensions.cs b/ARSoft.Tools.Net/Dns/Resolver/DnsSecResolverExtensions.cs deleted file mode 100644 index d6ae662..0000000 --- a/ARSoft.Tools.Net/Dns/Resolver/DnsSecResolverExtensions.cs +++ /dev/null @@ -1,64 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Extension methods for DNSSEC resolvers - /// - public static class DnsSecResolverExtensions - { - /// - /// Queries a dns resolver for specified records. - /// - /// Type of records, that should be returned - /// The resolver instance, that should be used for queries - /// Domain, that should be queried - /// Type the should be queried - /// Class the should be queried - /// The validating result and a list of matching records - public static DnsSecResult ResolveSecure(this IDnsSecResolver resolver, string name, RecordType recordType = RecordType.A, RecordClass recordClass = RecordClass.INet) - where T : DnsRecordBase - { - return resolver.ResolveSecure(DomainName.Parse(name), recordType, recordClass); - } - - /// - /// Queries a dns resolver for specified records as an asynchronous operation. - /// - /// Type of records, that should be returned - /// The resolver instance, that should be used for queries - /// Domain, that should be queried - /// Type the should be queried - /// Class the should be queried - /// The token to monitor cancellation requests - /// A list of matching records - public static Task> ResolveSecureAsync(this IDnsSecResolver resolver, string name, RecordType recordType = RecordType.A, RecordClass recordClass = RecordClass.INet, CancellationToken token = default(CancellationToken)) - where T : DnsRecordBase - { - return resolver.ResolveSecureAsync(DomainName.Parse(name), recordType, recordClass, token); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/Resolver/DnsSecResult.cs b/ARSoft.Tools.Net/Dns/Resolver/DnsSecResult.cs deleted file mode 100644 index ad2f481..0000000 --- a/ARSoft.Tools.Net/Dns/Resolver/DnsSecResult.cs +++ /dev/null @@ -1,45 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System.Collections.Generic; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// The response of a secure DNS resolver - /// - public class DnsSecResult - where T : DnsRecordBase - { - /// - /// The result of the validation process - /// - public DnsSecValidationResult ValidationResult { get; private set; } - - /// - /// The records representing the response - /// - public List Records { get; private set; } - - internal DnsSecResult(List records, DnsSecValidationResult validationResult) - { - Records = records; - ValidationResult = validationResult; - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/Resolver/DnsSecValidationResult.cs b/ARSoft.Tools.Net/Dns/Resolver/DnsSecValidationResult.cs deleted file mode 100644 index aa9c1b4..0000000 --- a/ARSoft.Tools.Net/Dns/Resolver/DnsSecValidationResult.cs +++ /dev/null @@ -1,46 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// The result of a DNSSEC validation - /// - public enum DnsSecValidationResult - { - /// - /// It is indeterminate whether the validation is secure, insecure or bogus - /// - Indeterminate, - - /// - /// The response is signed and fully validated - /// - Signed, - - /// - /// The response is unsigned with a validated OptOut - /// - Unsigned, - - /// - /// The response is bogus - /// - Bogus, - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/Resolver/DnsStubResolver.cs b/ARSoft.Tools.Net/Dns/Resolver/DnsStubResolver.cs deleted file mode 100644 index a7cc6ec..0000000 --- a/ARSoft.Tools.Net/Dns/Resolver/DnsStubResolver.cs +++ /dev/null @@ -1,188 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Stub resolver - /// - /// Defined in - /// RFC 1035 - /// - /// - public class DnsStubResolver : IDnsResolver - { - private readonly DnsClient _dnsClient; - private DnsCache _cache = new DnsCache(); - - /// - /// Provides a new instance using the local configured DNS servers - /// - public DnsStubResolver() - : this(DnsClient.Default) {} - - /// - /// Provides a new instance using a custom DNS client - /// - /// The DNS client to use - public DnsStubResolver(DnsClient dnsClient) - { - _dnsClient = dnsClient; - } - - /// - /// Provides a new instance using a list of custom DNS servers and a default query timeout of 10 seconds - /// - /// The list of servers to use - public DnsStubResolver(IEnumerable servers) - : this(new DnsClient(servers, 10000)) {} - - /// - /// Provides a new instance using a list of custom DNS servers and a custom query timeout - /// - /// The list of servers to use - /// The query timeout in milliseconds - public DnsStubResolver(IEnumerable servers, int queryTimeout) - : this(new DnsClient(servers, queryTimeout)) {} - - /// - /// Queries a the upstream DNS server(s) for specified records. - /// - /// Type of records, that should be returned - /// Domain, that should be queried - /// Type the should be queried - /// Class the should be queried - /// A list of matching records - public List Resolve(DomainName name, RecordType recordType = RecordType.A, RecordClass recordClass = RecordClass.INet) - where T : DnsRecordBase - { - if (name == null) - throw new ArgumentNullException(nameof(name), "Name must be provided"); - - List records; - if (_cache.TryGetRecords(name, recordType, recordClass, out records)) - { - return records; - } - - DnsMessage msg = _dnsClient.Resolve(name, recordType, recordClass); - - if ((msg == null) || ((msg.ReturnCode != ReturnCode.NoError) && (msg.ReturnCode != ReturnCode.NxDomain))) - { - throw new Exception("DNS request failed"); - } - - CNameRecord cName = msg.AnswerRecords.Where(x => (x.RecordType == RecordType.CName) && (x.RecordClass == recordClass) && x.Name.Equals(name)).OfType().FirstOrDefault(); - - if (cName != null) - { - records = msg.AnswerRecords.Where(x => x.Name.Equals(cName.CanonicalName)).OfType().ToList(); - if (records.Count > 0) - { - _cache.Add(name, recordType, recordClass, records, DnsSecValidationResult.Indeterminate, records.Min(x => x.TimeToLive)); - return records; - } - - records = Resolve(cName.CanonicalName, recordType, recordClass); - - if (records.Count > 0) - _cache.Add(name, recordType, recordClass, records, DnsSecValidationResult.Indeterminate, records.Min(x => x.TimeToLive)); - - return records; - } - - records = msg.AnswerRecords.Where(x => x.Name.Equals(name)).OfType().ToList(); - - if (records.Count > 0) - _cache.Add(name, recordType, recordClass, records, DnsSecValidationResult.Indeterminate, records.Min(x => x.TimeToLive)); - - return records; - } - - /// - /// Queries a the upstream DNS server(s) for specified records as an asynchronous operation. - /// - /// Type of records, that should be returned - /// Domain, that should be queried - /// Type the should be queried - /// Class the should be queried - /// The token to monitor cancellation requests - /// A list of matching records - public async Task> ResolveAsync(DomainName name, RecordType recordType = RecordType.A, RecordClass recordClass = RecordClass.INet, CancellationToken token = default(CancellationToken)) - where T : DnsRecordBase - { - if (name == null) - throw new ArgumentNullException(nameof(name), "Name must be provided"); - - List records; - if (_cache.TryGetRecords(name, recordType, recordClass, out records)) - { - return records; - } - - DnsMessage msg = await _dnsClient.ResolveAsync(name, recordType, recordClass, null, token); - - if ((msg == null) || ((msg.ReturnCode != ReturnCode.NoError) && (msg.ReturnCode != ReturnCode.NxDomain))) - { - throw new Exception("DNS request failed"); - } - - CNameRecord cName = msg.AnswerRecords.Where(x => (x.RecordType == RecordType.CName) && (x.RecordClass == recordClass) && x.Name.Equals(name)).OfType().FirstOrDefault(); - - if (cName != null) - { - records = msg.AnswerRecords.Where(x => (x.RecordType == recordType) && (x.RecordClass == recordClass) && x.Name.Equals(cName.CanonicalName)).OfType().ToList(); - if (records.Count > 0) - { - _cache.Add(name, recordType, recordClass, records, DnsSecValidationResult.Indeterminate, Math.Min(cName.TimeToLive, records.Min(x => x.TimeToLive))); - return records; - } - - records = await ResolveAsync(cName.CanonicalName, recordType, recordClass, token); - - if (records.Count > 0) - _cache.Add(name, recordType, recordClass, records, DnsSecValidationResult.Indeterminate, Math.Min(cName.TimeToLive, records.Min(x => x.TimeToLive))); - - return records; - } - - records = msg.AnswerRecords.Where(x => x.Name.Equals(name)).OfType().ToList(); - - if (records.Count > 0) - _cache.Add(name, recordType, recordClass, records, DnsSecValidationResult.Indeterminate, records.Min(x => x.TimeToLive)); - - return records; - } - - /// - /// Clears the record cache - /// - public void ClearCache() - { - _cache = new DnsCache(); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/Resolver/IDnsResolver.cs b/ARSoft.Tools.Net/Dns/Resolver/IDnsResolver.cs deleted file mode 100644 index 3c4ef97..0000000 --- a/ARSoft.Tools.Net/Dns/Resolver/IDnsResolver.cs +++ /dev/null @@ -1,61 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Interface of a DNS resolver - /// - public interface IDnsResolver - { - /// - /// Queries a dns resolver for specified records. - /// - /// Type of records, that should be returned - /// Domain, that should be queried - /// Type the should be queried - /// Class the should be queried - /// A list of matching records - List Resolve(DomainName name, RecordType recordType = RecordType.A, RecordClass recordClass = RecordClass.INet) - where T : DnsRecordBase; - - /// - /// Queries a dns resolver for specified records as an asynchronous operation. - /// - /// Type of records, that should be returned - /// Domain, that should be queried - /// Type the should be queried - /// Class the should be queried - /// The token to monitor cancellation requests - /// A list of matching records - Task> ResolveAsync(DomainName name, RecordType recordType = RecordType.A, RecordClass recordClass = RecordClass.INet, CancellationToken token = default(CancellationToken)) - where T : DnsRecordBase; - - /// - /// Clears the record cache - /// - void ClearCache(); - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/Resolver/IDnsSecResolver.cs b/ARSoft.Tools.Net/Dns/Resolver/IDnsSecResolver.cs deleted file mode 100644 index 7dc440c..0000000 --- a/ARSoft.Tools.Net/Dns/Resolver/IDnsSecResolver.cs +++ /dev/null @@ -1,56 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Interface of a DNSSEC validating resolver - /// - public interface IDnsSecResolver : IDnsResolver - { - /// - /// Queries a dns resolver for specified records. - /// - /// Type of records, that should be returned - /// Domain, that should be queried - /// Type the should be queried - /// Class the should be queried - /// The validating result and a list of matching records - DnsSecResult ResolveSecure(DomainName name, RecordType recordType = RecordType.A, RecordClass recordClass = RecordClass.INet) - where T : DnsRecordBase; - - /// - /// Queries a dns resolver for specified records as an asynchronous operation. - /// - /// Type of records, that should be returned - /// Domain, that should be queried - /// Type the should be queried - /// Class the should be queried - /// The token to monitor cancellation requests - /// A list of matching records - Task> ResolveSecureAsync(DomainName name, RecordType recordType = RecordType.A, RecordClass recordClass = RecordClass.INet, CancellationToken token = default(CancellationToken)) - where T : DnsRecordBase; - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/Resolver/IResolverHintStore.cs b/ARSoft.Tools.Net/Dns/Resolver/IResolverHintStore.cs deleted file mode 100644 index 99c175d..0000000 --- a/ARSoft.Tools.Net/Dns/Resolver/IResolverHintStore.cs +++ /dev/null @@ -1,42 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Interface to provide hints used by resolvers - /// - public interface IResolverHintStore - { - /// - /// List of hints to the root servers - /// - List RootServers { get; } - - /// - /// List of DsRecords of the root zone - /// - List RootKeys { get; } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/Resolver/RecursiveDnsResolver.cs b/ARSoft.Tools.Net/Dns/Resolver/RecursiveDnsResolver.cs deleted file mode 100644 index 4f1f889..0000000 --- a/ARSoft.Tools.Net/Dns/Resolver/RecursiveDnsResolver.cs +++ /dev/null @@ -1,294 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Net.Sockets; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Recursive resolver - /// - /// Defined in - /// RFC 1035 - /// - /// - public class RecursiveDnsResolver : IDnsResolver - { - private class State - { - public int QueryCount; - } - - private DnsCache _cache = new DnsCache(); - private NameserverCache _nameserverCache = new NameserverCache(); - - private readonly IResolverHintStore _resolverHintStore; - - /// - /// Provides a new instance with custom root server hints - /// - /// The resolver hint store with the IP addresses of the root server hints - public RecursiveDnsResolver(IResolverHintStore resolverHintStore = null) - { - _resolverHintStore = resolverHintStore ?? new StaticResolverHintStore(); - IsResponseValidationEnabled = true; - QueryTimeout = 2000; - MaximumReferalCount = 20; - } - - /// - /// Gets or sets a value indicating how much referals for a single query could be performed - /// - public int MaximumReferalCount { get; set; } - - /// - /// Milliseconds after which a query times out. - /// - public int QueryTimeout { get; set; } - - /// - /// Gets or set a value indicating whether the response is validated as described in - /// - /// draft-vixie-dnsext-dns0x20-00 - /// - /// - public bool IsResponseValidationEnabled { get; set; } - - /// - /// Gets or set a value indicating whether the query labels are used for additional validation as described in - /// - /// draft-vixie-dnsext-dns0x20-00 - /// - /// - // ReSharper disable once InconsistentNaming - public bool Is0x20ValidationEnabled { get; set; } - - /// - /// Clears the record cache - /// - public void ClearCache() - { - _cache = new DnsCache(); - _nameserverCache = new NameserverCache(); - } - - /// - /// Resolves specified records. - /// - /// Type of records, that should be returned - /// Domain, that should be queried - /// Type the should be queried - /// Class the should be queried - /// A list of matching records - public List Resolve(DomainName name, RecordType recordType = RecordType.A, RecordClass recordClass = RecordClass.INet) - where T : DnsRecordBase - { - var res = ResolveAsync(name, recordType, recordClass); - res.Wait(); - return res.Result; - } - - /// - /// Resolves specified records as an asynchronous operation. - /// - /// Type of records, that should be returned - /// Domain, that should be queried - /// Type the should be queried - /// Class the should be queried - /// The token to monitor cancellation requests - /// A list of matching records - public Task> ResolveAsync(DomainName name, RecordType recordType = RecordType.A, RecordClass recordClass = RecordClass.INet, CancellationToken token = default(CancellationToken)) - where T : DnsRecordBase - { - if (name == null) - throw new ArgumentNullException(nameof(name), "Name must be provided"); - - return ResolveAsyncInternal(name, recordType, recordClass, new State(), token); - } - - private async Task ResolveMessageAsync(DomainName name, RecordType recordType, RecordClass recordClass, State state, CancellationToken token) - { - for (; state.QueryCount <= MaximumReferalCount; state.QueryCount++) - { - DnsMessage msg = await new DnsClient(GetBestNameservers(recordType == RecordType.Ds ? name.GetParentName() : name), QueryTimeout) - { - IsResponseValidationEnabled = IsResponseValidationEnabled, - Is0x20ValidationEnabled = Is0x20ValidationEnabled - }.ResolveAsync(name, recordType, recordClass, new DnsQueryOptions() - { - IsRecursionDesired = false, - IsEDnsEnabled = true - }, token); - - if ((msg != null) && ((msg.ReturnCode == ReturnCode.NoError) || (msg.ReturnCode == ReturnCode.NxDomain))) - { - if (msg.IsAuthoritiveAnswer) - return msg; - - List referalRecords = msg.AuthorityRecords - .Where(x => - (x.RecordType == RecordType.Ns) - && (name.Equals(x.Name) || name.IsSubDomainOf(x.Name))) - .OfType() - .ToList(); - - if (referalRecords.Count > 0) - { - if (referalRecords.GroupBy(x => x.Name).Count() == 1) - { - var newServers = referalRecords.Join(msg.AdditionalRecords.OfType(), x => x.NameServer, x => x.Name, (x, y) => new { y.Address, TimeToLive = Math.Min(x.TimeToLive, y.TimeToLive) }).ToList(); - - if (newServers.Count > 0) - { - DomainName zone = referalRecords.First().Name; - - foreach (var newServer in newServers) - { - _nameserverCache.Add(zone, newServer.Address, newServer.TimeToLive); - } - - continue; - } - else - { - NsRecord firstReferal = referalRecords.First(); - - var newLookedUpServers = await ResolveHostWithTtlAsync(firstReferal.NameServer, state, token); - - foreach (var newServer in newLookedUpServers) - { - _nameserverCache.Add(firstReferal.Name, newServer.Item1, Math.Min(firstReferal.TimeToLive, newServer.Item2)); - } - - if (newLookedUpServers.Count > 0) - continue; - } - } - } - - // Response of best known server is not authoritive and has no referrals --> No chance to get a result - throw new Exception("Could not resolve " + name); - } - } - - // query limit reached without authoritive answer - throw new Exception("Could not resolve " + name); - } - - private async Task> ResolveAsyncInternal(DomainName name, RecordType recordType, RecordClass recordClass, State state, CancellationToken token) - where T : DnsRecordBase - { - List cachedResults; - if (_cache.TryGetRecords(name, recordType, recordClass, out cachedResults)) - { - return cachedResults; - } - - List cachedCNames; - if (_cache.TryGetRecords(name, RecordType.CName, recordClass, out cachedCNames)) - { - return await ResolveAsyncInternal(cachedCNames.First().CanonicalName, recordType, recordClass, state, token); - } - - DnsMessage msg = await ResolveMessageAsync(name, recordType, recordClass, state, token); - - // check for cname - List cNameRecords = msg.AnswerRecords.Where(x => (x.RecordType == RecordType.CName) && (x.RecordClass == recordClass) && x.Name.Equals(name)).ToList(); - if (cNameRecords.Count > 0) - { - _cache.Add(name, RecordType.CName, recordClass, cNameRecords, DnsSecValidationResult.Indeterminate, cNameRecords.Min(x => x.TimeToLive)); - - DomainName canonicalName = ((CNameRecord) cNameRecords.First()).CanonicalName; - - List matchingAdditionalRecords = msg.AnswerRecords.Where(x => (x.RecordType == recordType) && (x.RecordClass == recordClass) && x.Name.Equals(canonicalName)).ToList(); - if (matchingAdditionalRecords.Count > 0) - { - _cache.Add(canonicalName, recordType, recordClass, matchingAdditionalRecords, DnsSecValidationResult.Indeterminate, matchingAdditionalRecords.Min(x => x.TimeToLive)); - return matchingAdditionalRecords.OfType().ToList(); - } - - return await ResolveAsyncInternal(canonicalName, recordType, recordClass, state, token); - } - - // check for "normal" answer - List answerRecords = msg.AnswerRecords.Where(x => (x.RecordType == recordType) && (x.RecordClass == recordClass) && x.Name.Equals(name)).ToList(); - if (answerRecords.Count > 0) - { - _cache.Add(name, recordType, recordClass, answerRecords, DnsSecValidationResult.Indeterminate, answerRecords.Min(x => x.TimeToLive)); - return answerRecords.OfType().ToList(); - } - - // check for negative answer - SoaRecord soaRecord = msg.AuthorityRecords - .Where(x => - (x.RecordType == RecordType.Soa) - && (name.Equals(x.Name) || name.IsSubDomainOf(x.Name))) - .OfType() - .FirstOrDefault(); - - if (soaRecord != null) - { - _cache.Add(name, recordType, recordClass, new List(), DnsSecValidationResult.Indeterminate, soaRecord.NegativeCachingTTL); - return new List(); - } - - // authoritive response does not contain answer - throw new Exception("Could not resolve " + name); - } - - private async Task>> ResolveHostWithTtlAsync(DomainName name, State state, CancellationToken token) - { - List> result = new List>(); - - var aaaaRecords = await ResolveAsyncInternal(name, RecordType.Aaaa, RecordClass.INet, state, token); - result.AddRange(aaaaRecords.Select(x => new Tuple(x.Address, x.TimeToLive))); - - var aRecords = await ResolveAsyncInternal(name, RecordType.A, RecordClass.INet, state, token); - result.AddRange(aRecords.Select(x => new Tuple(x.Address, x.TimeToLive))); - - return result; - } - - private IEnumerable GetBestNameservers(DomainName name) - { - Random rnd = new Random(); - - while (name.LabelCount > 0) - { - List cachedAddresses; - if (_nameserverCache.TryGetAddresses(name, out cachedAddresses)) - { - return cachedAddresses.OrderBy(x => x.AddressFamily == AddressFamily.InterNetworkV6 ? 0 : 1).ThenBy(x => rnd.Next()); - } - - name = name.GetParentName(); - } - - return _resolverHintStore.RootServers.OrderBy(x => x.AddressFamily == AddressFamily.InterNetworkV6 ? 0 : 1).ThenBy(x => rnd.Next()); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/Resolver/SelfValidatingDnsSecStubResolver.cs b/ARSoft.Tools.Net/Dns/Resolver/SelfValidatingDnsSecStubResolver.cs deleted file mode 100644 index e10f5ea..0000000 --- a/ARSoft.Tools.Net/Dns/Resolver/SelfValidatingDnsSecStubResolver.cs +++ /dev/null @@ -1,220 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Self validating security aware stub resolver - /// - /// Defined in - /// RFC 4033, - /// RFC 4034 - /// and RFC 4035 - /// - /// - public class SelfValidatingInternalDnsSecStubResolver : IDnsSecResolver, IInternalDnsSecResolver - { - private readonly DnsClient _dnsClient; - private DnsCache _cache; - private readonly DnsSecValidator _validator; - - /// - /// Provides a new instance using a custom DNS client - /// - /// The DNS client to use - /// The resolver hint store with the root DnsKey hints - public SelfValidatingInternalDnsSecStubResolver(DnsClient dnsClient = null, IResolverHintStore resolverHintStore = null) - { - _dnsClient = dnsClient ?? DnsClient.Default; - _cache = new DnsCache(); - _validator = new DnsSecValidator(this, resolverHintStore ?? new StaticResolverHintStore()); - } - - /// - /// Provides a new instance using a list of custom DNS servers and a default query timeout of 10 seconds - /// - /// The list of servers to use - public SelfValidatingInternalDnsSecStubResolver(IEnumerable servers) - : this(servers, 10000) {} - - /// - /// Provides a new instance using a list of custom DNS servers and a custom query timeout - /// - /// The list of servers to use - /// The query timeout in milliseconds - public SelfValidatingInternalDnsSecStubResolver(IEnumerable servers, int queryTimeout) - : this(new DnsClient(servers, queryTimeout)) {} - - /// - /// Resolves specified records. - /// - /// Type of records, that should be returned - /// Domain, that should be queried - /// Type the should be queried - /// Class the should be queried - /// A list of matching records - public List Resolve(DomainName name, RecordType recordType = RecordType.A, RecordClass recordClass = RecordClass.INet) - where T : DnsRecordBase - { - var res = ResolveAsync(name, recordType, recordClass); - res.Wait(); - return res.Result; - } - - /// - /// Resolves specified records as an asynchronous operation. - /// - /// Type of records, that should be returned - /// Domain, that should be queried - /// Type the should be queried - /// Class the should be queried - /// The token to monitor cancellation requests - /// A list of matching records - public async Task> ResolveAsync(DomainName name, RecordType recordType = RecordType.A, RecordClass recordClass = RecordClass.INet, CancellationToken token = default(CancellationToken)) - where T : DnsRecordBase - { - if (name == null) - throw new ArgumentNullException(nameof(name), "Name must be provided"); - - var res = await ResolveSecureAsync(name, recordType, recordClass, token); - - return res.Records; - } - - /// - /// Resolves specified records. - /// - /// Type of records, that should be returned - /// Domain, that should be queried - /// Type the should be queried - /// Class the should be queried - /// A list of matching records - public DnsSecResult ResolveSecure(DomainName name, RecordType recordType = RecordType.A, RecordClass recordClass = RecordClass.INet) - where T : DnsRecordBase - { - var res = ResolveSecureAsync(name, recordType, recordClass); - res.Wait(); - return res.Result; - } - - /// - /// Resolves specified records as an asynchronous operation. - /// - /// Type of records, that should be returned - /// Domain, that should be queried - /// Type the should be queried - /// Class the should be queried - /// The token to monitor cancellation requests - /// A list of matching records - public async Task> ResolveSecureAsync(DomainName name, RecordType recordType = RecordType.A, RecordClass recordClass = RecordClass.INet, CancellationToken token = default(CancellationToken)) - where T : DnsRecordBase - { - if (name == null) - throw new ArgumentNullException(nameof(name), "Name must be provided"); - - DnsCacheRecordList cacheResult; - if (_cache.TryGetRecords(name, recordType, recordClass, out cacheResult)) - { - return new DnsSecResult(cacheResult, cacheResult.ValidationResult); - } - - DnsMessage msg = await _dnsClient.ResolveAsync(name, recordType, recordClass, new DnsQueryOptions() - { - IsEDnsEnabled = true, - IsDnsSecOk = true, - IsCheckingDisabled = true, - IsRecursionDesired = true - }, token); - - if ((msg == null) || ((msg.ReturnCode != ReturnCode.NoError) && (msg.ReturnCode != ReturnCode.NxDomain))) - { - throw new Exception("DNS request failed"); - } - - DnsSecValidationResult validationResult; - - CNameRecord cName = msg.AnswerRecords.Where(x => (x.RecordType == RecordType.CName) && (x.RecordClass == recordClass) && x.Name.Equals(name)).OfType().FirstOrDefault(); - - if (cName != null) - { - DnsSecValidationResult cNameValidationResult = await _validator.ValidateAsync(name, RecordType.CName, recordClass, msg, new List() { cName }, null, token); - if ((cNameValidationResult == DnsSecValidationResult.Bogus) || (cNameValidationResult == DnsSecValidationResult.Indeterminate)) - throw new DnsSecValidationException("CNAME record could not be validated"); - - var records = msg.AnswerRecords.Where(x => (x.RecordType == recordType) && (x.RecordClass == recordClass) && x.Name.Equals(cName.CanonicalName)).OfType().ToList(); - if (records.Count > 0) - { - DnsSecValidationResult recordsValidationResult = await _validator.ValidateAsync(cName.CanonicalName, recordType, recordClass, msg, records, null, token); - if ((recordsValidationResult == DnsSecValidationResult.Bogus) || (recordsValidationResult == DnsSecValidationResult.Indeterminate)) - throw new DnsSecValidationException("CNAME matching records could not be validated"); - - validationResult = cNameValidationResult == recordsValidationResult ? cNameValidationResult : DnsSecValidationResult.Unsigned; - _cache.Add(name, recordType, recordClass, records, validationResult, Math.Min(cName.TimeToLive, records.Min(x => x.TimeToLive))); - - return new DnsSecResult(records, validationResult); - } - - var cNameResults = await ResolveSecureAsync(cName.CanonicalName, recordType, recordClass, token); - validationResult = cNameValidationResult == cNameResults.ValidationResult ? cNameValidationResult : DnsSecValidationResult.Unsigned; - - if (cNameResults.Records.Count > 0) - _cache.Add(name, recordType, recordClass, cNameResults.Records, validationResult, Math.Min(cName.TimeToLive, cNameResults.Records.Min(x => x.TimeToLive))); - - return new DnsSecResult(cNameResults.Records, validationResult); - } - - List res = msg.AnswerRecords.Where(x => (x.RecordType == recordType) && (x.RecordClass == recordClass) && x.Name.Equals(name)).OfType().ToList(); - - validationResult = await _validator.ValidateAsync(name, recordType, recordClass, msg, res, null, token); - - if ((validationResult == DnsSecValidationResult.Bogus) || (validationResult == DnsSecValidationResult.Indeterminate)) - throw new DnsSecValidationException("Response records could not be validated"); - - if (res.Count > 0) - _cache.Add(name, recordType, recordClass, res, validationResult, res.Min(x => x.TimeToLive)); - - return new DnsSecResult(res, validationResult); - } - - /// - /// Clears the record cache - /// - public void ClearCache() - { - _cache = new DnsCache(); - } - - Task IInternalDnsSecResolver.ResolveMessageAsync(DomainName name, RecordType recordType, RecordClass recordClass, object state, CancellationToken token) - { - return _dnsClient.ResolveAsync(name, RecordType.Ds, recordClass, new DnsQueryOptions() { IsEDnsEnabled = true, IsDnsSecOk = true, IsCheckingDisabled = true, IsRecursionDesired = true }, token); - } - - Task> IInternalDnsSecResolver.ResolveSecureAsync(DomainName name, RecordType recordType, RecordClass recordClass, object state, CancellationToken token) - { - return ResolveSecureAsync(name, recordType, recordClass, token); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/Resolver/StaticResolverHintStore.cs b/ARSoft.Tools.Net/Dns/Resolver/StaticResolverHintStore.cs deleted file mode 100644 index 5312fa5..0000000 --- a/ARSoft.Tools.Net/Dns/Resolver/StaticResolverHintStore.cs +++ /dev/null @@ -1,101 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Net; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Implementation of IResolverHintStore, which uses statically linked hints - /// - public class StaticResolverHintStore : IResolverHintStore - { - private static readonly List _rootServers = new List() - { - // a.root-servers.net - IPAddress.Parse("198.41.0.4"), - IPAddress.Parse("2001:503:ba3e::2:30"), - - // b.root-servers.net - IPAddress.Parse("192.228.79.201"), - IPAddress.Parse("2001:500:200::b"), - - // c.root-servers.net - IPAddress.Parse("192.33.4.12"), - IPAddress.Parse("2001:500:2::c"), - - // d.root-servers.net - IPAddress.Parse("199.7.91.13"), - IPAddress.Parse("2001:500:2d::d"), - - // e.root-servers.net - IPAddress.Parse("192.203.230.10"), - IPAddress.Parse("2001:500:a8::e"), - - // f.root-servers.net - IPAddress.Parse("192.5.5.241"), - IPAddress.Parse("2001:500:2f::f"), - - // g.root-servers.net - IPAddress.Parse("192.112.36.4"), - IPAddress.Parse("2001:500:12::d0d"), - - // h.root-servers.net - IPAddress.Parse("198.97.190.53"), - IPAddress.Parse("2001:500:1::53"), - - // i.root-servers.net - IPAddress.Parse("192.36.148.17"), - IPAddress.Parse("2001:7fe::53"), - - // j.root-servers.net - IPAddress.Parse("192.58.128.30"), - IPAddress.Parse("2001:503:c27::2:30"), - - // k.root-servers.net - IPAddress.Parse("193.0.14.129"), - IPAddress.Parse("2001:7fd::1"), - - // l.root-servers.net - IPAddress.Parse("199.7.83.42"), - IPAddress.Parse("2001:500:9f::42"), - - // m.root-servers.net - IPAddress.Parse("202.12.27.33"), - IPAddress.Parse("2001:dc3::35") - }; - - /// - /// List of hints to the root servers - /// - public List RootServers => _rootServers; - - private static readonly List _rootKeys = new List() - { - new DsRecord(DomainName.Root, RecordClass.INet, 0, 19036, DnsSecAlgorithm.RsaSha256, DnsSecDigestType.Sha256, "49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5".FromBase16String()), - new DsRecord(DomainName.Root, RecordClass.INet, 0, 20326, DnsSecAlgorithm.RsaSha256, DnsSecDigestType.Sha256, "E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D".FromBase16String()), - }; - - /// - /// List of DsRecords of the root zone - /// - public List RootKeys => _rootKeys; - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/Resolver/UpdateableResolverHintStoreBase.cs b/ARSoft.Tools.Net/Dns/Resolver/UpdateableResolverHintStoreBase.cs deleted file mode 100644 index ab271c6..0000000 --- a/ARSoft.Tools.Net/Dns/Resolver/UpdateableResolverHintStoreBase.cs +++ /dev/null @@ -1,117 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Base class for a ResolverHintStore, which has an updateable local storage for the hints - /// - public abstract class UpdateableResolverHintStoreBase : IResolverHintStore - { - private bool _isInitiated; - private List _rootServers; - private List _rootKeys; - - /// - /// List of hints to the root servers - /// - public List RootServers - { - get - { - EnsureInit(); - return _rootServers; - } - private set { _rootServers = value; } - } - - /// - /// List of DsRecords of the root zone - /// - public List RootKeys - { - get - { - EnsureInit(); - return _rootKeys; - } - private set { _rootKeys = value; } - } - - /// - /// Forces to update all hints using the given resolver - /// - /// The resolver to use for resolving the new hints - public void Update(IDnsResolver resolver) - { - Zone zone = new Zone(DomainName.Root); - - var nameServer = resolver.Resolve(DomainName.Root, RecordType.Ns); - zone.AddRange(nameServer); - - foreach (var nsRecord in nameServer) - { - zone.AddRange(resolver.Resolve(nsRecord.NameServer, RecordType.A)); - zone.AddRange(resolver.Resolve(nsRecord.NameServer, RecordType.Aaaa)); - } - - zone.AddRange(resolver.Resolve(DomainName.Root, RecordType.DnsKey).Where(x => x.IsSecureEntryPoint)); - - LoadZoneInternal(zone); - - Save(zone); - } - - private void EnsureInit() - { - if (!_isInitiated) - { - Zone zone = Load(); - - LoadZoneInternal(zone); - - _isInitiated = true; - } - } - - private void LoadZoneInternal(Zone zone) - { - var nameServers = zone.OfType().Where(x => x.Name == DomainName.Root).Select(x => x.NameServer); - RootServers = zone.Where(x => x.RecordType == RecordType.A || x.RecordType == RecordType.Aaaa).Join(nameServers, x => x.Name, x => x, (x, y) => ((IAddressRecord) x).Address).ToList(); - RootKeys = zone.OfType().Where(x => (x.Name == DomainName.Root) && x.IsSecureEntryPoint).Select(x => new DsRecord(x, x.TimeToLive, DnsSecDigestType.Sha256)).ToList(); - } - - /// - /// Saves the hints to a local storage - /// - /// - protected abstract void Save(Zone zone); - - /// - /// Loads the hints from a local storage - /// - /// - protected abstract Zone Load(); - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/Resolver/ZoneFileResolverHintStore.cs b/ARSoft.Tools.Net/Dns/Resolver/ZoneFileResolverHintStore.cs deleted file mode 100644 index 0e8320a..0000000 --- a/ARSoft.Tools.Net/Dns/Resolver/ZoneFileResolverHintStore.cs +++ /dev/null @@ -1,70 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Updateable Resolver HintStore using a local zone file for the hints - /// - public class ZoneFileResolverHintStore : UpdateableResolverHintStoreBase - { - private readonly string _fileName; - - /// - /// Creates a new instance of the ZoneFileResolverHintStore class - /// - /// The path to the local zone file containing the hints - public ZoneFileResolverHintStore(string fileName) - { - _fileName = fileName; - } - - /// - /// Saves the hints to the local file - /// - /// The zone to save - protected override void Save(Zone zone) - { - using (StreamWriter writer = new StreamWriter(_fileName)) - { - foreach (DnsRecordBase record in zone) - { - writer.WriteLine(record.ToString()); - } - } - } - - /// - /// Loads the hints from the local file - /// - /// - protected override Zone Load() - { - if (!File.Exists(_fileName)) - throw new FileNotFoundException(); - - return Zone.ParseMasterFile(DomainName.Root, _fileName); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/TSig/TSigAlgorithm.cs b/ARSoft.Tools.Net/Dns/TSig/TSigAlgorithm.cs deleted file mode 100644 index 96cff96..0000000 --- a/ARSoft.Tools.Net/Dns/TSig/TSigAlgorithm.cs +++ /dev/null @@ -1,82 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Type of algorithm - /// - // ReSharper disable once InconsistentNaming - public enum TSigAlgorithm - { - /// - /// Unknown - /// - Unknown, - - /// - /// MD5 - /// - /// Defined in - /// RFC 2845 - /// - /// - Md5, - - /// - /// SHA-1 - /// - /// Defined in - /// RFC 4635 - /// - /// - Sha1, // RFC4635 - - /// - /// SHA-256 - /// - /// Defined in - /// RFC 4635 - /// - /// - Sha256, - - /// - /// SHA-384 - /// - /// Defined in - /// RFC 4635 - /// - /// - Sha384, - - /// - /// SHA-512 - /// - /// Defined in - /// RFC 4635 - /// - /// - Sha512, - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/TSig/TSigAlgorithmHelper.cs b/ARSoft.Tools.Net/Dns/TSig/TSigAlgorithmHelper.cs deleted file mode 100644 index bd416a0..0000000 --- a/ARSoft.Tools.Net/Dns/TSig/TSigAlgorithmHelper.cs +++ /dev/null @@ -1,110 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Security.Cryptography; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - // ReSharper disable once InconsistentNaming - internal class TSigAlgorithmHelper - { - public static DomainName GetDomainName(TSigAlgorithm algorithm) - { - switch (algorithm) - { - case TSigAlgorithm.Md5: - return DomainName.Parse("hmac-md5.sig-alg.reg.int"); - case TSigAlgorithm.Sha1: - return DomainName.Parse("hmac-sha1"); - case TSigAlgorithm.Sha256: - return DomainName.Parse("hmac-sha256"); - case TSigAlgorithm.Sha384: - return DomainName.Parse("hmac-sha384"); - case TSigAlgorithm.Sha512: - return DomainName.Parse("hmac-sha512"); - - default: - return null; - } - } - - public static TSigAlgorithm GetAlgorithmByName(DomainName name) - { - switch (name.ToString().ToLower()) - { - case "hmac-md5.sig-alg.reg.int": - return TSigAlgorithm.Md5; - case "hmac-sha1": - return TSigAlgorithm.Sha1; - case "hmac-sha256": - return TSigAlgorithm.Sha256; - case "hmac-sha384": - return TSigAlgorithm.Sha384; - case "hmac-sha512": - return TSigAlgorithm.Sha512; - - default: - return TSigAlgorithm.Unknown; - } - } - - public static KeyedHashAlgorithm GetHashAlgorithm(TSigAlgorithm algorithm) - { - switch (algorithm) - { - case TSigAlgorithm.Md5: - return new HMACMD5(); - case TSigAlgorithm.Sha1: - return new HMACSHA1(); - case TSigAlgorithm.Sha256: - return new HMACSHA256(); - case TSigAlgorithm.Sha384: - return new HMACSHA384(); - case TSigAlgorithm.Sha512: - return new HMACSHA512(); - - default: - return null; - } - } - - internal static int GetHashSize(TSigAlgorithm algorithm) - { - switch (algorithm) - { - case TSigAlgorithm.Md5: - return 16; - case TSigAlgorithm.Sha1: - return 20; - case TSigAlgorithm.Sha256: - return 32; - case TSigAlgorithm.Sha384: - return 48; - case TSigAlgorithm.Sha512: - return 64; - - default: - return 0; - } - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/TSig/TSigRecord.cs b/ARSoft.Tools.Net/Dns/TSig/TSigRecord.cs deleted file mode 100644 index a38323f..0000000 --- a/ARSoft.Tools.Net/Dns/TSig/TSigRecord.cs +++ /dev/null @@ -1,206 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - /// - /// Transaction signature record - /// - /// Defined in - /// RFC 2845 - /// - /// - // ReSharper disable once InconsistentNaming - public class TSigRecord : DnsRecordBase - { - /// - /// Algorithm of the key - /// - public TSigAlgorithm Algorithm { get; private set; } - - /// - /// Time when the data was signed - /// - public DateTime TimeSigned { get; internal set; } - - /// - /// Timespan errors permitted - /// - public TimeSpan Fudge { get; private set; } - - /// - /// MAC defined by algorithm - /// - public byte[] Mac { get; internal set; } - - /// - /// Original ID of message - /// - public ushort OriginalID { get; private set; } - - /// - /// Error field - /// - public ReturnCode Error { get; internal set; } - - /// - /// Binary other data - /// - public byte[] OtherData { get; internal set; } - - /// - /// Binary data of the key - /// - public byte[] KeyData { get; internal set; } - - /// - /// Result of validation of record - /// - public ReturnCode ValidationResult { get; internal set; } - - internal TSigRecord() {} - - /// - /// Creates a new instance of the TSigRecord class - /// - /// Name of the record - /// Algorithm of the key - /// Time when the data was signed - /// Timespan errors permitted - /// Original ID of message - /// Error field - /// Binary other data - /// Binary data of the key - public TSigRecord(DomainName name, TSigAlgorithm algorithm, DateTime timeSigned, TimeSpan fudge, ushort originalID, ReturnCode error, byte[] otherData, byte[] keyData) - : base(name, RecordType.TSig, RecordClass.Any, 0) - { - Algorithm = algorithm; - TimeSigned = timeSigned; - Fudge = fudge; - Mac = new byte[] { }; - OriginalID = originalID; - Error = error; - OtherData = otherData ?? new byte[] { }; - KeyData = keyData; - } - - internal override void ParseRecordData(byte[] resultData, int startPosition, int length) - { - Algorithm = TSigAlgorithmHelper.GetAlgorithmByName(DnsMessageBase.ParseDomainName(resultData, ref startPosition)); - TimeSigned = ParseDateTime(resultData, ref startPosition); - Fudge = TimeSpan.FromSeconds(DnsMessageBase.ParseUShort(resultData, ref startPosition)); - int macSize = DnsMessageBase.ParseUShort(resultData, ref startPosition); - Mac = DnsMessageBase.ParseByteData(resultData, ref startPosition, macSize); - OriginalID = DnsMessageBase.ParseUShort(resultData, ref startPosition); - Error = (ReturnCode) DnsMessageBase.ParseUShort(resultData, ref startPosition); - int otherDataSize = DnsMessageBase.ParseUShort(resultData, ref startPosition); - OtherData = DnsMessageBase.ParseByteData(resultData, ref startPosition, otherDataSize); - } - - internal override void ParseRecordData(DomainName origin, string[] stringRepresentation) - { - throw new NotSupportedException(); - } - - internal override string RecordDataToString() - { - return TSigAlgorithmHelper.GetDomainName(Algorithm) - + " " + (int) (TimeSigned - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds - + " " + (ushort) Fudge.TotalSeconds - + " " + Mac.Length - + " " + Mac.ToBase64String() - + " " + OriginalID - + " " + (ushort) Error - + " " + OtherData.Length - + " " + OtherData.ToBase64String(); - } - - protected internal override int MaximumRecordDataLength => TSigAlgorithmHelper.GetDomainName(Algorithm).MaximumRecordDataLength + 18 + TSigAlgorithmHelper.GetHashSize(Algorithm) + OtherData.Length; - - internal void Encode(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, byte[] mac) - { - EncodeRecordHeader(messageData, offset, ref currentPosition, domainNames, false); - int recordDataOffset = currentPosition + 2; - EncodeRecordData(messageData, offset, ref recordDataOffset, mac); - EncodeRecordLength(messageData, offset, ref currentPosition, domainNames, recordDataOffset); - } - - private void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, byte[] mac) - { - DnsMessageBase.EncodeDomainName(messageData, offset, ref currentPosition, TSigAlgorithmHelper.GetDomainName(Algorithm), null, false); - EncodeDateTime(messageData, ref currentPosition, TimeSigned); - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, (ushort) Fudge.TotalSeconds); - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, (ushort) mac.Length); - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, mac); - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, OriginalID); - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, (ushort) Error); - DnsMessageBase.EncodeUShort(messageData, ref currentPosition, (ushort) OtherData.Length); - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, OtherData); - } - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames, bool useCanonical) - { - EncodeRecordData(messageData, offset, ref currentPosition, Mac); - } - - internal static void EncodeDateTime(byte[] buffer, ref int currentPosition, DateTime value) - { - long timeStamp = (long) (value.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds; - - if (BitConverter.IsLittleEndian) - { - buffer[currentPosition++] = (byte) ((timeStamp >> 40) & 0xff); - buffer[currentPosition++] = (byte) ((timeStamp >> 32) & 0xff); - buffer[currentPosition++] = (byte) (timeStamp >> 24 & 0xff); - buffer[currentPosition++] = (byte) ((timeStamp >> 16) & 0xff); - buffer[currentPosition++] = (byte) ((timeStamp >> 8) & 0xff); - buffer[currentPosition++] = (byte) (timeStamp & 0xff); - } - else - { - buffer[currentPosition++] = (byte) (timeStamp & 0xff); - buffer[currentPosition++] = (byte) ((timeStamp >> 8) & 0xff); - buffer[currentPosition++] = (byte) ((timeStamp >> 16) & 0xff); - buffer[currentPosition++] = (byte) ((timeStamp >> 24) & 0xff); - buffer[currentPosition++] = (byte) ((timeStamp >> 32) & 0xff); - buffer[currentPosition++] = (byte) ((timeStamp >> 40) & 0xff); - } - } - - private static DateTime ParseDateTime(byte[] buffer, ref int currentPosition) - { - long timeStamp; - - if (BitConverter.IsLittleEndian) - { - timeStamp = ((buffer[currentPosition++] << 40) | (buffer[currentPosition++] << 32) | buffer[currentPosition++] << 24 | (buffer[currentPosition++] << 16) | (buffer[currentPosition++] << 8) | buffer[currentPosition++]); - } - else - { - timeStamp = (buffer[currentPosition++] | (buffer[currentPosition++] << 8) | (buffer[currentPosition++] << 16) | (buffer[currentPosition++] << 24) | (buffer[currentPosition++] << 32) | (buffer[currentPosition++] << 40)); - } - - return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(timeStamp).ToLocalTime(); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/Zone.cs b/ARSoft.Tools.Net/Dns/Zone.cs index f5339a3..6e9900a 100644 --- a/ARSoft.Tools.Net/Dns/Zone.cs +++ b/ARSoft.Tools.Net/Dns/Zone.cs @@ -21,10 +21,9 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; -using Org.BouncyCastle.Crypto.Prng; -using Org.BouncyCastle.Security; namespace ARSoft.Tools.Net.Dns { @@ -33,9 +32,7 @@ namespace ARSoft.Tools.Net.Dns /// public class Zone : ICollection { - private static readonly SecureRandom _secureRandom = new SecureRandom(new CryptoApiRandomGenerator()); - - private static readonly Regex _commentRemoverRegex = new Regex(@"^(?(\\\""|[^\""]|(?(\\\""|[^\""]|(? _records; @@ -365,201 +362,7 @@ private static string ReadLineWithoutComment(StreamReader reader) // ReSharper disable once AssignNullToNotNullAttribute return _commentRemoverRegex.Match(line).Groups["data"].Value; } - - /// - /// Signs a zone - /// - /// A list of keys to sign the zone - /// The inception date of the signatures - /// The expiration date of the signatures - /// The NSEC3 algorithm (or 0 when NSEC should be used) - /// The number of iterations when NSEC3 is used - /// The salt when NSEC3 is used - /// true, of NSEC3 OptOut should be used for delegations without DS record - /// A signed zone - public Zone Sign(List keys, DateTime inception, DateTime expiration, NSec3HashAlgorithm nsec3Algorithm = 0, int nsec3Iterations = 10, byte[] nsec3Salt = null, bool nsec3OptOut = false) - { - if ((keys == null) || (keys.Count == 0)) - throw new Exception("No DNS Keys were provided"); - - if (!keys.All(x => x.IsZoneKey)) - throw new Exception("No DNS key with Zone Key Flag were provided"); - - if (keys.Any(x => (x.PrivateKey == null) || (x.PrivateKey.Length == 0))) - throw new Exception("For at least one DNS key no Private Key was provided"); - - if (keys.Any(x => (x.Protocol != 3) || ((nsec3Algorithm != 0) ? !x.Algorithm.IsCompatibleWithNSec3() : !x.Algorithm.IsCompatibleWithNSec()))) - throw new Exception("At least one invalid DNS key was provided"); - - List keySigningKeys = keys.Where(x => x.IsSecureEntryPoint).ToList(); - List zoneSigningKeys = keys.Where(x => !x.IsSecureEntryPoint).ToList(); - - if (nsec3Algorithm == 0) - { - return SignWithNSec(inception, expiration, zoneSigningKeys, keySigningKeys); - } - else - { - return SignWithNSec3(inception, expiration, zoneSigningKeys, keySigningKeys, nsec3Algorithm, nsec3Iterations, nsec3Salt, nsec3OptOut); - } - } - - private Zone SignWithNSec(DateTime inception, DateTime expiration, List zoneSigningKeys, List keySigningKeys) - { - var soaRecord = _records.OfType().First(); - var subZones = _records.Where(x => (x.RecordType == RecordType.Ns) && (x.Name != Name)).Select(x => x.Name).Distinct().ToList(); - var glueRecords = _records.Where(x => subZones.Any(y => x.Name.IsSubDomainOf(y))).ToList(); - var recordsByName = _records.Except(glueRecords).Union(zoneSigningKeys).Union(keySigningKeys).GroupBy(x => x.Name).Select(x => new Tuple>(x.Key, x.OrderBy(y => y.RecordType == RecordType.Soa ? -1 : (int) y.RecordType).ToList())).OrderBy(x => x.Item1).ToList(); - - Zone res = new Zone(Name, Count * 3); - - for (int i = 0; i < recordsByName.Count; i++) - { - List recordTypes = new List(); - - DomainName currentName = recordsByName[i].Item1; - - foreach (var recordsByType in recordsByName[i].Item2.GroupBy(x => x.RecordType)) - { - List records = recordsByType.ToList(); - - recordTypes.Add(recordsByType.Key); - res.AddRange(records); - - // do not sign nameserver delegations for sub zones - if ((records[0].RecordType == RecordType.Ns) && (currentName != Name)) - continue; - - recordTypes.Add(RecordType.RrSig); - - foreach (var key in zoneSigningKeys) - { - res.Add(new RrSigRecord(records, key, inception, expiration)); - } - if (records[0].RecordType == RecordType.DnsKey) - { - foreach (var key in keySigningKeys) - { - res.Add(new RrSigRecord(records, key, inception, expiration)); - } - } - } - - recordTypes.Add(RecordType.NSec); - - NSecRecord nsecRecord = new NSecRecord(recordsByName[i].Item1, soaRecord.RecordClass, soaRecord.NegativeCachingTTL, recordsByName[(i + 1) % recordsByName.Count].Item1, recordTypes); - res.Add(nsecRecord); - - foreach (var key in zoneSigningKeys) - { - res.Add(new RrSigRecord(new List() { nsecRecord }, key, inception, expiration)); - } - } - - res.AddRange(glueRecords); - - return res; - } - - private Zone SignWithNSec3(DateTime inception, DateTime expiration, List zoneSigningKeys, List keySigningKeys, NSec3HashAlgorithm nsec3Algorithm, int nsec3Iterations, byte[] nsec3Salt, bool nsec3OptOut) - { - var soaRecord = _records.OfType().First(); - var subZoneNameserver = _records.Where(x => (x.RecordType == RecordType.Ns) && (x.Name != Name)).ToList(); - var subZones = subZoneNameserver.Select(x => x.Name).Distinct().ToList(); - var unsignedRecords = _records.Where(x => subZones.Any(y => x.Name.IsSubDomainOf(y))).ToList(); // glue records - if (nsec3OptOut) - unsignedRecords = unsignedRecords.Union(subZoneNameserver.Where(x => !_records.Any(y => (y.RecordType == RecordType.Ds) && (y.Name == x.Name)))).ToList(); // delegations without DS record - var recordsByName = _records.Except(unsignedRecords).Union(zoneSigningKeys).Union(keySigningKeys).GroupBy(x => x.Name).Select(x => new Tuple>(x.Key, x.OrderBy(y => y.RecordType == RecordType.Soa ? -1 : (int) y.RecordType).ToList())).OrderBy(x => x.Item1).ToList(); - - byte nsec3RecordFlags = (byte) (nsec3OptOut ? 1 : 0); - - Zone res = new Zone(Name, Count * 3); - List nSec3Records = new List(Count); - - if (nsec3Salt == null) - nsec3Salt = _secureRandom.GenerateSeed(8); - - recordsByName[0].Item2.Add(new NSec3ParamRecord(soaRecord.Name, soaRecord.RecordClass, 0, nsec3Algorithm, 0, (ushort) nsec3Iterations, nsec3Salt)); - - HashSet allNames = new HashSet(); - - for (int i = 0; i < recordsByName.Count; i++) - { - List recordTypes = new List(); - - DomainName currentName = recordsByName[i].Item1; - - foreach (var recordsByType in recordsByName[i].Item2.GroupBy(x => x.RecordType)) - { - List records = recordsByType.ToList(); - - recordTypes.Add(recordsByType.Key); - res.AddRange(records); - - // do not sign nameserver delegations for sub zones - if ((records[0].RecordType == RecordType.Ns) && (currentName != Name)) - continue; - - recordTypes.Add(RecordType.RrSig); - - foreach (var key in zoneSigningKeys) - { - res.Add(new RrSigRecord(records, key, inception, expiration)); - } - if (records[0].RecordType == RecordType.DnsKey) - { - foreach (var key in keySigningKeys) - { - res.Add(new RrSigRecord(records, key, inception, expiration)); - } - } - } - - byte[] hash = recordsByName[i].Item1.GetNSec3Hash(nsec3Algorithm, nsec3Iterations, nsec3Salt); - nSec3Records.Add(new NSec3Record(DomainName.ParseFromMasterfile(hash.ToBase32HexString()) + Name, soaRecord.RecordClass, soaRecord.NegativeCachingTTL, nsec3Algorithm, nsec3RecordFlags, (ushort) nsec3Iterations, nsec3Salt, hash, recordTypes)); - - allNames.Add(currentName); - for (int j = currentName.LabelCount - Name.LabelCount; j > 0; j--) - { - DomainName possibleNonTerminal = currentName.GetParentName(j); - - if (!allNames.Contains(possibleNonTerminal)) - { - hash = possibleNonTerminal.GetNSec3Hash(nsec3Algorithm, nsec3Iterations, nsec3Salt); - nSec3Records.Add(new NSec3Record(DomainName.ParseFromMasterfile(hash.ToBase32HexString()) + Name, soaRecord.RecordClass, soaRecord.NegativeCachingTTL, nsec3Algorithm, nsec3RecordFlags, (ushort) nsec3Iterations, nsec3Salt, hash, new List())); - - allNames.Add(possibleNonTerminal); - } - } - } - - nSec3Records = nSec3Records.OrderBy(x => x.Name).ToList(); - - byte[] firstNextHashedOwnerName = nSec3Records[0].NextHashedOwnerName; - - for (int i = 1; i < nSec3Records.Count; i++) - { - nSec3Records[i - 1].NextHashedOwnerName = nSec3Records[i].NextHashedOwnerName; - } - - nSec3Records[nSec3Records.Count - 1].NextHashedOwnerName = firstNextHashedOwnerName; - - foreach (var nSec3Record in nSec3Records) - { - res.Add(nSec3Record); - - foreach (var key in zoneSigningKeys) - { - res.Add(new RrSigRecord(new List() { nSec3Record }, key, inception, expiration)); - } - } - - res.AddRange(unsignedRecords); - - return res; - } - - + /// /// Adds a record to the end of the Zone /// diff --git a/ARSoft.Tools.Net/DomainName.cs b/ARSoft.Tools.Net/DomainName.cs index 92938f0..7fe65ce 100644 --- a/ARSoft.Tools.Net/DomainName.cs +++ b/ARSoft.Tools.Net/DomainName.cs @@ -24,8 +24,6 @@ using System.Text; using System.Text.RegularExpressions; using ARSoft.Tools.Net.Dns; -using Org.BouncyCastle.Crypto; -using Org.BouncyCastle.Crypto.Digests; namespace ARSoft.Tools.Net { @@ -139,47 +137,6 @@ public bool IsSubDomainOf(DomainName domainName) return GetParentName(LabelCount - domainName.LabelCount).Equals(domainName); } - internal byte[] GetNSec3Hash(NSec3HashAlgorithm algorithm, int iterations, byte[] salt) - { - IDigest digest; - - switch (algorithm) - { - case NSec3HashAlgorithm.Sha1: - digest = new Sha1Digest(); - break; - - default: - throw new NotSupportedException(); - } - - byte[] buffer = new byte[Math.Max(MaximumRecordDataLength + 1, digest.GetDigestSize()) + salt.Length]; - - int length = 0; - - DnsMessageBase.EncodeDomainName(buffer, 0, ref length, this, null, true); - - for (int i = 0; i <= iterations; i++) - { - DnsMessageBase.EncodeByteArray(buffer, ref length, salt); - - digest.BlockUpdate(buffer, 0, length); - - digest.DoFinal(buffer, 0); - length = digest.GetDigestSize(); - } - - byte[] res = new byte[length]; - Buffer.BlockCopy(buffer, 0, res, 0, length); - - return res; - } - - internal DomainName GetNsec3HashName(NSec3HashAlgorithm algorithm, int iterations, byte[] salt, DomainName zoneApex) - { - return new DomainName(GetNSec3Hash(algorithm, iterations, salt).ToBase32HexString(), zoneApex); - } - internal static DomainName ParseFromMasterfile(string s) { if (s == ".") diff --git a/ARSoft.Tools.Net/Net/DaneStream.cs b/ARSoft.Tools.Net/Net/DaneStream.cs deleted file mode 100644 index dd2c81f..0000000 --- a/ARSoft.Tools.Net/Net/DaneStream.cs +++ /dev/null @@ -1,434 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net; -using System.Net.Security; -using System.Net.Sockets; -using System.Security.Authentication; -using System.Security.Cryptography.X509Certificates; -using System.Text; -using System.Threading.Tasks; -using ARSoft.Tools.Net.Dns; - -namespace ARSoft.Tools.Net.Net -{ - /// - /// Provides a stream used for client-server communication that uses SSL/TLS and DANE/TLSA validation to authenticate - /// the server. - /// - public class DaneStream : AuthenticatedStream - { - private readonly IDnsSecResolver _resolver; - private readonly bool _enforceTlsaValidation; - private readonly SslStream _sslStream; - - private DnsSecResult _tlsaRecords; - - /// - /// Creates a new instance of the TlsaStream class - /// - /// The underlying stream on which the encrypted stream should work - /// A DNSSEC resolver to get the TLSA records - /// If true, the use of TLSA records is enforced - /// If true, the underlying stream will not be closed when this instance is closed - /// - /// A callback to select client certificates to authenticate the client to - /// the server - /// - public DaneStream(Stream innerStream, IDnsSecResolver resolver, bool enforceTlsaValidation = false, bool leaveInnerStreamOpen = false, LocalCertificateSelectionCallback userCertificateSelectionCallback = null) - : base(innerStream, leaveInnerStreamOpen) - { - _resolver = resolver; - _enforceTlsaValidation = enforceTlsaValidation; - _sslStream = new SslStream(innerStream, leaveInnerStreamOpen, ValidateRemoteCertificate, userCertificateSelectionCallback); - } - - private bool ValidateRemoteCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) - { - IsAuthenticatedByDane = false; - - switch (_tlsaRecords.ValidationResult) - { - case DnsSecValidationResult.Signed: - if (_tlsaRecords.Records.Count == 0) - return !_enforceTlsaValidation && (sslPolicyErrors == SslPolicyErrors.None); - - foreach (var tlsaRecord in _tlsaRecords.Records) - { - if (ValidateCertificateByTlsa(tlsaRecord, certificate, chain, sslPolicyErrors)) - { - IsAuthenticatedByDane = true; - return true; - } - } - - return false; - - case DnsSecValidationResult.Bogus: - return false; - - default: - return !_enforceTlsaValidation && (sslPolicyErrors == SslPolicyErrors.None); - } - } - - private bool ValidateCertificateByTlsa(TlsaRecord tlsaRecord, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) - { - switch (tlsaRecord.CertificateUsage) - { - case TlsaRecord.TlsaCertificateUsage.PkixTA: - return chain.ChainElements.Cast().Any(x => ValidateCertificateByTlsa(tlsaRecord, x.Certificate)) && (sslPolicyErrors == SslPolicyErrors.None); - - case TlsaRecord.TlsaCertificateUsage.PkixEE: - return ValidateCertificateByTlsa(tlsaRecord, certificate) && (sslPolicyErrors == SslPolicyErrors.None); - - case TlsaRecord.TlsaCertificateUsage.DaneTA: - return chain.ChainElements.Cast().Any(x => ValidateCertificateByTlsa(tlsaRecord, x.Certificate)) && ((sslPolicyErrors | SslPolicyErrors.RemoteCertificateChainErrors) == SslPolicyErrors.RemoteCertificateChainErrors); - - case TlsaRecord.TlsaCertificateUsage.DaneEE: - return ValidateCertificateByTlsa(tlsaRecord, certificate) && ((sslPolicyErrors | SslPolicyErrors.RemoteCertificateChainErrors) == SslPolicyErrors.RemoteCertificateChainErrors); - - default: - throw new NotSupportedException(); - } - } - - private bool ValidateCertificateByTlsa(TlsaRecord tlsaRecord, X509Certificate certificate) - { - return TlsaRecord.GetCertificateAssocicationData(tlsaRecord.Selector, tlsaRecord.MatchingType, certificate).SequenceEqual(tlsaRecord.CertificateAssociationData); - } - - /// - /// Closes the current stream and releases any resources. - /// - public override void Close() - { - _sslStream.Close(); - } - - /// - /// Called by clients to authenticate the server and optionally the client in a client-server connection. - /// - /// The name of the server - /// The port of the server - /// The protocol used to communicate with the server - /// The X509CertificateCollection that contains client certificates. - /// The SslProtocols value that represents the protocol used for authentication. - /// - /// A Boolean value that specifies whether the certificate revocation list is - /// checked during authentication. - /// - public void AuthenticateAsClient(string targetHost, int port, ProtocolType protocol = ProtocolType.Tcp, X509CertificateCollection clientCertificates = null, SslProtocols enabledSslProtocols = SslProtocols.Default, bool checkCertificateRevocation = false) - { - _tlsaRecords = _resolver.ResolveSecure(DomainName.Parse("_" + port + "._" + EnumHelper.ToString(protocol).ToLower() + "." + targetHost), RecordType.Tlsa); - _sslStream.AuthenticateAsClient(targetHost, clientCertificates ?? new X509CertificateCollection(), enabledSslProtocols, checkCertificateRevocation); - } - - /// - /// Called by clients to authenticate the server and optionally the client in a client-server connection. - /// - /// The name of the server - /// The port of the server - /// The protocol used to communicate with the server - /// The X509CertificateCollection that contains client certificates. - /// The SslProtocols value that represents the protocol used for authentication. - /// - /// A Boolean value that specifies whether the certificate revocation list is - /// checked during authentication. - /// - public async Task AuthenticateAsClientAsync(string targetHost, int port, ProtocolType protocol = ProtocolType.Tcp, X509CertificateCollection clientCertificates = null, SslProtocols enabledSslProtocols = SslProtocols.Default, bool checkCertificateRevocation = false) - { - _tlsaRecords = await _resolver.ResolveSecureAsync(DomainName.Parse("_" + port + "._" + EnumHelper.ToString(protocol).ToLower() + "." + targetHost), RecordType.Tlsa); - await _sslStream.AuthenticateAsClientAsync(targetHost, clientCertificates ?? new X509CertificateCollection(), enabledSslProtocols, checkCertificateRevocation); - } - - /// - /// Sets the length of the underlying stream. - /// - /// The new length - public override void SetLength(long value) - { - _sslStream.SetLength(value); - } - - /// - /// Infrastructure. Throws a NotSupportedException. - /// - /// - /// - /// - public override long Seek(long offset, SeekOrigin origin) - { - return _sslStream.Seek(offset, origin); - } - - /// - /// Causes any buffered data to be written to the underlying device. - /// - public override void Flush() - { - _sslStream.Flush(); - } - - /// - /// Reads data from this stream and stores it in the specified array. - /// - /// A Byte array that receives the bytes read from this stream. - /// - /// A Int32 that contains the zero-based location in buffer at which to begin storing the data read - /// from this stream. - /// - /// A Int32 that contains the maximum number of bytes to read from this stream. - /// A Int32 value that specifies the number of bytes read. When there is no more data to be read, returns 0. - public override int Read(byte[] buffer, int offset, int count) - { - return _sslStream.Read(buffer, offset, count); - } - - /// - /// Writes data to this stream. - /// - /// A Byte array that supplies the bytes written to the stream. - /// - /// A Int32 that contains the zero-based location in buffer at which to begin reading bytes to be - /// written to the stream. - /// - /// A Int32 that contains the number of bytes to read from buffer. - public override void Write(byte[] buffer, int offset, int count) - { - _sslStream.Write(buffer, offset, count); - } - - /// - /// Begins an asynchronous read operation that reads data from the stream and stores it in the specified array. - /// - /// A Byte array that receives the bytes read from the stream. - /// The zero-based location in buffer at which to begin storing the data read from this stream. - /// The maximum number of bytes to read from the stream. - /// - /// An AsyncCallback delegate that references the method to invoke when the read operation is - /// complete. - /// - /// - /// A user-defined object that contains information about the read operation. This object is - /// passed to the asyncCallback delegate when the operation completes. - /// - /// An IAsyncResult object that indicates the status of the asynchronous operation. - public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState) - { - return _sslStream.BeginRead(buffer, offset, count, asyncCallback, asyncState); - } - - /// - /// Ends an asynchronous read operation started with a previous call to BeginRead. - /// - /// An IAsyncResult instance returned by a call to BeginRead - /// A Int32 value that specifies the number of bytes read from the underlying stream. - public override int EndRead(IAsyncResult asyncResult) - { - return _sslStream.EndRead(asyncResult); - } - - /// - /// Begins an asynchronous write operation that writes Bytes from the specified buffer to the stream. - /// - /// A Byte array that supplies the bytes to be written to the stream. - /// The zero-based location in buffer at which to begin reading bytes to be written to the stream. - /// An Int32 value that specifies the number of bytes to read from buffer. - /// - /// An AsyncCallback delegate that references the method to invoke when the write operation is - /// complete. - /// - /// - /// A user-defined object that contains information about the write operation. This object is - /// passed to the asyncCallback delegate when the operation completes. - /// - /// An IAsyncResult object indicating the status of the asynchronous operation. - public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState) - { - return _sslStream.BeginWrite(buffer, offset, count, asyncCallback, asyncState); - } - - /// - /// Ends an asynchronous write operation started with a previous call to BeginWrite. - /// - /// An IAsyncResult instance returned by a call to BeginWrite - public override void EndWrite(IAsyncResult asyncResult) - { - _sslStream.EndWrite(asyncResult); - } - - /// - /// Gets the TransportContext used for authentication using extended protection. - /// - public TransportContext TransportContext => _sslStream.TransportContext; - - /// - /// Gets a Boolean value that indicates whether authentication was successful. - /// - public override bool IsAuthenticated => _sslStream.IsAuthenticated; - - /// - /// Gets a Boolean value that indicates whether authentication by TLSA/DANE was successful. - /// - public bool IsAuthenticatedByDane { get; private set; } - - /// - /// Gets a Boolean value that indicates whether both server and client have been authenticated. - /// - public override bool IsMutuallyAuthenticated => _sslStream.IsMutuallyAuthenticated; - - /// - /// Gets a Boolean value that indicates whether this SslStream uses data encryption. - /// - public override bool IsEncrypted => _sslStream.IsEncrypted; - - /// - /// Gets a Boolean value that indicates whether the data sent using this stream is signed. - /// - public override bool IsSigned => _sslStream.IsSigned; - - /// - /// Gets a Boolean value that indicates whether the local side of the connection used by this SslStream was - /// authenticated as the server. - /// - public override bool IsServer => _sslStream.IsServer; - - /// - /// Gets a value that indicates the security protocol used to authenticate this connection. - /// - public SslProtocols SslProtocol => _sslStream.SslProtocol; - - /// - /// Gets a Boolean value that indicates whether the certificate revocation list is checked during the certificate - /// validation process. - /// - public bool CheckCertRevocationStatus => _sslStream.CheckCertRevocationStatus; - - /// - /// Gets the certificate used to authenticate the local endpoint. - /// - public X509Certificate LocalCertificate => _sslStream.LocalCertificate; - - /// - /// Gets the certificate used to authenticate the remote endpoint. - /// - public X509Certificate RemoteCertificate => _sslStream.RemoteCertificate; - - /// - /// Gets a value that identifies the bulk encryption algorithm used by this SslStream. - /// - public CipherAlgorithmType CipherAlgorithm => _sslStream.CipherAlgorithm; - - /// - /// Gets a value that identifies the strength of the cipher algorithm used by this SslStream. - /// - public int CipherStrength => _sslStream.CipherStrength; - - /// - /// Gets the algorithm used for generating message authentication codes (MACs). - /// - public HashAlgorithmType HashAlgorithm => _sslStream.HashAlgorithm; - - /// - /// Gets a value that identifies the strength of the hash algorithm used by this instance. - /// - public int HashStrength => _sslStream.HashStrength; - - /// - /// Gets the key exchange algorithm used by this SslStream. - /// - public ExchangeAlgorithmType KeyExchangeAlgorithm => _sslStream.KeyExchangeAlgorithm; - - /// - /// Gets a value that identifies the strength of the key exchange algorithm used by this instance. - /// - public int KeyExchangeStrength => _sslStream.KeyExchangeStrength; - - /// - /// Gets a Boolean value that indicates whether the underlying stream is seekable. - /// - public override bool CanSeek => _sslStream.CanSeek; - - /// - /// Gets a Boolean value that indicates whether the underlying stream is readable. - /// - public override bool CanRead => _sslStream.CanRead; - - /// - /// Gets a Boolean value that indicates whether the underlying stream supports time-outs. - /// - public override bool CanTimeout => _sslStream.CanTimeout; - - /// - /// Gets a Boolean value that indicates whether the underlying stream is writable. - /// - public override bool CanWrite => _sslStream.CanWrite; - - /// - /// Gets or sets the amount of time a read operation blocks waiting for data. - /// - public override int ReadTimeout - { - get { return _sslStream.ReadTimeout; } - set { _sslStream.ReadTimeout = value; } - } - - /// - /// Gets or sets the amount of time a write operation blocks waiting for data. - /// - public override int WriteTimeout - { - get { return _sslStream.WriteTimeout; } - set { _sslStream.WriteTimeout = value; } - } - - /// - /// Gets the length of the underlying stream. - /// - public override long Length => _sslStream.Length; - - /// - /// Gets or sets the current position in the underlying stream. - /// - public override long Position - { - get { return _sslStream.Position; } - set { _sslStream.Position = value; } - } - - /// - /// Releases the unmanaged resources used by this and optionally releases the managed resources. - /// - /// - /// true to release both managed and unmanaged resources; false to release only unmanaged - /// resources. - /// - protected override void Dispose(bool disposing) - { - if (disposing) - _sslStream.Dispose(); - - base.Dispose(disposing); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Spf/SenderIDRecord.cs b/ARSoft.Tools.Net/Spf/SenderIDRecord.cs deleted file mode 100644 index 7120996..0000000 --- a/ARSoft.Tools.Net/Spf/SenderIDRecord.cs +++ /dev/null @@ -1,195 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; - -namespace ARSoft.Tools.Net.Spf -{ - /// - /// Parsed instance of the textual representation of a SenderID record - /// - /// Defined in - /// RFC 4406 - /// - /// - public class SenderIDRecord : SpfRecordBase - { - private static readonly Regex _prefixRegex = new Regex(@"^v=spf((?1)|(?2)\.(?\d)/(?(([a-z0-9]+,)*[a-z0-9]+)))$", RegexOptions.Compiled | RegexOptions.IgnoreCase); - - /// - /// Version of the SenderID record. - /// - public int Version { get; set; } - - /// - /// Minor version of the SenderID record - /// - public int MinorVersion { get; set; } - - /// - /// List of Scopes of the SenderID record - /// - public List Scopes { get; set; } - - /// - /// Returns the textual representation of the SenderID record - /// - /// Textual representation - public override string ToString() - { - StringBuilder res = new StringBuilder(); - - if (Version == 1) - { - res.Append("v=spf1"); - } - else - { - res.Append("v=spf"); - res.Append(Version); - res.Append("."); - res.Append(MinorVersion); - res.Append("/"); - res.Append(String.Join(",", Scopes.Where(s => s != SenderIDScope.Unknown).Select(s => EnumHelper.ToString(s).ToLower()))); - } - - if ((Terms != null) && (Terms.Count > 0)) - { - foreach (SpfTerm term in Terms) - { - SpfModifier modifier = term as SpfModifier; - if ((modifier == null) || (modifier.Type != SpfModifierType.Unknown)) - { - res.Append(" "); - res.Append(term); - } - } - } - - return res.ToString(); - } - - /// - /// Checks, whether a given string starts with a correct SenderID prefix of a given scope - /// - /// Textual representation to check - /// Scope, which should be matched - /// true in case of correct prefix - public static bool IsSenderIDRecord(string s, SenderIDScope scope) - { - if (String.IsNullOrEmpty(s)) - return false; - - string[] terms = s.Split(new[] { ' ' }, 2); - - if (terms.Length < 2) - return false; - - int version; - int minor; - List scopes; - if (!TryParsePrefix(terms[0], out version, out minor, out scopes)) - { - return false; - } - - if ((version == 1) && ((scope == SenderIDScope.MFrom) || (scope == SenderIDScope.Pra))) - { - return true; - } - else - { - return scopes.Contains(scope); - } - } - - private static bool TryParsePrefix(string prefix, out int version, out int minor, out List scopes) - { - Match match = _prefixRegex.Match(prefix); - if (!match.Success) - { - version = 0; - minor = 0; - scopes = null; - - return false; - } - - version = Int32.Parse(match.Groups["version"].Value); - minor = Int32.Parse("0" + match.Groups["minor"].Value); - scopes = match.Groups["scopes"].Value.Split(',').Select(t => EnumHelper.Parse(t, true, SenderIDScope.Unknown)).ToList(); - - return true; - } - - /// - /// Tries to parse the textual representation of a SenderID record - /// - /// Textual representation to check - /// Parsed SenderID record in case of successful parsing - /// true in case of successful parsing - public static bool TryParse(string s, out SenderIDRecord value) - { - if (String.IsNullOrEmpty(s)) - { - value = null; - return false; - } - - string[] terms = s.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); - - if (terms.Length < 1) - { - value = null; - return false; - } - - int version; - int minor; - List scopes; - if (!TryParsePrefix(terms[0], out version, out minor, out scopes)) - { - value = null; - return false; - } - - List parsedTerms; - if (TryParseTerms(terms, out parsedTerms)) - { - value = - new SenderIDRecord - { - Version = version, - MinorVersion = minor, - Scopes = scopes, - Terms = parsedTerms - }; - return true; - } - else - { - value = null; - return false; - } - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Spf/SenderIDScope.cs b/ARSoft.Tools.Net/Spf/SenderIDScope.cs deleted file mode 100644 index 42699db..0000000 --- a/ARSoft.Tools.Net/Spf/SenderIDScope.cs +++ /dev/null @@ -1,46 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Spf -{ - /// - /// Scope of a SenderID record - /// - public enum SenderIDScope - { - /// - /// Unknown scope - /// - Unknown, - - /// - /// MFrom scope, used for lookups of SMTP MAIL FROM address - /// - MFrom, - - /// - /// PRA scope, used for lookups of the Purported Responsible Address - /// - Pra, - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Spf/SenderIDValidator.cs b/ARSoft.Tools.Net/Spf/SenderIDValidator.cs deleted file mode 100644 index 3741cc9..0000000 --- a/ARSoft.Tools.Net/Spf/SenderIDValidator.cs +++ /dev/null @@ -1,95 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using ARSoft.Tools.Net.Dns; - -namespace ARSoft.Tools.Net.Spf -{ - /// - /// Validator for SenderID records - /// - public class SenderIDValidator : ValidatorBase - { - /// - /// Scope to examin - /// - public SenderIDScope Scope { get; set; } - - /// - /// Initializes a new instance of the SenderIDValidator class. - /// - public SenderIDValidator() - { - Scope = SenderIDScope.MFrom; - } - - protected override async Task LoadRecordsAsync(DomainName domain, CancellationToken token) - { - DnsResolveResult dnsResult = await ResolveDnsAsync(domain, RecordType.Txt, token); - if ((dnsResult == null) || ((dnsResult.ReturnCode != ReturnCode.NoError) && (dnsResult.ReturnCode != ReturnCode.NxDomain))) - { - return new LoadRecordResult() { CouldBeLoaded = false, ErrorResult = SpfQualifier.TempError }; - } - else if ((Scope == SenderIDScope.Pra) && (dnsResult.ReturnCode == ReturnCode.NxDomain)) - { - return new LoadRecordResult() { CouldBeLoaded = false, ErrorResult = SpfQualifier.Fail }; - } - - var senderIDTextRecords = dnsResult.Records - .Select(r => r.TextData) - .Where(t => SenderIDRecord.IsSenderIDRecord(t, Scope)) - .ToList(); - - if (senderIDTextRecords.Count >= 1) - { - var potentialRecords = new List(); - foreach (var senderIDTextRecord in senderIDTextRecords) - { - SenderIDRecord tmpRecord; - if (SenderIDRecord.TryParse(senderIDTextRecord, out tmpRecord)) - { - potentialRecords.Add(tmpRecord); - } - else - { - return new LoadRecordResult() { CouldBeLoaded = false, ErrorResult = SpfQualifier.PermError }; - } - } - - if (potentialRecords.GroupBy(r => r.Version).Any(g => g.Count() > 1)) - { - return new LoadRecordResult() { CouldBeLoaded = false, ErrorResult = SpfQualifier.PermError }; - } - else - { - return new LoadRecordResult() { CouldBeLoaded = true, ErrorResult = default(SpfQualifier), Record = potentialRecords.OrderByDescending(r => r.Version).First() }; - } - } - else - { - return new LoadRecordResult() { CouldBeLoaded = false, ErrorResult = SpfQualifier.None }; - } - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Spf/SpfCheckHostParameter.cs b/ARSoft.Tools.Net/Spf/SpfCheckHostParameter.cs deleted file mode 100644 index 9618a76..0000000 --- a/ARSoft.Tools.Net/Spf/SpfCheckHostParameter.cs +++ /dev/null @@ -1,54 +0,0 @@ -#region Copyright and License -// Copyright 2010..11 Alexander Reinert -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Text; - -namespace ARSoft.Tools.Net.Spf -{ - internal class SpfCheckHostParameter - { - public SpfCheckHostParameter(IPAddress clientAddress, string clientName, string heloName, string domain, string sender) - { - LoopCount = 0; - ClientAddress = clientAddress; - ClientName = clientName; - HeloName = heloName; - CurrentDomain = domain; - Sender = sender; - } - - public SpfCheckHostParameter(string newDomain, SpfCheckHostParameter oldParameters) - { - LoopCount = oldParameters.LoopCount + 1; - ClientAddress = oldParameters.ClientAddress; - ClientName = oldParameters.ClientName; - HeloName = oldParameters.HeloName; - CurrentDomain = newDomain; - Sender = oldParameters.Sender; - } - - public int LoopCount; - public IPAddress ClientAddress; - public string ClientName; - public string HeloName; - public string CurrentDomain; - public string Sender; - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Spf/SpfMechanism.cs b/ARSoft.Tools.Net/Spf/SpfMechanism.cs deleted file mode 100644 index 102c8f4..0000000 --- a/ARSoft.Tools.Net/Spf/SpfMechanism.cs +++ /dev/null @@ -1,100 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Spf -{ - /// - /// Represents a single mechanism term in a SPF record - /// - public class SpfMechanism : SpfTerm - { - /// - /// Qualifier of the mechanism - /// - public SpfQualifier Qualifier { get; set; } - - /// - /// Type of the mechanism - /// - public SpfMechanismType Type { get; set; } - - /// - /// Domain part of the mechanism - /// - public string Domain { get; set; } - - /// - /// IPv4 prefix of the mechanism - /// - public int? Prefix { get; set; } - - /// - /// IPv6 prefix of the mechanism - /// - public int? Prefix6 { get; set; } - - /// - /// Returns the textual representation of a mechanism term - /// - /// Textual representation - public override string ToString() - { - StringBuilder res = new StringBuilder(); - - switch (Qualifier) - { - case SpfQualifier.Fail: - res.Append("-"); - break; - case SpfQualifier.SoftFail: - res.Append("~"); - break; - case SpfQualifier.Neutral: - res.Append("?"); - break; - } - - res.Append(EnumHelper.ToString(Type).ToLower()); - - if (!String.IsNullOrEmpty(Domain)) - { - res.Append(":"); - res.Append(Domain); - } - - if (Prefix.HasValue) - { - res.Append("/"); - res.Append(Prefix.Value); - } - - if (Prefix6.HasValue) - { - res.Append("//"); - res.Append(Prefix6.Value); - } - - return res.ToString(); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Spf/SpfMechanismType.cs b/ARSoft.Tools.Net/Spf/SpfMechanismType.cs deleted file mode 100644 index bf91764..0000000 --- a/ARSoft.Tools.Net/Spf/SpfMechanismType.cs +++ /dev/null @@ -1,76 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Spf -{ - /// - /// Type of spf mechanism - /// - public enum SpfMechanismType - { - /// - /// Unknown mechanism - /// - Unknown, - - /// - /// All mechanism, matches always - /// - All, - - /// - /// IP4 mechanism, matches if ip address (IPv4) is within the given network - /// - Ip4, - - /// - /// IP6 mechanism, matches if ip address (IPv6) is within the given network - /// - Ip6, - - /// - /// A mechanism, matches if the ip address is the target of a hostname lookup for the given domain - /// - A, - - /// - /// MX mechanism, matches if the ip address is a mail exchanger for the given domain - /// - Mx, - - /// - /// PTR mechanism, matches if a correct reverse mapping exists - /// - Ptr, - - /// - /// EXISTS mechanism, matches if the given domain exists - /// - Exists, - - /// - /// INCLUDE mechanism, triggers a recursive evaluation - /// - Include, - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Spf/SpfModifier.cs b/ARSoft.Tools.Net/Spf/SpfModifier.cs deleted file mode 100644 index 0299fbc..0000000 --- a/ARSoft.Tools.Net/Spf/SpfModifier.cs +++ /dev/null @@ -1,56 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Spf -{ - /// - /// Represents a single modifier term in a SPF record - /// - public class SpfModifier : SpfTerm - { - /// - /// Type of the modifier - /// - public SpfModifierType Type { get; set; } - - /// - /// Domain part of the modifier - /// - public string Domain { get; set; } - - /// - /// Returns the textual representation of a modifier term - /// - /// Textual representation - public override string ToString() - { - StringBuilder res = new StringBuilder(); - - res.Append(EnumHelper.ToString(Type).ToLower()); - res.Append("="); - res.Append(Domain); - - return res.ToString(); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Spf/SpfModifierType.cs b/ARSoft.Tools.Net/Spf/SpfModifierType.cs deleted file mode 100644 index 24d81f8..0000000 --- a/ARSoft.Tools.Net/Spf/SpfModifierType.cs +++ /dev/null @@ -1,46 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Spf -{ - /// - /// Type of the spf modifier - /// - public enum SpfModifierType - { - /// - /// Unknown mechanism - /// - Unknown, - - /// - /// REDIRECT modifier, redirects the evaluation to another record, if of all tests fail - /// - Redirect, - - /// - /// EXP modifier, used for lookup of a explanation in case of failed test - /// - Exp, - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Spf/SpfQualifier.cs b/ARSoft.Tools.Net/Spf/SpfQualifier.cs deleted file mode 100644 index e8e2ad2..0000000 --- a/ARSoft.Tools.Net/Spf/SpfQualifier.cs +++ /dev/null @@ -1,66 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Spf -{ - /// - /// Qualifier of spf mechanism - /// - public enum SpfQualifier - { - /// - /// No records were published or no checkable sender could be determined - /// - None, - - /// - /// Client is allowed to send mail with the given identity - /// - Pass, - - /// - /// Client is explicit not allowed to send mail with the given identity - /// - Fail, - - /// - /// Client is not allowed to send mail with the given identity - /// - SoftFail, - - /// - /// No statement if a client is allowed or not allowed to send mail with the given identity - /// - Neutral, - - /// - /// A transient error encountered while performing the check - /// - TempError, - - /// - /// The published record could not be correctly interpreted - /// - PermError, - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Spf/SpfRecord.cs b/ARSoft.Tools.Net/Spf/SpfRecord.cs deleted file mode 100644 index f9e325b..0000000 --- a/ARSoft.Tools.Net/Spf/SpfRecord.cs +++ /dev/null @@ -1,99 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Spf -{ - /// - /// Parsed instance of the textual representation of a SPF record - /// - /// Defined in - /// RFC 4408 - /// - /// - public class SpfRecord : SpfRecordBase - { - /// - /// Returns the textual representation of a SPF record - /// - /// Textual representation - public override string ToString() - { - StringBuilder res = new StringBuilder(); - res.Append("v=spf1"); - - if ((Terms != null) && (Terms.Count > 0)) - { - foreach (SpfTerm term in Terms) - { - SpfModifier modifier = term as SpfModifier; - if ((modifier == null) || (modifier.Type != SpfModifierType.Unknown)) - { - res.Append(" "); - res.Append(term); - } - } - } - - return res.ToString(); - } - - /// - /// Checks, whether a given string starts with a correct SPF prefix - /// - /// Textual representation to check - /// true in case of correct prefix - public static bool IsSpfRecord(string s) - { - return !String.IsNullOrEmpty(s) && s.StartsWith("v=spf1 "); - } - - /// - /// Tries to parse the textual representation of a SPF string - /// - /// Textual representation to check - /// Parsed spf record in case of successful parsing - /// true in case of successful parsing - public static bool TryParse(string s, out SpfRecord value) - { - if (!IsSpfRecord(s)) - { - value = null; - return false; - } - - string[] terms = s.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); - - List parsedTerms; - if (TryParseTerms(terms, out parsedTerms)) - { - value = new SpfRecord { Terms = parsedTerms }; - return true; - } - else - { - value = null; - return false; - } - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Spf/SpfRecordBase.cs b/ARSoft.Tools.Net/Spf/SpfRecordBase.cs deleted file mode 100644 index 57cfa5e..0000000 --- a/ARSoft.Tools.Net/Spf/SpfRecordBase.cs +++ /dev/null @@ -1,57 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Spf -{ - /// - /// Base class of a SPF or SenderID record - /// - public class SpfRecordBase - { - /// - /// Modifiers and mechanisms of a record - /// - public List Terms { get; set; } - - protected static bool TryParseTerms(string[] terms, out List parsedTerms) - { - parsedTerms = new List(terms.Length - 1); - - for (int i = 1; i < terms.Length; i++) - { - SpfTerm term; - if (SpfTerm.TryParse(terms[i], out term)) - { - parsedTerms.Add(term); - } - else - { - parsedTerms = null; - return false; - } - } - - return true; - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Spf/SpfTerm.cs b/ARSoft.Tools.Net/Spf/SpfTerm.cs deleted file mode 100644 index 0002044..0000000 --- a/ARSoft.Tools.Net/Spf/SpfTerm.cs +++ /dev/null @@ -1,111 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; - -namespace ARSoft.Tools.Net.Spf -{ - /// - /// Represents a single term of a SPF record - /// - public class SpfTerm - { - private static readonly Regex _parseMechanismRegex = new Regex(@"^(\s)*(?[~+?-]?)(?[a-z0-9]+)(:(?[^/]+))?(/(?[0-9]+)(/(?[0-9]+))?)?(\s)*$", RegexOptions.Compiled | RegexOptions.IgnoreCase); - private static readonly Regex _parseModifierRegex = new Regex(@"^(\s)*(?[a-z]+)=(?[^\s]+)(\s)*$", RegexOptions.Compiled | RegexOptions.IgnoreCase); - - internal static bool TryParse(string s, out SpfTerm value) - { - if (String.IsNullOrEmpty(s)) - { - value = null; - return false; - } - - #region Parse Mechanism - Match match = _parseMechanismRegex.Match(s); - if (match.Success) - { - SpfMechanism mechanism = new SpfMechanism(); - - switch (match.Groups["qualifier"].Value) - { - case "+": - mechanism.Qualifier = SpfQualifier.Pass; - break; - case "-": - mechanism.Qualifier = SpfQualifier.Fail; - break; - case "~": - mechanism.Qualifier = SpfQualifier.SoftFail; - break; - case "?": - mechanism.Qualifier = SpfQualifier.Neutral; - break; - - default: - mechanism.Qualifier = SpfQualifier.Pass; - break; - } - - SpfMechanismType type; - mechanism.Type = EnumHelper.TryParse(match.Groups["type"].Value, true, out type) ? type : SpfMechanismType.Unknown; - - mechanism.Domain = match.Groups["domain"].Value; - - string tmpPrefix = match.Groups["prefix"].Value; - int prefix; - if (!String.IsNullOrEmpty(tmpPrefix) && Int32.TryParse(tmpPrefix, out prefix)) - { - mechanism.Prefix = prefix; - } - - tmpPrefix = match.Groups["prefix6"].Value; - if (!String.IsNullOrEmpty(tmpPrefix) && Int32.TryParse(tmpPrefix, out prefix)) - { - mechanism.Prefix6 = prefix; - } - - value = mechanism; - return true; - } - #endregion - - #region Parse Modifier - match = _parseModifierRegex.Match(s); - if (match.Success) - { - SpfModifier modifier = new SpfModifier(); - - SpfModifierType type; - modifier.Type = EnumHelper.TryParse(match.Groups["type"].Value, true, out type) ? type : SpfModifierType.Unknown; - modifier.Domain = match.Groups["domain"].Value; - - value = modifier; - return true; - } - #endregion - - value = null; - return false; - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Spf/SpfValidator.cs b/ARSoft.Tools.Net/Spf/SpfValidator.cs deleted file mode 100644 index b1a1708..0000000 --- a/ARSoft.Tools.Net/Spf/SpfValidator.cs +++ /dev/null @@ -1,63 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using ARSoft.Tools.Net.Dns; - -namespace ARSoft.Tools.Net.Spf -{ - /// - /// Validator for SPF records - /// - public class SpfValidator : ValidatorBase - { - protected override async Task LoadRecordsAsync(DomainName domain, CancellationToken token) - { - DnsResolveResult dnsResult = await ResolveDnsAsync(domain, RecordType.Txt, token); - if ((dnsResult == null) || ((dnsResult.ReturnCode != ReturnCode.NoError) && (dnsResult.ReturnCode != ReturnCode.NxDomain))) - { - return new LoadRecordResult() { CouldBeLoaded = false, ErrorResult = SpfQualifier.TempError }; - } - - var spfTextRecords = dnsResult.Records - .Select(r => r.TextData) - .Where(SpfRecord.IsSpfRecord) - .ToList(); - - SpfRecord record; - - if (spfTextRecords.Count == 0) - { - return new LoadRecordResult() { CouldBeLoaded = false, ErrorResult = SpfQualifier.None }; - } - else if ((spfTextRecords.Count > 1) || !SpfRecord.TryParse(spfTextRecords[0], out record)) - { - return new LoadRecordResult() { CouldBeLoaded = false, ErrorResult = SpfQualifier.PermError }; - } - else - { - return new LoadRecordResult() { CouldBeLoaded = true, Record = record }; - } - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Spf/ValidationResult.cs b/ARSoft.Tools.Net/Spf/ValidationResult.cs deleted file mode 100644 index 790c91f..0000000 --- a/ARSoft.Tools.Net/Spf/ValidationResult.cs +++ /dev/null @@ -1,36 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -namespace ARSoft.Tools.Net.Spf -{ - /// - /// The result of a SPF or SenderID validation - /// - public class ValidationResult - { - /// - /// The result of the validation - /// - public SpfQualifier Result { get; internal set; } - - /// - /// A explanation in case of result Fail. Only filled if requested on validation call - /// - public string Explanation { get; internal set; } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Spf/ValidatorBase.cs b/ARSoft.Tools.Net/Spf/ValidatorBase.cs deleted file mode 100644 index 6570f41..0000000 --- a/ARSoft.Tools.Net/Spf/ValidatorBase.cs +++ /dev/null @@ -1,644 +0,0 @@ -#region Copyright and License -// Copyright 2010..2017 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Net.NetworkInformation; -using System.Net.Sockets; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading; -using System.Threading.Tasks; -using ARSoft.Tools.Net.Dns; - -namespace ARSoft.Tools.Net.Spf -{ - /// - /// Base implementation of a validator for SPF and SenderID records - /// - /// Type of the record - public abstract class ValidatorBase - where T : SpfRecordBase - { - protected class State - { - public int DnsLookupCount { get; set; } - } - - // ReSharper disable once StaticMemberInGenericType - private static readonly Regex _parseMacroRegex = new Regex(@"(%%|%_|%-|%\{(?[slodiphcrtv])(?\d*)(?r?)(?[\.\-+,/=]*)})", RegexOptions.Compiled); - - /// - /// DnsResolver which is used for DNS lookups - /// Default is a Stub DNS resolver using the local configured upstream servers - /// - public IDnsResolver DnsResolver { get; set; } = new DnsStubResolver(); - - /// - /// Domain name which was used in HELO/EHLO - /// - public DomainName HeloDomain { get; set; } - - /// - /// IP address of the computer validating the record - /// Default is the first IP the computer - /// - public IPAddress LocalIP { get; set; } - - /// - /// Name of the computer validating the record - /// Default is the computer name - /// - public DomainName LocalDomain { get; set; } - - /// - /// The maximum number of DNS lookups allowed - /// Default is 20 - /// - public int DnsLookupLimit { get; set; } = 20; - - protected abstract Task LoadRecordsAsync(DomainName domain, CancellationToken token); - - /// - /// Validates the record(s) - /// - /// The IP address of the SMTP client that is emitting the mail - /// The domain portion of the "MAIL FROM" or "HELO" identity - /// The "MAIL FROM" or "HELO" identity - /// A value indicating if the explanation should be retrieved in case of Fail - /// The result of the evaluation - public ValidationResult CheckHost(IPAddress ip, DomainName domain, string sender, bool expandExplanation = false) - { - var result = CheckHostInternalAsync(ip, domain, sender, expandExplanation, new State(), default(CancellationToken)); - result.Wait(); - - return result.Result; - } - - /// - /// Validates the record(s) - /// - /// The IP address of the SMTP client that is emitting the mail - /// The domain portion of the "MAIL FROM" or "HELO" identity - /// The "MAIL FROM" or "HELO" identity - /// A value indicating if the explanation should be retrieved in case of Fail - /// The result of the evaluation - public ValidationResult CheckHost(IPAddress ip, string domain, string sender, bool expandExplanation = false) - { - return CheckHost(ip, DomainName.Parse(domain), sender, expandExplanation); - } - - /// - /// Validates the record(s) - /// - /// The IP address of the SMTP client that is emitting the mail - /// The domain portion of the "MAIL FROM" or "HELO" identity - /// The "MAIL FROM" or "HELO" identity - /// A value indicating if the explanation should be retrieved in case of Fail - /// The token to monitor cancellation requests - /// The result of the evaluation - public Task CheckHostAsync(IPAddress ip, DomainName domain, string sender, bool expandExplanation = false, CancellationToken token = default(CancellationToken)) - { - return CheckHostInternalAsync(ip, domain, sender, expandExplanation, new State(), token); - } - - /// - /// Validates the record(s) - /// - /// The IP address of the SMTP client that is emitting the mail - /// The domain portion of the "MAIL FROM" or "HELO" identity - /// The "MAIL FROM" or "HELO" identity - /// A value indicating if the explanation should be retrieved in case of Fail - /// The token to monitor cancellation requests - /// The result of the evaluation - public Task CheckHostAsync(IPAddress ip, string domain, string sender, bool expandExplanation = false, CancellationToken token = default(CancellationToken)) - { - return CheckHostAsync(ip, DomainName.Parse(domain), sender, expandExplanation, token); - } - - protected class LoadRecordResult - { - public bool CouldBeLoaded { get; internal set; } - public T Record { get; internal set; } - public SpfQualifier ErrorResult { get; internal set; } - } - - private async Task CheckHostInternalAsync(IPAddress ip, DomainName domain, string sender, bool expandExplanation, State state, CancellationToken token) - { - if ((domain == null) || (domain.Equals(DomainName.Root))) - { - return new ValidationResult() { Result = SpfQualifier.None, Explanation = String.Empty }; - } - - if (String.IsNullOrEmpty(sender)) - { - sender = "postmaster@unknown"; - } - else if (!sender.Contains('@')) - { - sender = "postmaster@" + sender; - } - - LoadRecordResult loadResult = await LoadRecordsAsync(domain, token); - - if (!loadResult.CouldBeLoaded) - { - return new ValidationResult() { Result = loadResult.ErrorResult, Explanation = String.Empty }; - } - - T record = loadResult.Record; - - if ((record.Terms == null) || (record.Terms.Count == 0)) - return new ValidationResult() { Result = SpfQualifier.Neutral, Explanation = String.Empty }; - - if (record.Terms.OfType().GroupBy(m => m.Type).Where(g => (g.Key == SpfModifierType.Exp) || (g.Key == SpfModifierType.Redirect)).Any(g => g.Count() > 1)) - return new ValidationResult() { Result = SpfQualifier.PermError, Explanation = String.Empty }; - - ValidationResult result = new ValidationResult() { Result = loadResult.ErrorResult }; - - #region Evaluate mechanism - foreach (SpfMechanism mechanism in record.Terms.OfType()) - { - if (state.DnsLookupCount > DnsLookupLimit) - return new ValidationResult() { Result = SpfQualifier.PermError, Explanation = String.Empty }; - - SpfQualifier qualifier = await CheckMechanismAsync(mechanism, ip, domain, sender, state, token); - - if (qualifier != SpfQualifier.None) - { - result.Result = qualifier; - break; - } - } - #endregion - - #region Evaluate modifiers - if (result.Result == SpfQualifier.None) - { - SpfModifier redirectModifier = record.Terms.OfType().FirstOrDefault(m => m.Type == SpfModifierType.Redirect); - if (redirectModifier != null) - { - if (++state.DnsLookupCount > 10) - return new ValidationResult() { Result = SpfQualifier.PermError, Explanation = String.Empty }; - - DomainName redirectDomain = await ExpandDomainAsync(redirectModifier.Domain ?? String.Empty, ip, domain, sender, token); - - if ((redirectDomain == null) || (redirectDomain == DomainName.Root) || (redirectDomain.Equals(domain))) - { - result.Result = SpfQualifier.PermError; - } - else - { - result = await CheckHostInternalAsync(ip, redirectDomain, sender, expandExplanation, state, token); - - if (result.Result == SpfQualifier.None) - result.Result = SpfQualifier.PermError; - } - } - } - else if ((result.Result == SpfQualifier.Fail) && expandExplanation) - { - SpfModifier expModifier = record.Terms.OfType().FirstOrDefault(m => m.Type == SpfModifierType.Exp); - if (expModifier != null) - { - DomainName target = await ExpandDomainAsync(expModifier.Domain, ip, domain, sender, token); - - if ((target == null) || (target.Equals(DomainName.Root))) - { - result.Explanation = String.Empty; - } - else - { - DnsResolveResult dnsResult = await ResolveDnsAsync(target, RecordType.Txt, token); - if ((dnsResult != null) && (dnsResult.ReturnCode == ReturnCode.NoError)) - { - TxtRecord txtRecord = dnsResult.Records.FirstOrDefault(); - if (txtRecord != null) - { - result.Explanation = (await ExpandMacroAsync(txtRecord.TextData, ip, domain, sender, token)).ToString(); - } - } - } - } - } - #endregion - - if (result.Result == SpfQualifier.None) - result.Result = SpfQualifier.Neutral; - - return result; - } - - private async Task CheckMechanismAsync(SpfMechanism mechanism, IPAddress ip, DomainName domain, string sender, State state, CancellationToken token) - { - switch (mechanism.Type) - { - case SpfMechanismType.All: - return mechanism.Qualifier; - - case SpfMechanismType.A: - if (++state.DnsLookupCount > 10) - return SpfQualifier.PermError; - - DomainName aMechanismDomain = String.IsNullOrEmpty(mechanism.Domain) ? domain : await ExpandDomainAsync(mechanism.Domain, ip, domain, sender, token); - - bool? isAMatch = await IsIpMatchAsync(aMechanismDomain, ip, mechanism.Prefix, mechanism.Prefix6, token); - if (!isAMatch.HasValue) - return SpfQualifier.TempError; - - if (isAMatch.Value) - { - return mechanism.Qualifier; - } - break; - - case SpfMechanismType.Mx: - if (++state.DnsLookupCount > 10) - return SpfQualifier.PermError; - - DomainName mxMechanismDomain = String.IsNullOrEmpty(mechanism.Domain) ? domain : await ExpandDomainAsync(mechanism.Domain, ip, domain, sender, token); - - DnsResolveResult dnsMxResult = await ResolveDnsAsync(mxMechanismDomain, RecordType.Mx, token); - if ((dnsMxResult == null) || ((dnsMxResult.ReturnCode != ReturnCode.NoError) && (dnsMxResult.ReturnCode != ReturnCode.NxDomain))) - return SpfQualifier.TempError; - - int mxCheckedCount = 0; - - foreach (MxRecord mxRecord in dnsMxResult.Records) - { - if (++mxCheckedCount == 10) - break; - - bool? isMxMatch = await IsIpMatchAsync(mxRecord.ExchangeDomainName, ip, mechanism.Prefix, mechanism.Prefix6, token); - if (!isMxMatch.HasValue) - return SpfQualifier.TempError; - - if (isMxMatch.Value) - { - return mechanism.Qualifier; - } - } - break; - - case SpfMechanismType.Ip4: - case SpfMechanismType.Ip6: - IPAddress compareAddress; - if (IPAddress.TryParse(mechanism.Domain, out compareAddress)) - { - if (ip.AddressFamily != compareAddress.AddressFamily) - return SpfQualifier.None; - - if (mechanism.Prefix.HasValue) - { - if ((mechanism.Prefix.Value < 0) || (mechanism.Prefix.Value > (compareAddress.AddressFamily == AddressFamily.InterNetworkV6 ? 128 : 32))) - return SpfQualifier.PermError; - - if (ip.GetNetworkAddress(mechanism.Prefix.Value).Equals(compareAddress.GetNetworkAddress(mechanism.Prefix.Value))) - { - return mechanism.Qualifier; - } - } - else if (ip.Equals(compareAddress)) - { - return mechanism.Qualifier; - } - } - else - { - return SpfQualifier.PermError; - } - - break; - - case SpfMechanismType.Ptr: - if (++state.DnsLookupCount > 10) - return SpfQualifier.PermError; - - DnsResolveResult dnsPtrResult = await ResolveDnsAsync(ip.GetReverseLookupDomain(), RecordType.Ptr, token); - if ((dnsPtrResult == null) || ((dnsPtrResult.ReturnCode != ReturnCode.NoError) && (dnsPtrResult.ReturnCode != ReturnCode.NxDomain))) - return SpfQualifier.TempError; - - DomainName ptrMechanismDomain = String.IsNullOrEmpty(mechanism.Domain) ? domain : await ExpandDomainAsync(mechanism.Domain, ip, domain, sender, token); - - int ptrCheckedCount = 0; - foreach (PtrRecord ptrRecord in dnsPtrResult.Records) - { - if (++ptrCheckedCount == 10) - break; - - bool? isPtrMatch = await IsIpMatchAsync(ptrRecord.PointerDomainName, ip, 0, 0, token); - if (isPtrMatch.HasValue && isPtrMatch.Value) - { - if (ptrRecord.PointerDomainName.Equals(ptrMechanismDomain) || (ptrRecord.PointerDomainName.IsSubDomainOf(ptrMechanismDomain))) - return mechanism.Qualifier; - } - } - break; - - case SpfMechanismType.Exists: - if (++state.DnsLookupCount > 10) - return SpfQualifier.PermError; - - if (String.IsNullOrEmpty(mechanism.Domain)) - return SpfQualifier.PermError; - - DomainName existsMechanismDomain = String.IsNullOrEmpty(mechanism.Domain) ? domain : await ExpandDomainAsync(mechanism.Domain, ip, domain, sender, token); - - DnsResolveResult dnsAResult = await ResolveDnsAsync(existsMechanismDomain, RecordType.A, token); - if ((dnsAResult == null) || ((dnsAResult.ReturnCode != ReturnCode.NoError) && (dnsAResult.ReturnCode != ReturnCode.NxDomain))) - return SpfQualifier.TempError; - - if (dnsAResult.Records.Count(record => (record.RecordType == RecordType.A)) > 0) - { - return mechanism.Qualifier; - } - break; - - case SpfMechanismType.Include: - if (++state.DnsLookupCount > 10) - return SpfQualifier.PermError; - - if (String.IsNullOrEmpty(mechanism.Domain)) - return SpfQualifier.PermError; - - DomainName includeMechanismDomain = String.IsNullOrEmpty(mechanism.Domain) ? domain : await ExpandDomainAsync(mechanism.Domain, ip, domain, sender, token); - - if (includeMechanismDomain.Equals(domain)) - return SpfQualifier.PermError; - - var includeResult = await CheckHostInternalAsync(ip, includeMechanismDomain, sender, false, state, token); - switch (includeResult.Result) - { - case SpfQualifier.Pass: - return mechanism.Qualifier; - - case SpfQualifier.Fail: - case SpfQualifier.SoftFail: - case SpfQualifier.Neutral: - return SpfQualifier.None; - - case SpfQualifier.TempError: - return SpfQualifier.TempError; - - case SpfQualifier.PermError: - case SpfQualifier.None: - return SpfQualifier.PermError; - } - break; - - default: - return SpfQualifier.PermError; - } - - return SpfQualifier.None; - } - - private Task IsIpMatchAsync(DomainName domain, IPAddress ipAddress, int? prefix4, int? prefix6, CancellationToken token) - { - if (ipAddress.AddressFamily == AddressFamily.InterNetworkV6) - { - if (prefix6.HasValue) - ipAddress = ipAddress.GetNetworkAddress(prefix6.Value); - - return IsIpMatchAsync(domain, ipAddress, prefix6, RecordType.Aaaa, token); - } - else - { - if (prefix4.HasValue) - ipAddress = ipAddress.GetNetworkAddress(prefix4.Value); - - return IsIpMatchAsync(domain, ipAddress, prefix4, RecordType.A, token); - } - } - - private async Task IsIpMatchAsync(DomainName domain, IPAddress ipAddress, int? prefix, RecordType recordType, CancellationToken token) - where TRecord : DnsRecordBase, IAddressRecord - { - DnsResolveResult dnsResult = await ResolveDnsAsync(domain, recordType, token); - if ((dnsResult == null) || ((dnsResult.ReturnCode != ReturnCode.NoError) && (dnsResult.ReturnCode != ReturnCode.NxDomain))) - return null; - - foreach (var dnsRecord in dnsResult.Records) - { - if (prefix.HasValue) - { - if (ipAddress.Equals(dnsRecord.Address.GetNetworkAddress(prefix.Value))) - return true; - } - else - { - if (ipAddress.Equals(dnsRecord.Address)) - return true; - } - } - - return false; - } - - protected class DnsResolveResult - where TRecord : DnsRecordBase - { - public ReturnCode ReturnCode { get; } - public List Records { get; } - - public DnsResolveResult(ReturnCode returnCode, List records) - { - ReturnCode = returnCode; - Records = records; - } - } - - protected async Task> ResolveDnsAsync(DomainName domain, RecordType recordType, CancellationToken token) - where TRecord : DnsRecordBase - { - try - { - var records = await DnsResolver.ResolveAsync(domain, recordType, token: token); - return new DnsResolveResult(ReturnCode.NoError, records); - } - catch - { - return new DnsResolveResult(ReturnCode.ServerFailure, null); - } - } - - private async Task ExpandDomainAsync(string pattern, IPAddress ip, DomainName domain, string sender, CancellationToken token) - { - string expanded = await ExpandMacroAsync(pattern, ip, domain, sender, token); - - if (String.IsNullOrEmpty(expanded)) - return DomainName.Root; - - return DomainName.Parse(expanded); - } - - private async Task ExpandMacroAsync(string pattern, IPAddress ip, DomainName domain, string sender, CancellationToken token) - { - if (String.IsNullOrEmpty(pattern)) - return String.Empty; - - Match match = _parseMacroRegex.Match(pattern); - if (!match.Success) - { - return pattern; - } - - StringBuilder sb = new StringBuilder(); - int pos = 0; - do - { - if (match.Index != pos) - { - sb.Append(pattern, pos, match.Index - pos); - } - pos = match.Index + match.Length; - sb.Append(await ExpandMacroAsync(match, ip, domain, sender, token)); - match = match.NextMatch(); - } while (match.Success); - - if (pos < pattern.Length) - { - sb.Append(pattern, pos, pattern.Length - pos); - } - - return sb.ToString(); - } - - private async Task ExpandMacroAsync(Match pattern, IPAddress ip, DomainName domain, string sender, CancellationToken token) - { - switch (pattern.Value) - { - case "%%": - return "%"; - case "%_": - return "_"; - case "%-": - return "-"; - - default: - string letter; - switch (pattern.Groups["letter"].Value) - { - case "s": - letter = sender; - break; - case "l": - // no boundary check needed, sender is validated on start of CheckHost - letter = sender.Split('@')[0]; - break; - case "o": - // no boundary check needed, sender is validated on start of CheckHost - letter = sender.Split('@')[1]; - break; - case "d": - letter = domain.ToString(); - break; - case "i": - letter = String.Join(".", ip.GetAddressBytes().Select(b => b.ToString())); - break; - case "p": - letter = "unknown"; - - DnsResolveResult dnsResult = await ResolveDnsAsync(ip.GetReverseLookupDomain(), RecordType.Ptr, token); - if ((dnsResult == null) || ((dnsResult.ReturnCode != ReturnCode.NoError) && (dnsResult.ReturnCode != ReturnCode.NxDomain))) - { - break; - } - - int ptrCheckedCount = 0; - foreach (PtrRecord ptrRecord in dnsResult.Records) - { - if (++ptrCheckedCount == 10) - break; - - bool? isPtrMatch = await IsIpMatchAsync(ptrRecord.PointerDomainName, ip, 0, 0, token); - if (isPtrMatch.HasValue && isPtrMatch.Value) - { - if (letter == "unknown" || ptrRecord.PointerDomainName.IsSubDomainOf(domain)) - { - // use value, if first record or subdomain - // but evaluate the other records - letter = ptrRecord.PointerDomainName.ToString(); - } - else if (ptrRecord.PointerDomainName.Equals(domain)) - { - // ptr equal domain --> best match, use it - letter = ptrRecord.PointerDomainName.ToString(); - break; - } - } - } - break; - case "v": - letter = (ip.AddressFamily == AddressFamily.InterNetworkV6) ? "ip6" : "in-addr"; - break; - case "h": - letter = HeloDomain?.ToString() ?? "unknown"; - break; - case "c": - IPAddress address = - LocalIP - ?? NetworkInterface.GetAllNetworkInterfaces() - .Where(n => (n.OperationalStatus == OperationalStatus.Up) && (n.NetworkInterfaceType != NetworkInterfaceType.Loopback)) - .SelectMany(n => n.GetIPProperties().UnicastAddresses) - .Select(u => u.Address) - .FirstOrDefault(a => a.AddressFamily == ip.AddressFamily) - ?? ((ip.AddressFamily == AddressFamily.InterNetwork) ? IPAddress.Loopback : IPAddress.IPv6Loopback); - letter = address.ToString(); - break; - case "r": - letter = LocalDomain?.ToString() ?? System.Net.Dns.GetHostName(); - break; - case "t": - letter = ((int) (new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc) - DateTime.Now).TotalSeconds).ToString(); - break; - default: - return null; - } - - // only letter - if (pattern.Value.Length == 4) - return letter; - - char[] delimiters = pattern.Groups["delimiter"].Value.ToCharArray(); - if (delimiters.Length == 0) - delimiters = new[] { '.' }; - - string[] parts = letter.Split(delimiters); - - if (pattern.Groups["reverse"].Value == "r") - parts = parts.Reverse().ToArray(); - - int count = Int32.MaxValue; - if (!String.IsNullOrEmpty(pattern.Groups["count"].Value)) - { - count = Int32.Parse(pattern.Groups["count"].Value); - } - - if (count < 1) - return null; - - count = Math.Min(count, parts.Length); - - return String.Join(".", parts, (parts.Length - count), count); - } - } - } -} \ No newline at end of file From 1b8c201ba24fc20f858bf1bac31203d5acd4635b Mon Sep 17 00:00:00 2001 From: marcbarry <> Date: Tue, 24 Sep 2019 16:37:36 +0100 Subject: [PATCH 2/6] remove BouncyCastle nuget package --- ARSoft.Tools.Net/ARSoft.Tools.Net.csproj | 1 - ARSoft.Tools.Net/packages.config | 4 ---- 2 files changed, 5 deletions(-) delete mode 100644 ARSoft.Tools.Net/packages.config diff --git a/ARSoft.Tools.Net/ARSoft.Tools.Net.csproj b/ARSoft.Tools.Net/ARSoft.Tools.Net.csproj index 397e49d..604a84a 100644 --- a/ARSoft.Tools.Net/ARSoft.Tools.Net.csproj +++ b/ARSoft.Tools.Net/ARSoft.Tools.Net.csproj @@ -121,7 +121,6 @@ Always - diff --git a/ARSoft.Tools.Net/packages.config b/ARSoft.Tools.Net/packages.config deleted file mode 100644 index 730a601..0000000 --- a/ARSoft.Tools.Net/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file From a0a4a215fbe9a61cc3cb50b6be524aeead744999 Mon Sep 17 00:00:00 2001 From: marcbarry <> Date: Tue, 24 Sep 2019 16:40:08 +0100 Subject: [PATCH 3/6] clean-up code a bit more --- ARSoft.Tools.Net/ARSoft.Tools.Net.csproj | 3 --- ARSoft.Tools.Net/BaseEncoding.cs | 3 --- ARSoft.Tools.Net/Dns/DnsRecord/DnsRecordBase.cs | 1 - ARSoft.Tools.Net/IPAddressExtensions.cs | 1 - 4 files changed, 8 deletions(-) diff --git a/ARSoft.Tools.Net/ARSoft.Tools.Net.csproj b/ARSoft.Tools.Net/ARSoft.Tools.Net.csproj index 604a84a..9242c1e 100644 --- a/ARSoft.Tools.Net/ARSoft.Tools.Net.csproj +++ b/ARSoft.Tools.Net/ARSoft.Tools.Net.csproj @@ -52,9 +52,6 @@ - - 3.5 - diff --git a/ARSoft.Tools.Net/BaseEncoding.cs b/ARSoft.Tools.Net/BaseEncoding.cs index 6e42a71..30eccf1 100644 --- a/ARSoft.Tools.Net/BaseEncoding.cs +++ b/ARSoft.Tools.Net/BaseEncoding.cs @@ -16,10 +16,7 @@ // limitations under the License. #endregion -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; namespace ARSoft.Tools.Net { diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/DnsRecordBase.cs b/ARSoft.Tools.Net/Dns/DnsRecord/DnsRecordBase.cs index 5eb9b62..acee0fb 100644 --- a/ARSoft.Tools.Net/Dns/DnsRecord/DnsRecordBase.cs +++ b/ARSoft.Tools.Net/Dns/DnsRecord/DnsRecordBase.cs @@ -20,7 +20,6 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; -using System.Text; namespace ARSoft.Tools.Net.Dns { diff --git a/ARSoft.Tools.Net/IPAddressExtensions.cs b/ARSoft.Tools.Net/IPAddressExtensions.cs index 7cbfab9..b61a0d2 100644 --- a/ARSoft.Tools.Net/IPAddressExtensions.cs +++ b/ARSoft.Tools.Net/IPAddressExtensions.cs @@ -17,7 +17,6 @@ #endregion using System; -using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.NetworkInformation; From 5d17da396accbb77f51ae5310884ae06bbfabf04 Mon Sep 17 00:00:00 2001 From: Alistair Evans Date: Mon, 13 Dec 2021 11:13:37 +0000 Subject: [PATCH 4/6] Tidy up and change to .net6 --- ARSoft.Tools.Net/ARSoft.Tools.Net.csproj | 128 +--------- ARSoft.Tools.Net/Dns/DnsAsyncState.cs | 97 -------- ARSoft.Tools.Net/Dns/DnsClientAsyncState.cs | 120 --------- .../Dns/DnsClientParallelAsyncState.cs | 58 ----- .../Dns/DnsClientParallelState.cs | 30 --- ARSoft.Tools.Net/Dns/DnsMessage.cs | 11 +- ARSoft.Tools.Net/Dns/DnsRecord/DhcpIRecord.cs | 56 ----- ARSoft.Tools.Net/IPAddressExtension.cs | 228 ------------------ ARSoft.Tools.Net/TcpClientExtensions.cs | 5 +- NOTICE | 2 - 10 files changed, 10 insertions(+), 725 deletions(-) delete mode 100644 ARSoft.Tools.Net/Dns/DnsAsyncState.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsClientAsyncState.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsClientParallelAsyncState.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsClientParallelState.cs delete mode 100644 ARSoft.Tools.Net/Dns/DnsRecord/DhcpIRecord.cs delete mode 100644 ARSoft.Tools.Net/IPAddressExtension.cs diff --git a/ARSoft.Tools.Net/ARSoft.Tools.Net.csproj b/ARSoft.Tools.Net/ARSoft.Tools.Net.csproj index 9242c1e..5b0c00d 100644 --- a/ARSoft.Tools.Net/ARSoft.Tools.Net.csproj +++ b/ARSoft.Tools.Net/ARSoft.Tools.Net.csproj @@ -1,116 +1,11 @@ - - + - Debug - AnyCPU - 9.0.30729 - 2.0 - {65BFA748-C640-49B0-B506-34BBB165233A} + net6.0 Library - Properties - ARSoft.Tools.Net - ARSoft.Tools.Net - v4.5 - 512 - - - 3.5 - - 1.2.3.4 - + 1.0.0.0 + false + true - - true - full - false - ..\bin\Debug\ - DEBUG;TRACE - prompt - 4 - true - - - false - false - - - none - true - ..\bin\Release\ - TRACE - prompt - 4 - false - ..\bin\Release\ARSoft.Tools.Net.xml - false - false - 1591 - - - true - D:\arsoft.pfx - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Always @@ -119,17 +14,4 @@ Always - - - - - - - \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsAsyncState.cs b/ARSoft.Tools.Net/Dns/DnsAsyncState.cs deleted file mode 100644 index 9f7dc0a..0000000 --- a/ARSoft.Tools.Net/Dns/DnsAsyncState.cs +++ /dev/null @@ -1,97 +0,0 @@ -#region Copyright and License -// Copyright 2010..2012 Alexander Reinert -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Net.Sockets; -using System.Text; -using System.Threading; - -namespace ARSoft.Tools.Net.Dns -{ - internal class DnsAsyncState : IAsyncResult - { - internal List Servers; - internal int ServerIndex; - internal byte[] QueryData; - internal int QueryLength; - - internal DnsServer.SelectTsigKey TSigKeySelector; - internal byte[] TSigOriginalMac; - - internal DnsMessage Response; - - internal Timer Timer; - internal bool TimedOut; - - private long _timeOutUtcTicks; - - internal long TimeRemaining - { - get - { - long res = (_timeOutUtcTicks - DateTime.UtcNow.Ticks) / TimeSpan.TicksPerMillisecond; - return res > 0 ? res : 0; - } - set { _timeOutUtcTicks = DateTime.UtcNow.Ticks + value * TimeSpan.TicksPerMillisecond; } - } - - internal UdpClient UdpClient; - internal IPEndPoint UdpEndpoint; - - internal TcpClient TcpClient; - internal NetworkStream TcpStream; - internal byte[] TcpBuffer; - internal int TcpBytesToReceive; - - internal AsyncCallback UserCallback; - public object AsyncState { get; internal set; } - public bool IsCompleted { get; private set; } - - public bool CompletedSynchronously - { - get { return false; } - } - - private ManualResetEvent _waitHandle; - - public WaitHandle AsyncWaitHandle - { - get { return _waitHandle ?? (_waitHandle = new ManualResetEvent(IsCompleted)); } - } - - internal void SetCompleted() - { - QueryData = null; - - if (Timer != null) - { - Timer.Dispose(); - Timer = null; - } - - - IsCompleted = true; - if (_waitHandle != null) - _waitHandle.Set(); - - if (UserCallback != null) - UserCallback(this); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsClientAsyncState.cs b/ARSoft.Tools.Net/Dns/DnsClientAsyncState.cs deleted file mode 100644 index 3c93ad4..0000000 --- a/ARSoft.Tools.Net/Dns/DnsClientAsyncState.cs +++ /dev/null @@ -1,120 +0,0 @@ -#region Copyright and License -// Copyright 2010..2014 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (http://arsofttoolsnet.codeplex.com/) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Net.Sockets; -using System.Text; -using System.Threading; - -namespace ARSoft.Tools.Net.Dns -{ - internal class DnsClientAsyncState : IAsyncResult - where TMessage : DnsMessageBase - { - internal List EndpointInfos; - internal int EndpointInfoIndex; - - internal TMessage Query; - internal byte[] QueryData; - internal int QueryLength; - - internal DnsServer.SelectTsigKey TSigKeySelector; - internal byte[] TSigOriginalMac; - - internal TMessage PartialMessage; - internal List Responses; - - internal Timer Timer; - internal bool TimedOut; - - private long _timeOutUtcTicks; - - internal long TimeRemaining - { - get - { - long res = (_timeOutUtcTicks - DateTime.UtcNow.Ticks) / TimeSpan.TicksPerMillisecond; - return res > 0 ? res : 0; - } - set { _timeOutUtcTicks = DateTime.UtcNow.Ticks + value * TimeSpan.TicksPerMillisecond; } - } - - internal System.Net.Sockets.Socket UdpClient; - internal EndPoint UdpEndpoint; - - internal byte[] Buffer; - - internal TcpClient TcpClient; - internal NetworkStream TcpStream; - internal int TcpBytesToReceive; - - internal AsyncCallback UserCallback; - public object AsyncState { get; internal set; } - public bool IsCompleted { get; private set; } - - public bool CompletedSynchronously - { - get { return false; } - } - - private ManualResetEvent _waitHandle; - - public WaitHandle AsyncWaitHandle - { - get { return _waitHandle ?? (_waitHandle = new ManualResetEvent(IsCompleted)); } - } - - internal void SetCompleted() - { - QueryData = null; - - if (Timer != null) - { - Timer.Dispose(); - Timer = null; - } - - IsCompleted = true; - if (_waitHandle != null) - _waitHandle.Set(); - - if (UserCallback != null) - UserCallback(this); - } - - public DnsClientAsyncState CreateTcpCloneWithoutCallback() - { - return - new DnsClientAsyncState - { - EndpointInfos = EndpointInfos, - EndpointInfoIndex = EndpointInfoIndex, - Query = Query, - QueryData = QueryData, - QueryLength = QueryLength, - TSigKeySelector = TSigKeySelector, - TSigOriginalMac = TSigOriginalMac, - Responses = Responses, - _timeOutUtcTicks = _timeOutUtcTicks - }; - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsClientParallelAsyncState.cs b/ARSoft.Tools.Net/Dns/DnsClientParallelAsyncState.cs deleted file mode 100644 index f778aa9..0000000 --- a/ARSoft.Tools.Net/Dns/DnsClientParallelAsyncState.cs +++ /dev/null @@ -1,58 +0,0 @@ -#region Copyright and License -// Copyright 2010..2014 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (http://arsofttoolsnet.codeplex.com/) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Threading; - -namespace ARSoft.Tools.Net.Dns -{ - internal class DnsClientParallelAsyncState : IAsyncResult - where TMessage : DnsMessageBase - { - internal int ResponsesToReceive; - internal List Responses; - - internal AsyncCallback UserCallback; - public object AsyncState { get; internal set; } - public bool IsCompleted { get; private set; } - - public bool CompletedSynchronously - { - get { return false; } - } - - private ManualResetEvent _waitHandle; - - public WaitHandle AsyncWaitHandle - { - get { return _waitHandle ?? (_waitHandle = new ManualResetEvent(IsCompleted)); } - } - - internal void SetCompleted() - { - IsCompleted = true; - - if (_waitHandle != null) - _waitHandle.Set(); - - if (UserCallback != null) - UserCallback(this); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsClientParallelState.cs b/ARSoft.Tools.Net/Dns/DnsClientParallelState.cs deleted file mode 100644 index 755cba5..0000000 --- a/ARSoft.Tools.Net/Dns/DnsClientParallelState.cs +++ /dev/null @@ -1,30 +0,0 @@ -#region Copyright and License -// Copyright 2010..2014 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (http://arsofttoolsnet.codeplex.com/) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; - -namespace ARSoft.Tools.Net.Dns -{ - internal class DnsClientParallelState - where TMessage : DnsMessageBase - { - internal object Lock = new object(); - internal IAsyncResult SingleMessageAsyncResult; - internal DnsClientParallelAsyncState ParallelMessageAsyncState; - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/Dns/DnsMessage.cs b/ARSoft.Tools.Net/Dns/DnsMessage.cs index 3bf7683..482aae2 100644 --- a/ARSoft.Tools.Net/Dns/DnsMessage.cs +++ b/ARSoft.Tools.Net/Dns/DnsMessage.cs @@ -16,17 +16,14 @@ // limitations under the License. #endregion -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; namespace ARSoft.Tools.Net.Dns { - /// - /// Message returned as result to a dns query - /// - public class DnsMessage : DnsMessageBase + /// + /// Message returned as result to a dns query + /// + public class DnsMessage : DnsMessageBase { /// /// Parses a the contents of a byte array as DnsMessage diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/DhcpIRecord.cs b/ARSoft.Tools.Net/Dns/DnsRecord/DhcpIRecord.cs deleted file mode 100644 index c730e33..0000000 --- a/ARSoft.Tools.Net/Dns/DnsRecord/DhcpIRecord.cs +++ /dev/null @@ -1,56 +0,0 @@ -#region Copyright and License -// Copyright 2010..11 Alexander Reinert -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ARSoft.Tools.Net.Dns -{ - public class DhcpIRecord : DnsRecordBase - { - public byte[] RecordData { get; private set; } - - internal DhcpIRecord() {} - - public DhcpIRecord(string name, int timeToLive, byte[] recordData) - : base(name, RecordType.DhcpI, RecordClass.INet, timeToLive) - { - RecordData = recordData ?? new byte[] { }; - } - - internal override void ParseRecordData(byte[] resultData, int startPosition, int length) - { - RecordData = DnsMessageBase.ParseByteData(resultData, ref startPosition, length); - } - - internal override string RecordDataToString() - { - return RecordData.ToBase64String(); - } - - protected internal override int MaximumRecordDataLength - { - get { return RecordData.Length; } - } - - protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary domainNames) - { - DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, RecordData); - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/IPAddressExtension.cs b/ARSoft.Tools.Net/IPAddressExtension.cs deleted file mode 100644 index e946fdf..0000000 --- a/ARSoft.Tools.Net/IPAddressExtension.cs +++ /dev/null @@ -1,228 +0,0 @@ -#region Copyright and License -// Copyright 2010..2014 Alexander Reinert -// -// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (http://arsofttoolsnet.codeplex.com/) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Net.NetworkInformation; -using System.Net.Sockets; -using System.Text; - -namespace ARSoft.Tools.Net -{ - /// - /// Extension class for the class - /// - public static class IPAddressExtension - { - /// - /// Reverses the order of the bytes of an IPAddress - /// - /// Instance of the IPAddress, that should be reversed - /// New instance of IPAddress with reversed address - public static IPAddress Reverse(this IPAddress ipAddress) - { - if (ipAddress == null) - throw new ArgumentNullException("ipAddress"); - - byte[] addressBytes = ipAddress.GetAddressBytes(); - byte[] res = new byte[addressBytes.Length]; - - for (int i = 0; i < res.Length; i++) - { - res[i] = addressBytes[addressBytes.Length - i - 1]; - } - - return new IPAddress(res); - } - - /// - /// Gets the network address for a specified IPAddress and netmask - /// - /// IPAddress, for that the network address should be returned - /// Netmask, that should be used - /// New instance of IPAddress with the network address assigend - public static IPAddress GetNetworkAddress(this IPAddress ipAddress, IPAddress netmask) - { - if (ipAddress == null) - throw new ArgumentNullException("ipAddress"); - - if (netmask == null) - throw new ArgumentNullException("netMask"); - - if (ipAddress.AddressFamily != netmask.AddressFamily) - throw new ArgumentOutOfRangeException("netmask", "Protocoll version of ipAddress and netmask do not match"); - - byte[] resultBytes = ipAddress.GetAddressBytes(); - byte[] ipAddressBytes = ipAddress.GetAddressBytes(); - byte[] netmaskBytes = netmask.GetAddressBytes(); - - for (int i = 0; i < netmaskBytes.Length; i++) - { - resultBytes[i] = (byte) (ipAddressBytes[i] & netmaskBytes[i]); - } - - return new IPAddress(resultBytes); - } - - /// - /// Gets the network address for a specified IPAddress and netmask - /// - /// IPAddress, for that the network address should be returned - /// Netmask in CIDR format - /// New instance of IPAddress with the network address assigend - public static IPAddress GetNetworkAddress(this IPAddress ipAddress, int netmask) - { - if (ipAddress == null) - throw new ArgumentNullException("ipAddress"); - - if ((ipAddress.AddressFamily == AddressFamily.InterNetwork) && ((netmask < 0) || (netmask > 32))) - throw new ArgumentException("Netmask have to be in range of 0 to 32 on IPv4 addresses", "netmask"); - - if ((ipAddress.AddressFamily == AddressFamily.InterNetworkV6) && ((netmask < 0) || (netmask > 128))) - throw new ArgumentException("Netmask have to be in range of 0 to 128 on IPv6 addresses", "netmask"); - - byte[] ipAddressBytes = ipAddress.GetAddressBytes(); - - for (int i = 0; i < ipAddressBytes.Length; i++) - { - if (netmask >= 8) - { - netmask -= 8; - } - else - { - if (BitConverter.IsLittleEndian) - { - ipAddressBytes[i] &= ReverseBitOrder((byte) ~(255 << netmask)); - } - netmask = 0; - } - } - - return new IPAddress(ipAddressBytes); - } - - /// - /// Returns the reverse lookup address of an IPAddress - /// - /// Instance of the IPAddress, that should be used - /// A string with the reverse lookup address - public static string GetReverseLookupAddress(this IPAddress ipAddress) - { - if (ipAddress == null) - throw new ArgumentNullException("ipAddress"); - - StringBuilder res = new StringBuilder(); - - byte[] addressBytes = ipAddress.GetAddressBytes(); - - if (ipAddress.AddressFamily == AddressFamily.InterNetwork) - { - for (int i = addressBytes.Length - 1; i >= 0; i--) - { - res.Append(addressBytes[i]); - res.Append("."); - } - res.Append("in-addr.arpa"); - } - else - { - for (int i = addressBytes.Length - 1; i >= 0; i--) - { - string hex = addressBytes[i].ToString("x2"); - res.Append(hex[1]); - res.Append("."); - res.Append(hex[0]); - res.Append("."); - } - - res.Append("ip6.arpa"); - } - - return res.ToString(); - } - - private static readonly IPAddress _ipv4MulticastNetworkAddress = IPAddress.Parse("224.0.0.0"); - private static readonly IPAddress _ipv6MulticastNetworkAddress = IPAddress.Parse("FF00::"); - - /// - /// Returns a value indicating whether a ip address is a multicast address - /// - /// Instance of the IPAddress, that should be used - /// true, if the given address is a multicast address; otherwise, false - public static bool IsMulticast(this IPAddress ipAddress) - { - if (ipAddress == null) - throw new ArgumentNullException("ipAddress"); - - if (ipAddress.AddressFamily == AddressFamily.InterNetwork) - { - return ipAddress.GetNetworkAddress(4).Equals(_ipv4MulticastNetworkAddress); - } - else - { - return ipAddress.GetNetworkAddress(8).Equals(_ipv6MulticastNetworkAddress); - } - } - - /// - /// Returns the index for the interface which has the ip address assigned - /// - /// The ip address to look for - /// The index for the interface which has the ip address assigned - public static int GetInterfaceIndex(this IPAddress ipAddress) - { - if (ipAddress == null) - throw new ArgumentNullException("ipAddress"); - - var interfaceProperty = NetworkInterface.GetAllNetworkInterfaces().Select(n => n.GetIPProperties()).FirstOrDefault(p => p.UnicastAddresses.Any(a => a.Address.Equals(ipAddress))); - - if (interfaceProperty != null) - { - if (ipAddress.AddressFamily == AddressFamily.InterNetwork) - { - var property = interfaceProperty.GetIPv4Properties(); - if (property != null) - return property.Index; - } - else - { - var property = interfaceProperty.GetIPv6Properties(); - if (property != null) - return property.Index; - } - } - - throw new ArgumentOutOfRangeException("ipAddress", "The given ip address is not configured on the local system"); - } - - private static byte ReverseBitOrder(byte value) - { - byte result = 0; - - for (int i = 0; i < 8; i++) - { - result |= (byte) ((((1 << i) & value) >> i) << (7 - i)); - } - - return result; - } - } -} \ No newline at end of file diff --git a/ARSoft.Tools.Net/TcpClientExtensions.cs b/ARSoft.Tools.Net/TcpClientExtensions.cs index b3f70a8..0b9ba11 100644 --- a/ARSoft.Tools.Net/TcpClientExtensions.cs +++ b/ARSoft.Tools.Net/TcpClientExtensions.cs @@ -17,17 +17,14 @@ #endregion using System; -using System.Collections.Generic; -using System.Linq; using System.Net; using System.Net.Sockets; -using System.Text; using System.Threading; using System.Threading.Tasks; namespace ARSoft.Tools.Net { - internal static class TcpClientExtensions + internal static class TcpClientExtensions { public static bool TryConnect(this TcpClient tcpClient, IPEndPoint endPoint, int timeout) { diff --git a/NOTICE b/NOTICE index aebb878..3e173ba 100644 --- a/NOTICE +++ b/NOTICE @@ -1,3 +1 @@ ARSoft.Tools.Net - C# DNS client/server and SPF Library, Copyright (c) 2010-2017 Alexander Reinert (https://github.com/alexreinert/ARSoft.Tools.Net) - -The library uses the Bouncy Castle C# API, Copyright (c) 2000-2016 The Legion of the Bouncy Castle Inc. (http://www.bouncycastle.org/csharp/) From 47093afe4a640e5c2c54c81a074f644758a6c9f1 Mon Sep 17 00:00:00 2001 From: Alistair Evans Date: Mon, 13 Dec 2021 11:22:46 +0000 Subject: [PATCH 5/6] Add build flow, move some packages around, etc. --- .github/workflows/build.yml | 52 +++++++++++++++++++ ARSoft.Tools.Net.sln | 20 ------- Enclave.ARSoft.Tools.Net.sln | 31 +++++++++++ GitVersion.yml | 11 ++++ .../AsyncEventHandler.cs | 0 .../AsyncEventHandlerExtensions.cs | 0 .../Enclave.ARSoft.Tools.Net}/BaseEncoding.cs | 0 .../Dns/ClientConnectedEventArgs.cs | 0 .../Dns/DnsMessage.cs | 0 .../Dns/DnsMessageBase.cs | 0 .../Dns/DnsMessageEntryBase.cs | 0 .../Dns/DnsQueryOptions.cs | 0 .../Dns/DnsQuestion.cs | 0 .../Dns/DnsRecord/ARecord.cs | 0 .../Dns/DnsRecord/AaaaRecord.cs | 0 .../Dns/DnsRecord/AddressRecordBase.cs | 0 .../Dns/DnsRecord/CNameRecord.cs | 0 .../Dns/DnsRecord/DnsRecordBase.cs | 0 .../Dns/DnsRecord/Eui48Record.cs | 0 .../Dns/DnsRecord/Eui64Record.cs | 0 .../Dns/DnsRecord/IAddressRecord.cs | 0 .../Dns/DnsRecord/ITextRecord.cs | 0 .../Dns/DnsRecord/LocRecord.cs | 0 .../Dns/DnsRecord/MxRecord.cs | 0 .../Dns/DnsRecord/NaptrRecord.cs | 0 .../Dns/DnsRecord/NsRecord.cs | 0 .../Dns/DnsRecord/PtrRecord.cs | 0 .../Dns/DnsRecord/RpRecord.cs | 0 .../Dns/DnsRecord/SoaRecord.cs | 0 .../Dns/DnsRecord/SrvRecord.cs | 0 .../Dns/DnsRecord/TextRecordBase.cs | 0 .../Dns/DnsRecord/TxtRecord.cs | 0 .../Dns/DnsRecord/UnknownRecord.cs | 0 .../Dns/DnsServer.cs | 0 .../Dns/DynamicUpdate/AddRecordUpdate.cs | 0 .../DynamicUpdate/DeleteAllRecordsUpdate.cs | 0 .../Dns/DynamicUpdate/DeleteRecordUpdate.cs | 0 .../Dns/DynamicUpdate/DnsUpdateMessage.cs | 0 .../DynamicUpdate/NameIsInUsePrequisite.cs | 0 .../DynamicUpdate/NameIsNotInUsePrequisite.cs | 0 .../Dns/DynamicUpdate/PrequisiteBase.cs | 0 .../DynamicUpdate/RecordExistsPrequisite.cs | 0 .../RecordNotExistsPrequisite.cs | 0 .../Dns/DynamicUpdate/UpdateBase.cs | 0 .../Dns/ExceptionEventArgs.cs | 0 .../Dns/InvalidSignedMessageEventArgs.cs | 0 .../Dns/OperationCode.cs | 0 .../Dns/QueryReceivedEventArgs.cs | 0 .../Dns/RecordClass.cs | 0 .../Dns/RecordType.cs | 0 .../Dns/ReturnCode.cs | 0 .../Enclave.ARSoft.Tools.Net}/Dns/Zone.cs | 0 .../Enclave.ARSoft.Tools.Net}/DomainName.cs | 0 .../Enclave.ARSoft.Tools.Net.csproj | 7 +-- .../Enclave.ARSoft.Tools.Net}/EnumHelper.cs | 0 .../EventHandlerExtensions.cs | 0 .../IPAddressExtensions.cs | 0 .../Properties/AssemblyInfo.cs | 0 .../Socket/UdpListener.cs | 0 .../StringExtensions.cs | 0 .../TcpClientExtensions.cs | 0 .../UdpClientExtensions.cs | 0 62 files changed, 98 insertions(+), 23 deletions(-) create mode 100644 .github/workflows/build.yml delete mode 100644 ARSoft.Tools.Net.sln create mode 100644 Enclave.ARSoft.Tools.Net.sln create mode 100644 GitVersion.yml rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/AsyncEventHandler.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/AsyncEventHandlerExtensions.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/BaseEncoding.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/ClientConnectedEventArgs.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/DnsMessage.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/DnsMessageBase.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/DnsMessageEntryBase.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/DnsQueryOptions.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/DnsQuestion.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/DnsRecord/ARecord.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/DnsRecord/AaaaRecord.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/DnsRecord/AddressRecordBase.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/DnsRecord/CNameRecord.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/DnsRecord/DnsRecordBase.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/DnsRecord/Eui48Record.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/DnsRecord/Eui64Record.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/DnsRecord/IAddressRecord.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/DnsRecord/ITextRecord.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/DnsRecord/LocRecord.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/DnsRecord/MxRecord.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/DnsRecord/NaptrRecord.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/DnsRecord/NsRecord.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/DnsRecord/PtrRecord.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/DnsRecord/RpRecord.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/DnsRecord/SoaRecord.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/DnsRecord/SrvRecord.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/DnsRecord/TextRecordBase.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/DnsRecord/TxtRecord.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/DnsRecord/UnknownRecord.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/DnsServer.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/DynamicUpdate/AddRecordUpdate.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/DynamicUpdate/DeleteAllRecordsUpdate.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/DynamicUpdate/DeleteRecordUpdate.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/DynamicUpdate/DnsUpdateMessage.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/DynamicUpdate/NameIsInUsePrequisite.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/DynamicUpdate/NameIsNotInUsePrequisite.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/DynamicUpdate/PrequisiteBase.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/DynamicUpdate/RecordExistsPrequisite.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/DynamicUpdate/RecordNotExistsPrequisite.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/DynamicUpdate/UpdateBase.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/ExceptionEventArgs.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/InvalidSignedMessageEventArgs.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/OperationCode.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/QueryReceivedEventArgs.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/RecordClass.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/RecordType.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/ReturnCode.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Dns/Zone.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/DomainName.cs (100%) rename ARSoft.Tools.Net/ARSoft.Tools.Net.csproj => src/Enclave.ARSoft.Tools.Net/Enclave.ARSoft.Tools.Net.csproj (68%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/EnumHelper.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/EventHandlerExtensions.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/IPAddressExtensions.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Properties/AssemblyInfo.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/Socket/UdpListener.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/StringExtensions.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/TcpClientExtensions.cs (100%) rename {ARSoft.Tools.Net => src/Enclave.ARSoft.Tools.Net}/UdpClientExtensions.cs (100%) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..45b8f27 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,52 @@ +name: Build + +on: + push: + branches: [ develop, master ] + pull_request: + branches: [ develop ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Install GitVersion + uses: gittools/actions/gitversion/setup@v0.9.7 + with: + versionSpec: '5.x' + + - name: Determine Version + id: gitversion + uses: gittools/actions/gitversion/execute@v0.9.7 + + - name: Setup .NET 6 (SDK) + uses: actions/setup-dotnet@v1 + with: + dotnet-version: 6.0.x + source-url: https://nuget.pkg.github.com/enclave-networks/index.json + env: + NUGET_AUTH_TOKEN: ${{github.token}} + + - name: Build + run: dotnet build -c Release /p:Version=${{ steps.gitversion.outputs.SemVer }} + + - name: Push Github Source Packages + if: github.event_name == 'push' + run: dotnet nuget push src/**/*${{ steps.gitversion.outputs.SemVer }}.nupkg --api-key ${{github.token}} -s https://nuget.pkg.github.com/enclave-networks/index.json --skip-duplicate --no-symbols true + + - name: Create Release + if: github.event_name == 'push' && github.ref == 'refs/heads/master' + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: v${{ steps.gitversion.outputs.SemVer }} + release_name: Release v${{ steps.gitversion.outputs.SemVer }} + body: Latest SDK Release \ No newline at end of file diff --git a/ARSoft.Tools.Net.sln b/ARSoft.Tools.Net.sln deleted file mode 100644 index 41a083e..0000000 --- a/ARSoft.Tools.Net.sln +++ /dev/null @@ -1,20 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ARSoft.Tools.Net", "ARSoft.Tools.Net\ARSoft.Tools.Net.csproj", "{65BFA748-C640-49B0-B506-34BBB165233A}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {65BFA748-C640-49B0-B506-34BBB165233A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {65BFA748-C640-49B0-B506-34BBB165233A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {65BFA748-C640-49B0-B506-34BBB165233A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {65BFA748-C640-49B0-B506-34BBB165233A}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/Enclave.ARSoft.Tools.Net.sln b/Enclave.ARSoft.Tools.Net.sln new file mode 100644 index 0000000..603974b --- /dev/null +++ b/Enclave.ARSoft.Tools.Net.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{79AA3194-4E39-415B-A737-A3D7421EF59A}" + ProjectSection(SolutionItems) = preProject + .github\workflows\build.yml = .github\workflows\build.yml + GitVersion.yml = GitVersion.yml + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Enclave.ARSoft.Tools.Net", "src\Enclave.ARSoft.Tools.Net\Enclave.ARSoft.Tools.Net.csproj", "{31DB8445-094F-4727-B847-ED9CFE6B0778}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {31DB8445-094F-4727-B847-ED9CFE6B0778}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {31DB8445-094F-4727-B847-ED9CFE6B0778}.Debug|Any CPU.Build.0 = Debug|Any CPU + {31DB8445-094F-4727-B847-ED9CFE6B0778}.Release|Any CPU.ActiveCfg = Release|Any CPU + {31DB8445-094F-4727-B847-ED9CFE6B0778}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {7D83AF96-71EE-44F9-95FC-C4559F160D9A} + EndGlobalSection +EndGlobal diff --git a/GitVersion.yml b/GitVersion.yml new file mode 100644 index 0000000..fc20495 --- /dev/null +++ b/GitVersion.yml @@ -0,0 +1,11 @@ +assembly-versioning-scheme: None +mode: ContinuousDelivery +next-version: 1.0.0 +branches: + master: + mode: ContinuousDelivery + develop: + increment: Patch +ignore: + sha: [] +merge-message-formats: {} diff --git a/ARSoft.Tools.Net/AsyncEventHandler.cs b/src/Enclave.ARSoft.Tools.Net/AsyncEventHandler.cs similarity index 100% rename from ARSoft.Tools.Net/AsyncEventHandler.cs rename to src/Enclave.ARSoft.Tools.Net/AsyncEventHandler.cs diff --git a/ARSoft.Tools.Net/AsyncEventHandlerExtensions.cs b/src/Enclave.ARSoft.Tools.Net/AsyncEventHandlerExtensions.cs similarity index 100% rename from ARSoft.Tools.Net/AsyncEventHandlerExtensions.cs rename to src/Enclave.ARSoft.Tools.Net/AsyncEventHandlerExtensions.cs diff --git a/ARSoft.Tools.Net/BaseEncoding.cs b/src/Enclave.ARSoft.Tools.Net/BaseEncoding.cs similarity index 100% rename from ARSoft.Tools.Net/BaseEncoding.cs rename to src/Enclave.ARSoft.Tools.Net/BaseEncoding.cs diff --git a/ARSoft.Tools.Net/Dns/ClientConnectedEventArgs.cs b/src/Enclave.ARSoft.Tools.Net/Dns/ClientConnectedEventArgs.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/ClientConnectedEventArgs.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/ClientConnectedEventArgs.cs diff --git a/ARSoft.Tools.Net/Dns/DnsMessage.cs b/src/Enclave.ARSoft.Tools.Net/Dns/DnsMessage.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/DnsMessage.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/DnsMessage.cs diff --git a/ARSoft.Tools.Net/Dns/DnsMessageBase.cs b/src/Enclave.ARSoft.Tools.Net/Dns/DnsMessageBase.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/DnsMessageBase.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/DnsMessageBase.cs diff --git a/ARSoft.Tools.Net/Dns/DnsMessageEntryBase.cs b/src/Enclave.ARSoft.Tools.Net/Dns/DnsMessageEntryBase.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/DnsMessageEntryBase.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/DnsMessageEntryBase.cs diff --git a/ARSoft.Tools.Net/Dns/DnsQueryOptions.cs b/src/Enclave.ARSoft.Tools.Net/Dns/DnsQueryOptions.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/DnsQueryOptions.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/DnsQueryOptions.cs diff --git a/ARSoft.Tools.Net/Dns/DnsQuestion.cs b/src/Enclave.ARSoft.Tools.Net/Dns/DnsQuestion.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/DnsQuestion.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/DnsQuestion.cs diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/ARecord.cs b/src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/ARecord.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/DnsRecord/ARecord.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/ARecord.cs diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/AaaaRecord.cs b/src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/AaaaRecord.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/DnsRecord/AaaaRecord.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/AaaaRecord.cs diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/AddressRecordBase.cs b/src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/AddressRecordBase.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/DnsRecord/AddressRecordBase.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/AddressRecordBase.cs diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/CNameRecord.cs b/src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/CNameRecord.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/DnsRecord/CNameRecord.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/CNameRecord.cs diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/DnsRecordBase.cs b/src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/DnsRecordBase.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/DnsRecord/DnsRecordBase.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/DnsRecordBase.cs diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/Eui48Record.cs b/src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/Eui48Record.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/DnsRecord/Eui48Record.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/Eui48Record.cs diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/Eui64Record.cs b/src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/Eui64Record.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/DnsRecord/Eui64Record.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/Eui64Record.cs diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/IAddressRecord.cs b/src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/IAddressRecord.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/DnsRecord/IAddressRecord.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/IAddressRecord.cs diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/ITextRecord.cs b/src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/ITextRecord.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/DnsRecord/ITextRecord.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/ITextRecord.cs diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/LocRecord.cs b/src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/LocRecord.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/DnsRecord/LocRecord.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/LocRecord.cs diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/MxRecord.cs b/src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/MxRecord.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/DnsRecord/MxRecord.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/MxRecord.cs diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/NaptrRecord.cs b/src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/NaptrRecord.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/DnsRecord/NaptrRecord.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/NaptrRecord.cs diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/NsRecord.cs b/src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/NsRecord.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/DnsRecord/NsRecord.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/NsRecord.cs diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/PtrRecord.cs b/src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/PtrRecord.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/DnsRecord/PtrRecord.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/PtrRecord.cs diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/RpRecord.cs b/src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/RpRecord.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/DnsRecord/RpRecord.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/RpRecord.cs diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/SoaRecord.cs b/src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/SoaRecord.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/DnsRecord/SoaRecord.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/SoaRecord.cs diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/SrvRecord.cs b/src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/SrvRecord.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/DnsRecord/SrvRecord.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/SrvRecord.cs diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/TextRecordBase.cs b/src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/TextRecordBase.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/DnsRecord/TextRecordBase.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/TextRecordBase.cs diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/TxtRecord.cs b/src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/TxtRecord.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/DnsRecord/TxtRecord.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/TxtRecord.cs diff --git a/ARSoft.Tools.Net/Dns/DnsRecord/UnknownRecord.cs b/src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/UnknownRecord.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/DnsRecord/UnknownRecord.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/DnsRecord/UnknownRecord.cs diff --git a/ARSoft.Tools.Net/Dns/DnsServer.cs b/src/Enclave.ARSoft.Tools.Net/Dns/DnsServer.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/DnsServer.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/DnsServer.cs diff --git a/ARSoft.Tools.Net/Dns/DynamicUpdate/AddRecordUpdate.cs b/src/Enclave.ARSoft.Tools.Net/Dns/DynamicUpdate/AddRecordUpdate.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/DynamicUpdate/AddRecordUpdate.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/DynamicUpdate/AddRecordUpdate.cs diff --git a/ARSoft.Tools.Net/Dns/DynamicUpdate/DeleteAllRecordsUpdate.cs b/src/Enclave.ARSoft.Tools.Net/Dns/DynamicUpdate/DeleteAllRecordsUpdate.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/DynamicUpdate/DeleteAllRecordsUpdate.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/DynamicUpdate/DeleteAllRecordsUpdate.cs diff --git a/ARSoft.Tools.Net/Dns/DynamicUpdate/DeleteRecordUpdate.cs b/src/Enclave.ARSoft.Tools.Net/Dns/DynamicUpdate/DeleteRecordUpdate.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/DynamicUpdate/DeleteRecordUpdate.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/DynamicUpdate/DeleteRecordUpdate.cs diff --git a/ARSoft.Tools.Net/Dns/DynamicUpdate/DnsUpdateMessage.cs b/src/Enclave.ARSoft.Tools.Net/Dns/DynamicUpdate/DnsUpdateMessage.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/DynamicUpdate/DnsUpdateMessage.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/DynamicUpdate/DnsUpdateMessage.cs diff --git a/ARSoft.Tools.Net/Dns/DynamicUpdate/NameIsInUsePrequisite.cs b/src/Enclave.ARSoft.Tools.Net/Dns/DynamicUpdate/NameIsInUsePrequisite.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/DynamicUpdate/NameIsInUsePrequisite.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/DynamicUpdate/NameIsInUsePrequisite.cs diff --git a/ARSoft.Tools.Net/Dns/DynamicUpdate/NameIsNotInUsePrequisite.cs b/src/Enclave.ARSoft.Tools.Net/Dns/DynamicUpdate/NameIsNotInUsePrequisite.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/DynamicUpdate/NameIsNotInUsePrequisite.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/DynamicUpdate/NameIsNotInUsePrequisite.cs diff --git a/ARSoft.Tools.Net/Dns/DynamicUpdate/PrequisiteBase.cs b/src/Enclave.ARSoft.Tools.Net/Dns/DynamicUpdate/PrequisiteBase.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/DynamicUpdate/PrequisiteBase.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/DynamicUpdate/PrequisiteBase.cs diff --git a/ARSoft.Tools.Net/Dns/DynamicUpdate/RecordExistsPrequisite.cs b/src/Enclave.ARSoft.Tools.Net/Dns/DynamicUpdate/RecordExistsPrequisite.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/DynamicUpdate/RecordExistsPrequisite.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/DynamicUpdate/RecordExistsPrequisite.cs diff --git a/ARSoft.Tools.Net/Dns/DynamicUpdate/RecordNotExistsPrequisite.cs b/src/Enclave.ARSoft.Tools.Net/Dns/DynamicUpdate/RecordNotExistsPrequisite.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/DynamicUpdate/RecordNotExistsPrequisite.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/DynamicUpdate/RecordNotExistsPrequisite.cs diff --git a/ARSoft.Tools.Net/Dns/DynamicUpdate/UpdateBase.cs b/src/Enclave.ARSoft.Tools.Net/Dns/DynamicUpdate/UpdateBase.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/DynamicUpdate/UpdateBase.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/DynamicUpdate/UpdateBase.cs diff --git a/ARSoft.Tools.Net/Dns/ExceptionEventArgs.cs b/src/Enclave.ARSoft.Tools.Net/Dns/ExceptionEventArgs.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/ExceptionEventArgs.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/ExceptionEventArgs.cs diff --git a/ARSoft.Tools.Net/Dns/InvalidSignedMessageEventArgs.cs b/src/Enclave.ARSoft.Tools.Net/Dns/InvalidSignedMessageEventArgs.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/InvalidSignedMessageEventArgs.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/InvalidSignedMessageEventArgs.cs diff --git a/ARSoft.Tools.Net/Dns/OperationCode.cs b/src/Enclave.ARSoft.Tools.Net/Dns/OperationCode.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/OperationCode.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/OperationCode.cs diff --git a/ARSoft.Tools.Net/Dns/QueryReceivedEventArgs.cs b/src/Enclave.ARSoft.Tools.Net/Dns/QueryReceivedEventArgs.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/QueryReceivedEventArgs.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/QueryReceivedEventArgs.cs diff --git a/ARSoft.Tools.Net/Dns/RecordClass.cs b/src/Enclave.ARSoft.Tools.Net/Dns/RecordClass.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/RecordClass.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/RecordClass.cs diff --git a/ARSoft.Tools.Net/Dns/RecordType.cs b/src/Enclave.ARSoft.Tools.Net/Dns/RecordType.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/RecordType.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/RecordType.cs diff --git a/ARSoft.Tools.Net/Dns/ReturnCode.cs b/src/Enclave.ARSoft.Tools.Net/Dns/ReturnCode.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/ReturnCode.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/ReturnCode.cs diff --git a/ARSoft.Tools.Net/Dns/Zone.cs b/src/Enclave.ARSoft.Tools.Net/Dns/Zone.cs similarity index 100% rename from ARSoft.Tools.Net/Dns/Zone.cs rename to src/Enclave.ARSoft.Tools.Net/Dns/Zone.cs diff --git a/ARSoft.Tools.Net/DomainName.cs b/src/Enclave.ARSoft.Tools.Net/DomainName.cs similarity index 100% rename from ARSoft.Tools.Net/DomainName.cs rename to src/Enclave.ARSoft.Tools.Net/DomainName.cs diff --git a/ARSoft.Tools.Net/ARSoft.Tools.Net.csproj b/src/Enclave.ARSoft.Tools.Net/Enclave.ARSoft.Tools.Net.csproj similarity index 68% rename from ARSoft.Tools.Net/ARSoft.Tools.Net.csproj rename to src/Enclave.ARSoft.Tools.Net/Enclave.ARSoft.Tools.Net.csproj index 5b0c00d..64f42ab 100644 --- a/ARSoft.Tools.Net/ARSoft.Tools.Net.csproj +++ b/src/Enclave.ARSoft.Tools.Net/Enclave.ARSoft.Tools.Net.csproj @@ -2,15 +2,16 @@ net6.0 Library - 1.0.0.0 false true + true + https://github.com/enclave-networks/arsoft.tools.net - + Always - + Always diff --git a/ARSoft.Tools.Net/EnumHelper.cs b/src/Enclave.ARSoft.Tools.Net/EnumHelper.cs similarity index 100% rename from ARSoft.Tools.Net/EnumHelper.cs rename to src/Enclave.ARSoft.Tools.Net/EnumHelper.cs diff --git a/ARSoft.Tools.Net/EventHandlerExtensions.cs b/src/Enclave.ARSoft.Tools.Net/EventHandlerExtensions.cs similarity index 100% rename from ARSoft.Tools.Net/EventHandlerExtensions.cs rename to src/Enclave.ARSoft.Tools.Net/EventHandlerExtensions.cs diff --git a/ARSoft.Tools.Net/IPAddressExtensions.cs b/src/Enclave.ARSoft.Tools.Net/IPAddressExtensions.cs similarity index 100% rename from ARSoft.Tools.Net/IPAddressExtensions.cs rename to src/Enclave.ARSoft.Tools.Net/IPAddressExtensions.cs diff --git a/ARSoft.Tools.Net/Properties/AssemblyInfo.cs b/src/Enclave.ARSoft.Tools.Net/Properties/AssemblyInfo.cs similarity index 100% rename from ARSoft.Tools.Net/Properties/AssemblyInfo.cs rename to src/Enclave.ARSoft.Tools.Net/Properties/AssemblyInfo.cs diff --git a/ARSoft.Tools.Net/Socket/UdpListener.cs b/src/Enclave.ARSoft.Tools.Net/Socket/UdpListener.cs similarity index 100% rename from ARSoft.Tools.Net/Socket/UdpListener.cs rename to src/Enclave.ARSoft.Tools.Net/Socket/UdpListener.cs diff --git a/ARSoft.Tools.Net/StringExtensions.cs b/src/Enclave.ARSoft.Tools.Net/StringExtensions.cs similarity index 100% rename from ARSoft.Tools.Net/StringExtensions.cs rename to src/Enclave.ARSoft.Tools.Net/StringExtensions.cs diff --git a/ARSoft.Tools.Net/TcpClientExtensions.cs b/src/Enclave.ARSoft.Tools.Net/TcpClientExtensions.cs similarity index 100% rename from ARSoft.Tools.Net/TcpClientExtensions.cs rename to src/Enclave.ARSoft.Tools.Net/TcpClientExtensions.cs diff --git a/ARSoft.Tools.Net/UdpClientExtensions.cs b/src/Enclave.ARSoft.Tools.Net/UdpClientExtensions.cs similarity index 100% rename from ARSoft.Tools.Net/UdpClientExtensions.cs rename to src/Enclave.ARSoft.Tools.Net/UdpClientExtensions.cs From bed082f0710eced8461a006edf5b8872688c815e Mon Sep 17 00:00:00 2001 From: Alistair Evans Date: Mon, 13 Dec 2021 11:35:29 +0000 Subject: [PATCH 6/6] Change build branch --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 45b8f27..a7e5e30 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,9 +2,9 @@ name: Build on: push: - branches: [ develop, master ] + branches: [ master ] pull_request: - branches: [ develop ] + branches: [ master ] jobs: build: