diff --git a/DnsServerCore/Dns/Zones/AuthZoneInfo.cs b/DnsServerCore/Dns/Zones/AuthZoneInfo.cs index 068d637b..036f6ddd 100644 --- a/DnsServerCore/Dns/Zones/AuthZoneInfo.cs +++ b/DnsServerCore/Dns/Zones/AuthZoneInfo.cs @@ -24,7 +24,6 @@ using System.Collections.Generic; using System.IO; using System.Net; using System.Net.Sockets; -using System.Threading.Tasks; using TechnitiumLibrary.IO; using TechnitiumLibrary.Net; using TechnitiumLibrary.Net.Dns; @@ -38,7 +37,10 @@ namespace DnsServerCore.Dns.Zones Primary = 1, Secondary = 2, Stub = 3, - Forwarder = 4 + Forwarder = 4, + SecondaryForwarder = 5, + Catalog = 6, + SecondaryCatalog = 7 } public sealed class AuthZoneInfo : IComparable @@ -49,20 +51,40 @@ namespace DnsServerCore.Dns.Zones readonly string _name; readonly AuthZoneType _type; + readonly DateTime _lastModified; readonly bool _disabled; + + readonly string _catalogZoneName; + readonly bool _overrideCatalogQueryAccess; + readonly bool _overrideCatalogZoneTransfer; + readonly bool _overrideCatalogNotify; + readonly bool _overrideCatalogPrimaryNameServers; //only for secondary zones + + readonly AuthZoneQueryAccess _queryAccess; + readonly IReadOnlyCollection _queryAccessNetworkACL; + readonly AuthZoneTransfer _zoneTransfer; - readonly IReadOnlyCollection _zoneTransferNameServers; + readonly IReadOnlyCollection _zoneTransferNetworkACL; + readonly IReadOnlyDictionary _zoneTransferTsigKeyNames; + readonly IReadOnlyList _zoneHistory; //for IXFR support + readonly AuthZoneNotify _notify; readonly IReadOnlyCollection _notifyNameServers; + readonly AuthZoneUpdate _update; - readonly IReadOnlyCollection _updateIpAddresses; - readonly DateTime _lastModified; - readonly DateTime _expiry; - readonly bool _validationFailed; //only for secondary zones - readonly IReadOnlyList _zoneHistory; //for IXFR support - readonly IReadOnlyDictionary _zoneTransferTsigKeyNames; + readonly IReadOnlyCollection _updateNetworkACL; readonly IReadOnlyDictionary>> _updateSecurityPolicies; - readonly IReadOnlyCollection _dnssecPrivateKeys; + + readonly IReadOnlyCollection _dnssecPrivateKeys; //only for primary zones + + readonly IReadOnlyList _primaryNameServerAddresses; //only for secondary and stub zones + readonly DnsTransportProtocol _primaryZoneTransferProtocol; //only for secondary zones + readonly string _primaryZoneTransferTsigKeyName; //only for secondary zones + + readonly DateTime _expiry; //only for secondary and stub zones + + readonly bool _validateZone; //only for secondary zones + readonly bool _validationFailed; //only for secondary zones #endregion @@ -72,7 +94,9 @@ namespace DnsServerCore.Dns.Zones { _name = name; _type = type; + _lastModified = DateTime.UtcNow; _disabled = disabled; + _queryAccess = AuthZoneQueryAccess.Allow; switch (_type) { @@ -106,338 +130,497 @@ namespace DnsServerCore.Dns.Zones case 9: case 10: case 11: - case 12: - _name = bR.ReadShortString(); - _type = (AuthZoneType)bR.ReadByte(); - _disabled = bR.ReadBoolean(); - - if (version >= 2) { + _name = bR.ReadShortString(); + _type = (AuthZoneType)bR.ReadByte(); + _disabled = bR.ReadBoolean(); + + _queryAccess = AuthZoneQueryAccess.Allow; + + if (version >= 2) { - _zoneTransfer = (AuthZoneTransfer)bR.ReadByte(); - - int count = bR.ReadByte(); - if (count > 0) { - NetworkAddress[] networks = new NetworkAddress[count]; + _zoneTransfer = (AuthZoneTransfer)bR.ReadByte(); - if (version >= 9) - { - for (int i = 0; i < count; i++) - networks[i] = NetworkAddress.ReadFrom(bR); - } - else - { - for (int i = 0; i < count; i++) - { - IPAddress address = IPAddressExtensions.ReadFrom(bR); - - switch (address.AddressFamily) - { - case AddressFamily.InterNetwork: - networks[i] = new NetworkAddress(address, 32); - break; - - case AddressFamily.InterNetworkV6: - networks[i] = new NetworkAddress(address, 128); - break; - - default: - throw new InvalidOperationException(); - } - } - } - - _zoneTransferNameServers = networks; - } - } - - { - _notify = (AuthZoneNotify)bR.ReadByte(); - - int count = bR.ReadByte(); - if (count > 0) - { - IPAddress[] nameServers = new IPAddress[count]; - - for (int i = 0; i < count; i++) - nameServers[i] = IPAddressExtensions.ReadFrom(bR); - - _notifyNameServers = nameServers; - } - } - - if (version >= 6) - { - _update = (AuthZoneUpdate)bR.ReadByte(); - - int count = bR.ReadByte(); - if (count > 0) - { - NetworkAddress[] networks = new NetworkAddress[count]; - - if (version >= 9) - { - for (int i = 0; i < count; i++) - networks[i] = NetworkAddress.ReadFrom(bR); - } - else - { - for (int i = 0; i < count; i++) - { - IPAddress address = IPAddressExtensions.ReadFrom(bR); - - switch (address.AddressFamily) - { - case AddressFamily.InterNetwork: - networks[i] = new NetworkAddress(address, 32); - break; - - case AddressFamily.InterNetworkV6: - networks[i] = new NetworkAddress(address, 128); - break; - - default: - throw new InvalidOperationException(); - } - } - } - - _updateIpAddresses = networks; - } - } - } - else - { - switch (_type) - { - case AuthZoneType.Primary: - _zoneTransfer = AuthZoneTransfer.AllowOnlyZoneNameServers; - _notify = AuthZoneNotify.ZoneNameServers; - _update = AuthZoneUpdate.Deny; - break; - - default: - _zoneTransfer = AuthZoneTransfer.Deny; - _notify = AuthZoneNotify.None; - _update = AuthZoneUpdate.Deny; - break; - } - } - - if (version >= 8) - _lastModified = bR.ReadDateTime(); - else - _lastModified = lastModified; - - switch (_type) - { - case AuthZoneType.Primary: - if (version >= 3) - { - int count = bR.ReadInt32(); - DnsResourceRecord[] zoneHistory = new DnsResourceRecord[count]; - - if (version >= 11) - { - for (int i = 0; i < count; i++) - { - zoneHistory[i] = new DnsResourceRecord(bR.BaseStream); - - if (bR.ReadBoolean()) - zoneHistory[i].Tag = new HistoryRecordInfo(bR); - } - } - else - { - for (int i = 0; i < count; i++) - { - zoneHistory[i] = new DnsResourceRecord(bR.BaseStream); - zoneHistory[i].Tag = new HistoryRecordInfo(bR); - } - } - - _zoneHistory = zoneHistory; - } - - if (version >= 4) - { - int count = bR.ReadByte(); - Dictionary tsigKeyNames = new Dictionary(count); - - for (int i = 0; i < count; i++) - tsigKeyNames.Add(bR.ReadShortString(), null); - - _zoneTransferTsigKeyNames = tsigKeyNames; - } - - if (version >= 7) - { - int count = bR.ReadByte(); - Dictionary>> updateSecurityPolicies = new Dictionary>>(count); - - for (int i = 0; i < count; i++) - { - string tsigKeyName = bR.ReadShortString().ToLower(); - - if (!updateSecurityPolicies.TryGetValue(tsigKeyName, out IReadOnlyDictionary> policyMap)) - { - policyMap = new Dictionary>(); - updateSecurityPolicies.Add(tsigKeyName, policyMap); - } - - int policyCount = bR.ReadByte(); - - for (int j = 0; j < policyCount; j++) - { - string domain = bR.ReadShortString().ToLower(); - - if (!policyMap.TryGetValue(domain, out IReadOnlyList types)) - { - types = new List(); - (policyMap as Dictionary>).Add(domain, types); - } - - int typeCount = bR.ReadByte(); - - for (int k = 0; k < typeCount; k++) - (types as List).Add((DnsResourceRecordType)bR.ReadUInt16()); - } - } - - _updateSecurityPolicies = updateSecurityPolicies; - } - else if (version >= 6) - { - int count = bR.ReadByte(); - Dictionary>> updateSecurityPolicies = new Dictionary>>(count); - - Dictionary> defaultAllowPolicy = new Dictionary>(1); - defaultAllowPolicy.Add(_name, new List() { DnsResourceRecordType.ANY }); - defaultAllowPolicy.Add("*." + _name, new List() { DnsResourceRecordType.ANY }); - - for (int i = 0; i < count; i++) - updateSecurityPolicies.Add(bR.ReadShortString().ToLower(), defaultAllowPolicy); - - _updateSecurityPolicies = updateSecurityPolicies; - } - - if (version >= 5) - { int count = bR.ReadByte(); if (count > 0) { - List dnssecPrivateKeys = new List(count); + NetworkAddress[] networks = new NetworkAddress[count]; - for (int i = 0; i < count; i++) - dnssecPrivateKeys.Add(DnssecPrivateKey.ReadFrom(bR)); - - _dnssecPrivateKeys = dnssecPrivateKeys; - } - } - - break; - - case AuthZoneType.Secondary: - _expiry = bR.ReadDateTime(); - - if (version >= 12) - _validationFailed = bR.ReadBoolean(); - - if (version >= 4) - { - int count = bR.ReadInt32(); - DnsResourceRecord[] zoneHistory = new DnsResourceRecord[count]; - - if (version >= 11) - { - for (int i = 0; i < count; i++) + if (version >= 9) { - zoneHistory[i] = new DnsResourceRecord(bR.BaseStream); - - if (bR.ReadBoolean()) - zoneHistory[i].Tag = new HistoryRecordInfo(bR); + for (int i = 0; i < count; i++) + networks[i] = NetworkAddress.ReadFrom(bR); } - } - else - { - for (int i = 0; i < count; i++) + else { - zoneHistory[i] = new DnsResourceRecord(bR.BaseStream); - zoneHistory[i].Tag = new HistoryRecordInfo(bR); - } - } - - _zoneHistory = zoneHistory; - } - - if (version >= 4) - { - int count = bR.ReadByte(); - Dictionary tsigKeyNames = new Dictionary(count); - - for (int i = 0; i < count; i++) - tsigKeyNames.Add(bR.ReadShortString(), null); - - _zoneTransferTsigKeyNames = tsigKeyNames; - } - - if (version == 6) - { - //MUST skip old version data - int count = bR.ReadByte(); - Dictionary tsigKeyNames = new Dictionary(count); - - for (int i = 0; i < count; i++) - tsigKeyNames.Add(bR.ReadShortString(), null); - } - - break; - - case AuthZoneType.Stub: - _expiry = bR.ReadDateTime(); - break; - - case AuthZoneType.Forwarder: - if (version >= 10) - { - int count = bR.ReadByte(); - Dictionary>> updateSecurityPolicies = new Dictionary>>(count); - - for (int i = 0; i < count; i++) - { - string tsigKeyName = bR.ReadShortString().ToLower(); - - if (!updateSecurityPolicies.TryGetValue(tsigKeyName, out IReadOnlyDictionary> policyMap)) - { - policyMap = new Dictionary>(); - updateSecurityPolicies.Add(tsigKeyName, policyMap); - } - - int policyCount = bR.ReadByte(); - - for (int j = 0; j < policyCount; j++) - { - string domain = bR.ReadShortString().ToLower(); - - if (!policyMap.TryGetValue(domain, out IReadOnlyList types)) + for (int i = 0; i < count; i++) { - types = new List(); - (policyMap as Dictionary>).Add(domain, types); + IPAddress address = IPAddressExtensions.ReadFrom(bR); + + switch (address.AddressFamily) + { + case AddressFamily.InterNetwork: + networks[i] = new NetworkAddress(address, 32); + break; + + case AddressFamily.InterNetworkV6: + networks[i] = new NetworkAddress(address, 128); + break; + + default: + throw new InvalidOperationException(); + } + } + } + + _zoneTransferNetworkACL = ConvertDenyAllowToACL(null, networks); + } + } + + { + _notify = (AuthZoneNotify)bR.ReadByte(); + + int count = bR.ReadByte(); + if (count > 0) + { + IPAddress[] nameServers = new IPAddress[count]; + + for (int i = 0; i < count; i++) + nameServers[i] = IPAddressExtensions.ReadFrom(bR); + + _notifyNameServers = nameServers; + } + } + + if (version >= 6) + { + _update = (AuthZoneUpdate)bR.ReadByte(); + + int count = bR.ReadByte(); + if (count > 0) + { + NetworkAddress[] networks = new NetworkAddress[count]; + + if (version >= 9) + { + for (int i = 0; i < count; i++) + networks[i] = NetworkAddress.ReadFrom(bR); + } + else + { + for (int i = 0; i < count; i++) + { + IPAddress address = IPAddressExtensions.ReadFrom(bR); + + switch (address.AddressFamily) + { + case AddressFamily.InterNetwork: + networks[i] = new NetworkAddress(address, 32); + break; + + case AddressFamily.InterNetworkV6: + networks[i] = new NetworkAddress(address, 128); + break; + + default: + throw new InvalidOperationException(); + } + } + } + + _updateNetworkACL = ConvertDenyAllowToACL(null, networks); + } + } + } + else + { + switch (_type) + { + case AuthZoneType.Primary: + _zoneTransfer = AuthZoneTransfer.AllowOnlyZoneNameServers; + _notify = AuthZoneNotify.ZoneNameServers; + _update = AuthZoneUpdate.Deny; + break; + + default: + _zoneTransfer = AuthZoneTransfer.Deny; + _notify = AuthZoneNotify.None; + _update = AuthZoneUpdate.Deny; + break; + } + } + + if (version >= 8) + _lastModified = bR.ReadDateTime(); + else + _lastModified = lastModified; + + switch (_type) + { + case AuthZoneType.Primary: + { + if (version >= 3) + { + int count = bR.ReadInt32(); + DnsResourceRecord[] zoneHistory = new DnsResourceRecord[count]; + + if (version >= 11) + { + for (int i = 0; i < count; i++) + { + zoneHistory[i] = new DnsResourceRecord(bR.BaseStream); + + if (bR.ReadBoolean()) + zoneHistory[i].Tag = new HistoryRecordInfo(bR); + } + } + else + { + for (int i = 0; i < count; i++) + { + zoneHistory[i] = new DnsResourceRecord(bR.BaseStream); + zoneHistory[i].Tag = new HistoryRecordInfo(bR); + } } - int typeCount = bR.ReadByte(); + _zoneHistory = zoneHistory; + } - for (int k = 0; k < typeCount; k++) - (types as List).Add((DnsResourceRecordType)bR.ReadUInt16()); + if (version >= 4) + { + int count = bR.ReadByte(); + Dictionary tsigKeyNames = new Dictionary(count); + + for (int i = 0; i < count; i++) + tsigKeyNames.Add(bR.ReadShortString(), null); + + _zoneTransferTsigKeyNames = tsigKeyNames; + } + + if (version >= 7) + { + int count = bR.ReadByte(); + Dictionary>> updateSecurityPolicies = new Dictionary>>(count); + + for (int i = 0; i < count; i++) + { + string tsigKeyName = bR.ReadShortString().ToLowerInvariant(); + + if (!updateSecurityPolicies.TryGetValue(tsigKeyName, out IReadOnlyDictionary> policyMap)) + { + policyMap = new Dictionary>(); + updateSecurityPolicies.Add(tsigKeyName, policyMap); + } + + int policyCount = bR.ReadByte(); + + for (int j = 0; j < policyCount; j++) + { + string domain = bR.ReadShortString().ToLowerInvariant(); + + if (!policyMap.TryGetValue(domain, out IReadOnlyList types)) + { + types = new List(); + (policyMap as Dictionary>).Add(domain, types); + } + + int typeCount = bR.ReadByte(); + + for (int k = 0; k < typeCount; k++) + (types as List).Add((DnsResourceRecordType)bR.ReadUInt16()); + } + } + + _updateSecurityPolicies = updateSecurityPolicies; + } + else if (version >= 6) + { + int count = bR.ReadByte(); + Dictionary>> updateSecurityPolicies = new Dictionary>>(count); + + Dictionary> defaultAllowPolicy = new Dictionary>(1); + defaultAllowPolicy.Add(_name, new List() { DnsResourceRecordType.ANY }); + defaultAllowPolicy.Add("*." + _name, new List() { DnsResourceRecordType.ANY }); + + for (int i = 0; i < count; i++) + updateSecurityPolicies.Add(bR.ReadShortString().ToLowerInvariant(), defaultAllowPolicy); + + _updateSecurityPolicies = updateSecurityPolicies; + } + + if (version >= 5) + { + int count = bR.ReadByte(); + if (count > 0) + { + List dnssecPrivateKeys = new List(count); + + for (int i = 0; i < count; i++) + dnssecPrivateKeys.Add(DnssecPrivateKey.ReadFrom(bR)); + + _dnssecPrivateKeys = dnssecPrivateKeys; + } } } + break; - _updateSecurityPolicies = updateSecurityPolicies; - } - break; + case AuthZoneType.Secondary: + { + _expiry = bR.ReadDateTime(); + + if (version >= 4) + { + int count = bR.ReadInt32(); + DnsResourceRecord[] zoneHistory = new DnsResourceRecord[count]; + + if (version >= 11) + { + for (int i = 0; i < count; i++) + { + zoneHistory[i] = new DnsResourceRecord(bR.BaseStream); + + if (bR.ReadBoolean()) + zoneHistory[i].Tag = new HistoryRecordInfo(bR); + } + } + else + { + for (int i = 0; i < count; i++) + { + zoneHistory[i] = new DnsResourceRecord(bR.BaseStream); + zoneHistory[i].Tag = new HistoryRecordInfo(bR); + } + } + + _zoneHistory = zoneHistory; + } + + if (version >= 4) + { + int count = bR.ReadByte(); + Dictionary tsigKeyNames = new Dictionary(count); + + for (int i = 0; i < count; i++) + tsigKeyNames.Add(bR.ReadShortString(), null); + + _zoneTransferTsigKeyNames = tsigKeyNames; + } + + if (version == 6) + { + //MUST skip old version data + int count = bR.ReadByte(); + Dictionary tsigKeyNames = new Dictionary(count); + + for (int i = 0; i < count; i++) + tsigKeyNames.Add(bR.ReadShortString(), null); + } + } + break; + + case AuthZoneType.Stub: + { + _expiry = bR.ReadDateTime(); + } + break; + + case AuthZoneType.Forwarder: + { + if (version >= 10) + { + int count = bR.ReadByte(); + Dictionary>> updateSecurityPolicies = new Dictionary>>(count); + + for (int i = 0; i < count; i++) + { + string tsigKeyName = bR.ReadShortString().ToLowerInvariant(); + + if (!updateSecurityPolicies.TryGetValue(tsigKeyName, out IReadOnlyDictionary> policyMap)) + { + policyMap = new Dictionary>(); + updateSecurityPolicies.Add(tsigKeyName, policyMap); + } + + int policyCount = bR.ReadByte(); + + for (int j = 0; j < policyCount; j++) + { + string domain = bR.ReadShortString().ToLowerInvariant(); + + if (!policyMap.TryGetValue(domain, out IReadOnlyList types)) + { + types = new List(); + (policyMap as Dictionary>).Add(domain, types); + } + + int typeCount = bR.ReadByte(); + + for (int k = 0; k < typeCount; k++) + (types as List).Add((DnsResourceRecordType)bR.ReadUInt16()); + } + } + + _updateSecurityPolicies = updateSecurityPolicies; + } + } + break; + } } + break; + case 12: + { + _name = bR.ReadShortString(); + _type = (AuthZoneType)bR.ReadByte(); + _lastModified = bR.ReadDateTime(); + _disabled = bR.ReadBoolean(); + + switch (_type) + { + case AuthZoneType.Primary: + _catalogZoneName = bR.ReadShortString(); + if (_catalogZoneName.Length == 0) + _catalogZoneName = null; + + _overrideCatalogQueryAccess = bR.ReadBoolean(); + _overrideCatalogZoneTransfer = bR.ReadBoolean(); + _overrideCatalogNotify = bR.ReadBoolean(); + + _queryAccess = (AuthZoneQueryAccess)bR.ReadByte(); + _queryAccessNetworkACL = ReadNetworkACLFrom(bR); + + _zoneTransfer = (AuthZoneTransfer)bR.ReadByte(); + _zoneTransferNetworkACL = ReadNetworkACLFrom(bR); + _zoneTransferTsigKeyNames = ReadZoneTransferTsigKeyNamesFrom(bR); + _zoneHistory = ReadZoneHistoryFrom(bR); + + _notify = (AuthZoneNotify)bR.ReadByte(); + _notifyNameServers = ReadIPAddressesFrom(bR); + + _update = (AuthZoneUpdate)bR.ReadByte(); + _updateNetworkACL = ReadNetworkACLFrom(bR); + _updateSecurityPolicies = ReadUpdateSecurityPoliciesFrom(bR); + + _dnssecPrivateKeys = ReadDnssecPrivateKeysFrom(bR); + break; + + case AuthZoneType.Secondary: + _catalogZoneName = bR.ReadShortString(); + if (_catalogZoneName.Length == 0) + _catalogZoneName = null; + + _overrideCatalogPrimaryNameServers = bR.ReadBoolean(); + + _queryAccess = (AuthZoneQueryAccess)bR.ReadByte(); + _queryAccessNetworkACL = ReadNetworkACLFrom(bR); + + _zoneTransfer = (AuthZoneTransfer)bR.ReadByte(); + _zoneTransferNetworkACL = ReadNetworkACLFrom(bR); + _zoneTransferTsigKeyNames = ReadZoneTransferTsigKeyNamesFrom(bR); + _zoneHistory = ReadZoneHistoryFrom(bR); + + _notify = (AuthZoneNotify)bR.ReadByte(); + _notifyNameServers = ReadIPAddressesFrom(bR); + + _update = (AuthZoneUpdate)bR.ReadByte(); + _updateNetworkACL = ReadNetworkACLFrom(bR); + + _primaryNameServerAddresses = ReadNameServerAddressesFrom(bR); + _primaryZoneTransferProtocol = (DnsTransportProtocol)bR.ReadByte(); + _primaryZoneTransferTsigKeyName = bR.ReadShortString(); + if (_primaryZoneTransferTsigKeyName.Length == 0) + _primaryZoneTransferTsigKeyName = null; + + _expiry = bR.ReadDateTime(); + _validateZone = bR.ReadBoolean(); + _validationFailed = bR.ReadBoolean(); + break; + + case AuthZoneType.Stub: + _catalogZoneName = bR.ReadShortString(); + if (_catalogZoneName.Length == 0) + _catalogZoneName = null; + + _overrideCatalogQueryAccess = bR.ReadBoolean(); + + _queryAccess = (AuthZoneQueryAccess)bR.ReadByte(); + _queryAccessNetworkACL = ReadNetworkACLFrom(bR); + + _primaryNameServerAddresses = ReadNameServerAddressesFrom(bR); + + _expiry = bR.ReadDateTime(); + break; + + case AuthZoneType.Forwarder: + _catalogZoneName = bR.ReadShortString(); + if (_catalogZoneName.Length == 0) + _catalogZoneName = null; + + _overrideCatalogQueryAccess = bR.ReadBoolean(); + _overrideCatalogZoneTransfer = bR.ReadBoolean(); + _overrideCatalogNotify = bR.ReadBoolean(); + + _queryAccess = (AuthZoneQueryAccess)bR.ReadByte(); + _queryAccessNetworkACL = ReadNetworkACLFrom(bR); + + _zoneTransfer = (AuthZoneTransfer)bR.ReadByte(); + _zoneTransferNetworkACL = ReadNetworkACLFrom(bR); + _zoneTransferTsigKeyNames = ReadZoneTransferTsigKeyNamesFrom(bR); + _zoneHistory = ReadZoneHistoryFrom(bR); + + _notify = (AuthZoneNotify)bR.ReadByte(); + _notifyNameServers = ReadIPAddressesFrom(bR); + + _update = (AuthZoneUpdate)bR.ReadByte(); + _updateNetworkACL = ReadNetworkACLFrom(bR); + _updateSecurityPolicies = ReadUpdateSecurityPoliciesFrom(bR); + break; + + case AuthZoneType.SecondaryForwarder: + _catalogZoneName = bR.ReadShortString(); + if (_catalogZoneName.Length == 0) + _catalogZoneName = null; + + _queryAccess = (AuthZoneQueryAccess)bR.ReadByte(); + _queryAccessNetworkACL = ReadNetworkACLFrom(bR); + + _update = (AuthZoneUpdate)bR.ReadByte(); + _updateNetworkACL = ReadNetworkACLFrom(bR); + + _primaryNameServerAddresses = ReadNameServerAddressesFrom(bR); + _primaryZoneTransferProtocol = (DnsTransportProtocol)bR.ReadByte(); + _primaryZoneTransferTsigKeyName = bR.ReadShortString(); + if (_primaryZoneTransferTsigKeyName.Length == 0) + _primaryZoneTransferTsigKeyName = null; + + _expiry = bR.ReadDateTime(); + break; + + case AuthZoneType.Catalog: + _queryAccess = (AuthZoneQueryAccess)bR.ReadByte(); + _queryAccessNetworkACL = ReadNetworkACLFrom(bR); + + _zoneTransfer = (AuthZoneTransfer)bR.ReadByte(); + _zoneTransferNetworkACL = ReadNetworkACLFrom(bR); + _zoneTransferTsigKeyNames = ReadZoneTransferTsigKeyNamesFrom(bR); + _zoneHistory = ReadZoneHistoryFrom(bR); + + _notify = (AuthZoneNotify)bR.ReadByte(); + _notifyNameServers = ReadIPAddressesFrom(bR); + break; + + case AuthZoneType.SecondaryCatalog: + _primaryNameServerAddresses = ReadNameServerAddressesFrom(bR); + _primaryZoneTransferProtocol = (DnsTransportProtocol)bR.ReadByte(); + _primaryZoneTransferTsigKeyName = bR.ReadShortString(); + if (_primaryZoneTransferTsigKeyName.Length == 0) + _primaryZoneTransferTsigKeyName = null; + + _expiry = bR.ReadDateTime(); + break; + } + } break; default: @@ -449,86 +632,486 @@ namespace DnsServerCore.Dns.Zones { _apexZone = apexZone; _name = _apexZone.Name; + _lastModified = _apexZone.LastModified; + _disabled = _apexZone.Disabled; if (_apexZone is PrimaryZone primaryZone) { _type = AuthZoneType.Primary; - if (loadHistory) - _zoneHistory = primaryZone.GetZoneHistory(); + _catalogZoneName = _apexZone.CatalogZoneName; + _overrideCatalogQueryAccess = _apexZone.OverrideCatalogQueryAccess; + _overrideCatalogZoneTransfer = _apexZone.OverrideCatalogZoneTransfer; + _overrideCatalogNotify = _apexZone.OverrideCatalogNotify; + + _queryAccess = _apexZone.QueryAccess; + _queryAccessNetworkACL = _apexZone.QueryAccessNetworkACL; + + _zoneTransfer = _apexZone.ZoneTransfer; + _zoneTransferNetworkACL = _apexZone.ZoneTransferNetworkACL; + _zoneTransferTsigKeyNames = _apexZone.ZoneTransferTsigKeyNames; + + if (loadHistory) + _zoneHistory = _apexZone.GetZoneHistory(); + + _notify = _apexZone.Notify; + _notifyNameServers = _apexZone.NotifyNameServers; + + _update = _apexZone.Update; + _updateNetworkACL = _apexZone.UpdateNetworkACL; + _updateSecurityPolicies = _apexZone.UpdateSecurityPolicies; - _zoneTransferTsigKeyNames = primaryZone.ZoneTransferTsigKeyNames; - _updateSecurityPolicies = primaryZone.UpdateSecurityPolicies; _dnssecPrivateKeys = primaryZone.DnssecPrivateKeys; } + else if (_apexZone is SecondaryCatalogZone secondaryCatalogZone) + { + _type = AuthZoneType.SecondaryCatalog; + + _primaryNameServerAddresses = secondaryCatalogZone.PrimaryNameServerAddresses; + _primaryZoneTransferProtocol = secondaryCatalogZone.PrimaryZoneTransferProtocol; + _primaryZoneTransferTsigKeyName = secondaryCatalogZone.PrimaryZoneTransferTsigKeyName; + + _expiry = secondaryCatalogZone.Expiry; + } + else if (_apexZone is SecondaryForwarderZone secondaryForwarderZone) + { + _type = AuthZoneType.SecondaryForwarder; + + _catalogZoneName = _apexZone.CatalogZoneName; + + _queryAccess = _apexZone.QueryAccess; + _queryAccessNetworkACL = _apexZone.QueryAccessNetworkACL; + + _update = _apexZone.Update; + _updateNetworkACL = _apexZone.UpdateNetworkACL; + + _primaryNameServerAddresses = secondaryForwarderZone.PrimaryNameServerAddresses; + _primaryZoneTransferProtocol = secondaryForwarderZone.PrimaryZoneTransferProtocol; + _primaryZoneTransferTsigKeyName = secondaryForwarderZone.PrimaryZoneTransferTsigKeyName; + + _expiry = secondaryForwarderZone.Expiry; + } else if (_apexZone is SecondaryZone secondaryZone) { _type = AuthZoneType.Secondary; + _catalogZoneName = _apexZone.CatalogZoneName; + _overrideCatalogPrimaryNameServers = secondaryZone.OverrideCatalogPrimaryNameServers; + + _queryAccess = _apexZone.QueryAccess; + _queryAccessNetworkACL = _apexZone.QueryAccessNetworkACL; + + _zoneTransfer = _apexZone.ZoneTransfer; + _zoneTransferNetworkACL = _apexZone.ZoneTransferNetworkACL; + _zoneTransferTsigKeyNames = _apexZone.ZoneTransferTsigKeyNames; + if (loadHistory) - _zoneHistory = secondaryZone.GetZoneHistory(); + _zoneHistory = _apexZone.GetZoneHistory(); + + _notify = _apexZone.Notify; + _notifyNameServers = _apexZone.NotifyNameServers; + + _update = _apexZone.Update; + _updateNetworkACL = _apexZone.UpdateNetworkACL; + + _primaryNameServerAddresses = secondaryZone.PrimaryNameServerAddresses; + _primaryZoneTransferProtocol = secondaryZone.PrimaryZoneTransferProtocol; + _primaryZoneTransferTsigKeyName = secondaryZone.PrimaryZoneTransferTsigKeyName; _expiry = secondaryZone.Expiry; + _validateZone = secondaryZone.ValidateZone; _validationFailed = secondaryZone.ValidationFailed; - _zoneTransferTsigKeyNames = secondaryZone.ZoneTransferTsigKeyNames; } else if (_apexZone is StubZone stubZone) { _type = AuthZoneType.Stub; + + _catalogZoneName = _apexZone.CatalogZoneName; + _overrideCatalogQueryAccess = _apexZone.OverrideCatalogQueryAccess; + + _queryAccess = _apexZone.QueryAccess; + _queryAccessNetworkACL = _apexZone.QueryAccessNetworkACL; + + _primaryNameServerAddresses = stubZone.PrimaryNameServerAddresses; + _expiry = stubZone.Expiry; } - else if (_apexZone is ForwarderZone forwarderZone) + else if (_apexZone is CatalogZone) + { + _type = AuthZoneType.Catalog; + + _queryAccess = _apexZone.QueryAccess; + _queryAccessNetworkACL = _apexZone.QueryAccessNetworkACL; + + _zoneTransfer = _apexZone.ZoneTransfer; + _zoneTransferNetworkACL = _apexZone.ZoneTransferNetworkACL; + _zoneTransferTsigKeyNames = _apexZone.ZoneTransferTsigKeyNames; + + if (loadHistory) + _zoneHistory = _apexZone.GetZoneHistory(); + + _notify = _apexZone.Notify; + _notifyNameServers = _apexZone.NotifyNameServers; + } + else if (_apexZone is ForwarderZone) { _type = AuthZoneType.Forwarder; - _updateSecurityPolicies = forwarderZone.UpdateSecurityPolicies; + + _catalogZoneName = _apexZone.CatalogZoneName; + _overrideCatalogQueryAccess = _apexZone.OverrideCatalogQueryAccess; + _overrideCatalogZoneTransfer = _apexZone.OverrideCatalogZoneTransfer; + _overrideCatalogNotify = _apexZone.OverrideCatalogNotify; + + _queryAccess = _apexZone.QueryAccess; + _queryAccessNetworkACL = _apexZone.QueryAccessNetworkACL; + + _zoneTransfer = _apexZone.ZoneTransfer; + _zoneTransferNetworkACL = _apexZone.ZoneTransferNetworkACL; + _zoneTransferTsigKeyNames = _apexZone.ZoneTransferTsigKeyNames; + + if (loadHistory) + _zoneHistory = _apexZone.GetZoneHistory(); + + _notify = _apexZone.Notify; + _notifyNameServers = _apexZone.NotifyNameServers; + + _update = _apexZone.Update; + _updateNetworkACL = _apexZone.UpdateNetworkACL; + _updateSecurityPolicies = _apexZone.UpdateSecurityPolicies; } else { _type = AuthZoneType.Unknown; } + } - _disabled = _apexZone.Disabled; - _zoneTransfer = _apexZone.ZoneTransfer; - _zoneTransferNameServers = _apexZone.ZoneTransferNameServers; - _notify = _apexZone.Notify; - _notifyNameServers = _apexZone.NotifyNameServers; - _update = _apexZone.Update; - _updateIpAddresses = _apexZone.UpdateIpAddresses; - _lastModified = _apexZone.LastModified; + #endregion + + #region static + + public static string GetZoneTypeName(AuthZoneType type) + { + switch (type) + { + case AuthZoneType.SecondaryForwarder: + return "Secondary Forwarder"; + + case AuthZoneType.SecondaryCatalog: + return "Secondary Catalog"; + + default: + return type.ToString(); + } + } + + internal static NameServerAddress[] ReadNameServerAddressesFrom(BinaryReader bR) + { + int count = bR.ReadByte(); + if (count < 1) + return null; + + NameServerAddress[] nameServerAddresses = new NameServerAddress[count]; + + for (int i = 0; i < count; i++) + nameServerAddresses[i] = new NameServerAddress(bR); + + return nameServerAddresses; + } + + internal static void WriteNameServerAddressesTo(IReadOnlyCollection nameServerAddresses, BinaryWriter bW) + { + if (nameServerAddresses is null) + { + bW.Write((byte)0); + } + else + { + bW.Write(Convert.ToByte(nameServerAddresses.Count)); + + foreach (NameServerAddress network in nameServerAddresses) + network.WriteTo(bW); + } + } + + internal static NetworkAccessControl[] ReadNetworkACLFrom(BinaryReader bR) + { + int count = bR.ReadByte(); + if (count < 1) + return null; + + NetworkAccessControl[] acl = new NetworkAccessControl[count]; + + for (int i = 0; i < count; i++) + acl[i] = NetworkAccessControl.ReadFrom(bR); + + return acl; + } + + internal static void WriteNetworkACLTo(IReadOnlyCollection acl, BinaryWriter bW) + { + if (acl is null) + { + bW.Write((byte)0); + } + else + { + bW.Write(Convert.ToByte(acl.Count)); + + foreach (NetworkAccessControl nac in acl) + nac.WriteTo(bW); + } + } + + internal static NetworkAddress[] ReadNetworkAddressesFrom(BinaryReader bR) + { + int count = bR.ReadByte(); + if (count < 1) + return null; + + NetworkAddress[] networks = new NetworkAddress[count]; + + for (int i = 0; i < count; i++) + networks[i] = NetworkAddress.ReadFrom(bR); + + return networks; + } + + internal static void WriteNetworkAddressesTo(IReadOnlyCollection networkAddresses, BinaryWriter bW) + { + if (networkAddresses is null) + { + bW.Write((byte)0); + } + else + { + bW.Write(Convert.ToByte(networkAddresses.Count)); + + foreach (NetworkAddress network in networkAddresses) + network.WriteTo(bW); + } + } + + internal static IPAddress[] ReadIPAddressesFrom(BinaryReader bR) + { + int count = bR.ReadByte(); + if (count < 1) + return null; + + IPAddress[] ipAddresses = new IPAddress[count]; + + for (int i = 0; i < count; i++) + ipAddresses[i] = IPAddressExtensions.ReadFrom(bR); + + return ipAddresses; + } + + internal static void WriteIPAddressesTo(IReadOnlyCollection ipAddresses, BinaryWriter bW) + { + if (ipAddresses is null) + { + bW.Write((byte)0); + } + else + { + bW.Write(Convert.ToByte(ipAddresses.Count)); + + foreach (IPAddress ipAddress in ipAddresses) + ipAddress.WriteTo(bW); + } + } + + internal static List ConvertDenyAllowToACL(NetworkAddress[] deniedNetworks, NetworkAddress[] allowedNetworks) + { + List acl = new List(); + + if (deniedNetworks is not null) + { + foreach (NetworkAddress network in deniedNetworks) + acl.Add(new NetworkAccessControl(network, true)); + } + + if (allowedNetworks is not null) + { + foreach (NetworkAddress network in allowedNetworks) + acl.Add(new NetworkAccessControl(network)); + } + + if (acl.Count > 0) + return acl; + + return null; + } + + #endregion + + #region private + + private static Dictionary ReadZoneTransferTsigKeyNamesFrom(BinaryReader bR) + { + int count = bR.ReadByte(); + Dictionary zoneTransferTsigKeyNames = new Dictionary(count); + + for (int i = 0; i < count; i++) + zoneTransferTsigKeyNames.Add(bR.ReadShortString(), null); + + return zoneTransferTsigKeyNames; + } + + private void WriteZoneTransferTsigKeyNamesTo(BinaryWriter bW) + { + if (_zoneTransferTsigKeyNames is null) + { + bW.Write((byte)0); + } + else + { + bW.Write(Convert.ToByte(_zoneTransferTsigKeyNames.Count)); + + foreach (KeyValuePair tsigKeyName in _zoneTransferTsigKeyNames) + bW.WriteShortString(tsigKeyName.Key); + } + } + + private static DnsResourceRecord[] ReadZoneHistoryFrom(BinaryReader bR) + { + int count = bR.ReadInt32(); + DnsResourceRecord[] zoneHistory = new DnsResourceRecord[count]; + + for (int i = 0; i < count; i++) + { + zoneHistory[i] = new DnsResourceRecord(bR.BaseStream); + + if (bR.ReadBoolean()) + zoneHistory[i].Tag = new HistoryRecordInfo(bR); + } + + return zoneHistory; + } + + private void WriteZoneHistoryTo(BinaryWriter bW) + { + if (_zoneHistory is null) + { + bW.Write(0); + } + else + { + bW.Write(_zoneHistory.Count); + + foreach (DnsResourceRecord record in _zoneHistory) + { + record.WriteTo(bW.BaseStream); + + if (record.Tag is HistoryRecordInfo rrInfo) + { + bW.Write(true); + rrInfo.WriteTo(bW); + } + else + { + bW.Write(false); + } + } + } + } + + private static Dictionary>> ReadUpdateSecurityPoliciesFrom(BinaryReader bR) + { + int count = bR.ReadInt32(); + Dictionary>> updateSecurityPolicies = new Dictionary>>(count); + + for (int i = 0; i < count; i++) + { + string tsigKeyName = bR.ReadShortString().ToLowerInvariant(); + + if (!updateSecurityPolicies.TryGetValue(tsigKeyName, out IReadOnlyDictionary> policyMap)) + { + policyMap = new Dictionary>(); + updateSecurityPolicies.Add(tsigKeyName, policyMap); + } + + int policyCount = bR.ReadByte(); + + for (int j = 0; j < policyCount; j++) + { + string domain = bR.ReadShortString().ToLowerInvariant(); + + if (!policyMap.TryGetValue(domain, out IReadOnlyList types)) + { + types = new List(); + (policyMap as Dictionary>).Add(domain, types); + } + + int typeCount = bR.ReadByte(); + + for (int k = 0; k < typeCount; k++) + (types as List).Add((DnsResourceRecordType)bR.ReadUInt16()); + } + } + + return updateSecurityPolicies; + } + + private void WriteUpdateSecurityPoliciesTo(BinaryWriter bW) + { + if (_updateSecurityPolicies is null) + { + bW.Write(0); + } + else + { + bW.Write(_updateSecurityPolicies.Count); + + foreach (KeyValuePair>> updateSecurityPolicy in _updateSecurityPolicies) + { + bW.WriteShortString(updateSecurityPolicy.Key); + bW.Write(Convert.ToByte(updateSecurityPolicy.Value.Count)); + + foreach (KeyValuePair> policyMap in updateSecurityPolicy.Value) + { + bW.WriteShortString(policyMap.Key); + bW.Write(Convert.ToByte(policyMap.Value.Count)); + + foreach (DnsResourceRecordType type in policyMap.Value) + bW.Write((ushort)type); + } + } + } + } + + private static DnssecPrivateKey[] ReadDnssecPrivateKeysFrom(BinaryReader bR) + { + int count = bR.ReadByte(); + if (count < 1) + return null; + + DnssecPrivateKey[] dnssecPrivateKeys = new DnssecPrivateKey[count]; + + for (int i = 0; i < count; i++) + dnssecPrivateKeys[i] = DnssecPrivateKey.ReadFrom(bR); + + return dnssecPrivateKeys; + } + + private void WriteDnssecPrivateKeysTo(BinaryWriter bW) + { + if (_dnssecPrivateKeys is null) + { + bW.Write((byte)0); + } + else + { + bW.Write(Convert.ToByte(_dnssecPrivateKeys.Count)); + + foreach (DnssecPrivateKey dnssecPrivateKey in _dnssecPrivateKeys) + dnssecPrivateKey.WriteTo(bW); + } } #endregion #region public - public IReadOnlyList GetApexRecords(DnsResourceRecordType type) - { - if (_apexZone is null) - throw new InvalidOperationException(); - - return _apexZone.GetRecords(type); - } - - public void TriggerNotify() - { - if (_apexZone is null) - throw new InvalidOperationException(); - - switch (_type) - { - case AuthZoneType.Primary: - (_apexZone as PrimaryZone).TriggerNotify(); - break; - - case AuthZoneType.Secondary: - (_apexZone as SecondaryZone).TriggerNotify(); - break; - - default: - throw new InvalidOperationException(); - } - } - public void TriggerRefresh() { if (_apexZone is null) @@ -537,6 +1120,8 @@ namespace DnsServerCore.Dns.Zones switch (_type) { case AuthZoneType.Secondary: + case AuthZoneType.SecondaryForwarder: + case AuthZoneType.SecondaryCatalog: (_apexZone as SecondaryZone).TriggerRefresh(); break; @@ -557,6 +1142,8 @@ namespace DnsServerCore.Dns.Zones switch (_type) { case AuthZoneType.Secondary: + case AuthZoneType.SecondaryForwarder: + case AuthZoneType.SecondaryCatalog: (_apexZone as SecondaryZone).TriggerResync(); break; @@ -569,22 +1156,6 @@ namespace DnsServerCore.Dns.Zones } } - public Task> GetPrimaryNameServerAddressesAsync(DnsServer dnsServer) - { - if (_apexZone is null) - throw new InvalidOperationException(); - - return _apexZone.GetPrimaryNameServerAddressesAsync(dnsServer); - } - - public Task> GetSecondaryNameServerAddressesAsync(DnsServer dnsServer) - { - if (_apexZone is null) - throw new InvalidOperationException(); - - return _apexZone.GetSecondaryNameServerAddressesAsync(dnsServer); - } - public void WriteTo(BinaryWriter bW) { if (_apexZone is null) @@ -594,201 +1165,131 @@ namespace DnsServerCore.Dns.Zones bW.WriteShortString(_name); bW.Write((byte)_type); - bW.Write(_disabled); - bW.Write((byte)_zoneTransfer); - - if (_zoneTransferNameServers is null) - { - bW.Write((byte)0); - } - else - { - bW.Write(Convert.ToByte(_zoneTransferNameServers.Count)); - foreach (NetworkAddress networkAddress in _zoneTransferNameServers) - networkAddress.WriteTo(bW); - } - - bW.Write((byte)_notify); - - if (_notifyNameServers is null) - { - bW.Write((byte)0); - } - else - { - bW.Write(Convert.ToByte(_notifyNameServers.Count)); - foreach (IPAddress nameServer in _notifyNameServers) - nameServer.WriteTo(bW); - } - - bW.Write((byte)_update); - - if (_updateIpAddresses is null) - { - bW.Write((byte)0); - } - else - { - bW.Write(Convert.ToByte(_updateIpAddresses.Count)); - foreach (NetworkAddress networkAddress in _updateIpAddresses) - networkAddress.WriteTo(bW); - } - bW.Write(_lastModified); + bW.Write(_disabled); switch (_type) { case AuthZoneType.Primary: - { - if (_zoneHistory is null) - { - bW.Write(0); - } - else - { - bW.Write(_zoneHistory.Count); + bW.Write(_catalogZoneName ?? ""); + bW.Write(_overrideCatalogQueryAccess); + bW.Write(_overrideCatalogZoneTransfer); + bW.Write(_overrideCatalogNotify); - foreach (DnsResourceRecord record in _zoneHistory) - { - record.WriteTo(bW.BaseStream); + bW.Write((byte)_queryAccess); + WriteNetworkACLTo(_queryAccessNetworkACL, bW); - if (record.Tag is HistoryRecordInfo rrInfo) - { - bW.Write(true); - rrInfo.WriteTo(bW); - } - else - { - bW.Write(false); - } - } - } + bW.Write((byte)_zoneTransfer); + WriteNetworkACLTo(_zoneTransferNetworkACL, bW); + WriteZoneTransferTsigKeyNamesTo(bW); + WriteZoneHistoryTo(bW); - if (_zoneTransferTsigKeyNames is null) - { - bW.Write((byte)0); - } - else - { - bW.Write(Convert.ToByte(_zoneTransferTsigKeyNames.Count)); + bW.Write((byte)_notify); + WriteIPAddressesTo(_notifyNameServers, bW); - foreach (KeyValuePair tsigKeyName in _zoneTransferTsigKeyNames) - bW.WriteShortString(tsigKeyName.Key); - } + bW.Write((byte)_update); + WriteNetworkACLTo(_updateNetworkACL, bW); + WriteUpdateSecurityPoliciesTo(bW); - if (_updateSecurityPolicies is null) - { - bW.Write((byte)0); - } - else - { - bW.Write(Convert.ToByte(_updateSecurityPolicies.Count)); - - foreach (KeyValuePair>> updateSecurityPolicy in _updateSecurityPolicies) - { - bW.WriteShortString(updateSecurityPolicy.Key); - bW.Write(Convert.ToByte(updateSecurityPolicy.Value.Count)); - - foreach (KeyValuePair> policyMap in updateSecurityPolicy.Value) - { - bW.WriteShortString(policyMap.Key); - bW.Write(Convert.ToByte(policyMap.Value.Count)); - - foreach (DnsResourceRecordType type in policyMap.Value) - bW.Write((ushort)type); - } - } - } - - if (_dnssecPrivateKeys is null) - { - bW.Write((byte)0); - } - else - { - bW.Write(Convert.ToByte(_dnssecPrivateKeys.Count)); - - foreach (DnssecPrivateKey dnssecPrivateKey in _dnssecPrivateKeys) - dnssecPrivateKey.WriteTo(bW); - } - } + WriteDnssecPrivateKeysTo(bW); break; case AuthZoneType.Secondary: - { - bW.Write(_expiry); - bW.Write(_validationFailed); + bW.Write(_catalogZoneName ?? ""); + bW.Write(_overrideCatalogPrimaryNameServers); - if (_zoneHistory is null) - { - bW.Write(0); - } - else - { - bW.Write(_zoneHistory.Count); + bW.Write((byte)_queryAccess); + WriteNetworkACLTo(_queryAccessNetworkACL, bW); - foreach (DnsResourceRecord record in _zoneHistory) - { - record.WriteTo(bW.BaseStream); + bW.Write((byte)_zoneTransfer); + WriteNetworkACLTo(_zoneTransferNetworkACL, bW); + WriteZoneTransferTsigKeyNamesTo(bW); + WriteZoneHistoryTo(bW); - if (record.Tag is HistoryRecordInfo rrInfo) - { - bW.Write(true); - rrInfo.WriteTo(bW); - } - else - { - bW.Write(false); - } - } - } + bW.Write((byte)_notify); + WriteIPAddressesTo(_notifyNameServers, bW); - if (_zoneTransferTsigKeyNames is null) - { - bW.Write((byte)0); - } - else - { - bW.Write(Convert.ToByte(_zoneTransferTsigKeyNames.Count)); + bW.Write((byte)_update); + WriteNetworkACLTo(_updateNetworkACL, bW); - foreach (KeyValuePair tsigKeyName in _zoneTransferTsigKeyNames) - bW.WriteShortString(tsigKeyName.Key); - } - } + WriteNameServerAddressesTo(_primaryNameServerAddresses, bW); + bW.Write((byte)_primaryZoneTransferProtocol); + bW.Write(_primaryZoneTransferTsigKeyName ?? ""); + + bW.Write(_expiry); + bW.Write(_validateZone); + bW.Write(_validationFailed); break; case AuthZoneType.Stub: - { - bW.Write(_expiry); - } + bW.Write(_catalogZoneName ?? ""); + bW.Write(_overrideCatalogQueryAccess); + + bW.Write((byte)_queryAccess); + WriteNetworkACLTo(_queryAccessNetworkACL, bW); + + WriteNameServerAddressesTo(_primaryNameServerAddresses, bW); + + bW.Write(_expiry); break; case AuthZoneType.Forwarder: - { - if (_updateSecurityPolicies is null) - { - bW.Write((byte)0); - } - else - { - bW.Write(Convert.ToByte(_updateSecurityPolicies.Count)); + bW.Write(_catalogZoneName ?? ""); + bW.Write(_overrideCatalogQueryAccess); + bW.Write(_overrideCatalogZoneTransfer); + bW.Write(_overrideCatalogNotify); - foreach (KeyValuePair>> updateSecurityPolicy in _updateSecurityPolicies) - { - bW.WriteShortString(updateSecurityPolicy.Key); - bW.Write(Convert.ToByte(updateSecurityPolicy.Value.Count)); + bW.Write((byte)_queryAccess); + WriteNetworkACLTo(_queryAccessNetworkACL, bW); - foreach (KeyValuePair> policyMap in updateSecurityPolicy.Value) - { - bW.WriteShortString(policyMap.Key); - bW.Write(Convert.ToByte(policyMap.Value.Count)); + bW.Write((byte)_zoneTransfer); + WriteNetworkACLTo(_zoneTransferNetworkACL, bW); + WriteZoneTransferTsigKeyNamesTo(bW); + WriteZoneHistoryTo(bW); - foreach (DnsResourceRecordType type in policyMap.Value) - bW.Write((ushort)type); - } - } - } - } + bW.Write((byte)_notify); + WriteIPAddressesTo(_notifyNameServers, bW); + + bW.Write((byte)_update); + WriteNetworkACLTo(_updateNetworkACL, bW); + WriteUpdateSecurityPoliciesTo(bW); + break; + + case AuthZoneType.SecondaryForwarder: + bW.Write(_catalogZoneName ?? ""); + + bW.Write((byte)_queryAccess); + WriteNetworkACLTo(_queryAccessNetworkACL, bW); + + bW.Write((byte)_update); + WriteNetworkACLTo(_updateNetworkACL, bW); + + WriteNameServerAddressesTo(_primaryNameServerAddresses, bW); + bW.Write((byte)_primaryZoneTransferProtocol); + bW.Write(_primaryZoneTransferTsigKeyName ?? ""); + + bW.Write(_expiry); + break; + + case AuthZoneType.Catalog: + bW.Write((byte)_queryAccess); + WriteNetworkACLTo(_queryAccessNetworkACL, bW); + + bW.Write((byte)_zoneTransfer); + WriteNetworkACLTo(_zoneTransferNetworkACL, bW); + WriteZoneTransferTsigKeyNamesTo(bW); + WriteZoneHistoryTo(bW); + + bW.Write((byte)_notify); + WriteIPAddressesTo(_notifyNameServers, bW); + break; + + case AuthZoneType.SecondaryCatalog: + WriteNameServerAddressesTo(_primaryNameServerAddresses, bW); + bW.Write((byte)_primaryZoneTransferProtocol); + bW.Write(_primaryZoneTransferTsigKeyName ?? ""); + + bW.Write(_expiry); break; } } @@ -816,7 +1317,7 @@ namespace DnsServerCore.Dns.Zones public override string ToString() { - return _name; + return _name.Length == 0 ? "" : _name; ; } #endregion @@ -829,9 +1330,26 @@ namespace DnsServerCore.Dns.Zones public string Name { get { return _name; } } + public string DisplayName + { get { return _name.Length == 0 ? "" : _name; } } + public AuthZoneType Type { get { return _type; } } + public string TypeName + { get { return GetZoneTypeName(_type); } } + + public DateTime LastModified + { + get + { + if (_apexZone is null) + return _lastModified; + + return _apexZone.LastModified; + } + } + public bool Disabled { get @@ -850,14 +1368,141 @@ namespace DnsServerCore.Dns.Zones } } - public bool IsActive + public string CatalogZoneName { get + { + if (_apexZone is null) + return _catalogZoneName; + + return _apexZone.CatalogZoneName; + } + } + + public bool OverrideCatalogQueryAccess + { + get + { + if (_apexZone is null) + return _overrideCatalogQueryAccess; + + return _apexZone.OverrideCatalogQueryAccess; + } + set { if (_apexZone is null) throw new InvalidOperationException(); - return _apexZone.IsActive; + _apexZone.OverrideCatalogQueryAccess = value; + } + } + + public bool OverrideCatalogZoneTransfer + { + get + { + if (_apexZone is null) + return _overrideCatalogZoneTransfer; + + return _apexZone.OverrideCatalogZoneTransfer; + } + set + { + if (_apexZone is null) + throw new InvalidOperationException(); + + _apexZone.OverrideCatalogZoneTransfer = value; + } + } + + public bool OverrideCatalogNotify + { + get + { + if (_apexZone is null) + return _overrideCatalogNotify; + + return _apexZone.OverrideCatalogNotify; + } + set + { + if (_apexZone is null) + throw new InvalidOperationException(); + + _apexZone.OverrideCatalogNotify = value; + } + } + + public bool OverrideCatalogPrimaryNameServers + { + get + { + if (_apexZone is null) + return _overrideCatalogPrimaryNameServers; + + switch (_type) + { + case AuthZoneType.Secondary: + return (_apexZone as SecondaryZone).OverrideCatalogPrimaryNameServers; + + case AuthZoneType.SecondaryForwarder: + case AuthZoneType.SecondaryCatalog: + return false; + + default: + throw new InvalidOperationException(); + } + } + set + { + if (_apexZone is null) + throw new InvalidOperationException(); + + switch (_type) + { + case AuthZoneType.Secondary: + (_apexZone as SecondaryZone).OverrideCatalogPrimaryNameServers = value; + break; + + default: + throw new InvalidOperationException(); + } + } + } + + public AuthZoneQueryAccess QueryAccess + { + get + { + if (_apexZone is null) + return _queryAccess; + + return _apexZone.QueryAccess; + } + set + { + if (_apexZone is null) + throw new InvalidOperationException(); + + _apexZone.QueryAccess = value; + } + } + + public IReadOnlyCollection QueryAccessNetworkACL + { + get + { + if (_apexZone is null) + return _queryAccessNetworkACL; + + return _apexZone.QueryAccessNetworkACL; + } + set + { + if (_apexZone is null) + throw new InvalidOperationException(); + + _apexZone.QueryAccessNetworkACL = value; } } @@ -879,21 +1524,61 @@ namespace DnsServerCore.Dns.Zones } } - public IReadOnlyCollection ZoneTransferNameServers + public IReadOnlyCollection ZoneTransferNetworkACL { get { if (_apexZone is null) - return _zoneTransferNameServers; + return _zoneTransferNetworkACL; - return _apexZone.ZoneTransferNameServers; + return _apexZone.ZoneTransferNetworkACL; } set { if (_apexZone is null) throw new InvalidOperationException(); - _apexZone.ZoneTransferNameServers = value; + _apexZone.ZoneTransferNetworkACL = value; + } + } + + public IReadOnlyDictionary ZoneTransferTsigKeyNames + { + get + { + if (_apexZone is null) + return _zoneTransferTsigKeyNames; + + return _apexZone.ZoneTransferTsigKeyNames; + } + set + { + if (_apexZone is null) + throw new InvalidOperationException(); + + switch (_type) + { + case AuthZoneType.Primary: + case AuthZoneType.Secondary: + case AuthZoneType.Forwarder: + case AuthZoneType.Catalog: + _apexZone.ZoneTransferTsigKeyNames = value; + break; + + default: + throw new InvalidOperationException(); + } + } + } + + public IReadOnlyList ZoneHistory + { + get + { + if (_apexZone is null) + return _zoneHistory; + + return _apexZone.GetZoneHistory(); } } @@ -951,109 +1636,21 @@ namespace DnsServerCore.Dns.Zones } } - public IReadOnlyCollection UpdateIpAddresses + public IReadOnlyCollection UpdateNetworkACL { get { if (_apexZone is null) - return _updateIpAddresses; + return _updateNetworkACL; - return _apexZone.UpdateIpAddresses; + return _apexZone.UpdateNetworkACL; } set { if (_apexZone is null) throw new InvalidOperationException(); - _apexZone.UpdateIpAddresses = value; - } - } - - public DateTime LastModified - { - get - { - if (_apexZone is null) - return _lastModified; - - return _apexZone.LastModified; - } - } - - public DateTime Expiry - { - get - { - if (_apexZone is null) - return _expiry; - - switch (_type) - { - case AuthZoneType.Secondary: - return (_apexZone as SecondaryZone).Expiry; - - case AuthZoneType.Stub: - return (_apexZone as StubZone).Expiry; - - default: - throw new InvalidOperationException(); - } - } - } - - public bool ValidationFailed - { - get - { - if (_apexZone is null) - return _validationFailed; - - switch (_type) - { - case AuthZoneType.Secondary: - return (_apexZone as SecondaryZone).ValidationFailed; - - default: - throw new InvalidOperationException(); - } - } - } - - public IReadOnlyList ZoneHistory - { - get - { - if (_apexZone is null) - return _zoneHistory; - - return _apexZone.GetZoneHistory(); - } - } - - public IReadOnlyDictionary ZoneTransferTsigKeyNames - { - get - { - if (_apexZone is null) - return _zoneTransferTsigKeyNames; - - return _apexZone.ZoneTransferTsigKeyNames; - } - set - { - if (_apexZone is null) - throw new InvalidOperationException(); - - switch (_type) - { - case AuthZoneType.Primary: - case AuthZoneType.Secondary: - _apexZone.ZoneTransferTsigKeyNames = value; - break; - - default: - throw new InvalidOperationException(); - } + _apexZone.UpdateNetworkACL = value; } } @@ -1102,14 +1699,195 @@ namespace DnsServerCore.Dns.Zones } } - public AuthZoneDnssecStatus DnssecStatus + public IReadOnlyList PrimaryNameServerAddresses { get + { + if (_apexZone is null) + return _primaryNameServerAddresses; + + switch (_type) + { + case AuthZoneType.Secondary: + case AuthZoneType.SecondaryForwarder: + case AuthZoneType.SecondaryCatalog: + return (_apexZone as SecondaryZone).PrimaryNameServerAddresses; + + case AuthZoneType.Stub: + return (_apexZone as StubZone).PrimaryNameServerAddresses; + + default: + throw new InvalidOperationException(); + } + } + set { if (_apexZone is null) throw new InvalidOperationException(); - return _apexZone.DnssecStatus; + switch (_type) + { + case AuthZoneType.Secondary: + case AuthZoneType.SecondaryForwarder: + case AuthZoneType.SecondaryCatalog: + (_apexZone as SecondaryZone).PrimaryNameServerAddresses = value; + break; + + case AuthZoneType.Stub: + (_apexZone as StubZone).PrimaryNameServerAddresses = value; + break; + + default: + throw new InvalidOperationException(); + } + } + } + + public DnsTransportProtocol PrimaryZoneTransferProtocol + { + get + { + if (_apexZone is null) + return _primaryZoneTransferProtocol; + + switch (_type) + { + case AuthZoneType.Secondary: + case AuthZoneType.SecondaryForwarder: + case AuthZoneType.SecondaryCatalog: + return (_apexZone as SecondaryZone).PrimaryZoneTransferProtocol; + + default: + throw new InvalidOperationException(); + } + } + set + { + if (_apexZone is null) + throw new InvalidOperationException(); + + switch (_type) + { + case AuthZoneType.Secondary: + case AuthZoneType.SecondaryForwarder: + case AuthZoneType.SecondaryCatalog: + (_apexZone as SecondaryZone).PrimaryZoneTransferProtocol = value; + break; + + default: + throw new InvalidOperationException(); + } + } + } + + public string PrimaryZoneTransferTsigKeyName + { + get + { + if (_apexZone is null) + return _primaryZoneTransferTsigKeyName; + + switch (_type) + { + case AuthZoneType.Secondary: + case AuthZoneType.SecondaryForwarder: + case AuthZoneType.SecondaryCatalog: + return (_apexZone as SecondaryZone).PrimaryZoneTransferTsigKeyName; + + default: + throw new InvalidOperationException(); + } + } + set + { + if (_apexZone is null) + throw new InvalidOperationException(); + + switch (_type) + { + case AuthZoneType.Secondary: + case AuthZoneType.SecondaryForwarder: + case AuthZoneType.SecondaryCatalog: + (_apexZone as SecondaryZone).PrimaryZoneTransferTsigKeyName = value; + break; + + default: + throw new InvalidOperationException(); + } + } + } + + public DateTime Expiry + { + get + { + if (_apexZone is null) + return _expiry; + + switch (_type) + { + case AuthZoneType.Secondary: + case AuthZoneType.SecondaryForwarder: + case AuthZoneType.SecondaryCatalog: + return (_apexZone as SecondaryZone).Expiry; + + case AuthZoneType.Stub: + return (_apexZone as StubZone).Expiry; + + default: + throw new InvalidOperationException(); + } + } + } + + public bool ValidateZone + { + get + { + if (_apexZone is null) + return _validateZone; + + switch (_type) + { + case AuthZoneType.Secondary: + return (_apexZone as SecondaryZone).ValidateZone; + + default: + throw new InvalidOperationException(); + } + } + set + { + if (_apexZone is null) + throw new InvalidOperationException(); + + switch (_type) + { + case AuthZoneType.Secondary: + (_apexZone as SecondaryZone).ValidateZone = value; + break; + + default: + throw new InvalidOperationException(); + } + } + } + + public bool ValidationFailed + { + get + { + if (_apexZone is null) + return _validationFailed; + + switch (_type) + { + case AuthZoneType.Secondary: + return (_apexZone as SecondaryZone).ValidationFailed; + + default: + throw new InvalidOperationException(); + } } } @@ -1159,6 +1937,8 @@ namespace DnsServerCore.Dns.Zones switch (_type) { case AuthZoneType.Secondary: + case AuthZoneType.SecondaryForwarder: + case AuthZoneType.SecondaryCatalog: return (_apexZone as SecondaryZone).IsExpired; case AuthZoneType.Stub: @@ -1180,10 +1960,10 @@ namespace DnsServerCore.Dns.Zones switch (_type) { case AuthZoneType.Primary: - return (_apexZone as PrimaryZone).NotifyFailed; - case AuthZoneType.Secondary: - return (_apexZone as SecondaryZone).NotifyFailed; + case AuthZoneType.Forwarder: + case AuthZoneType.Catalog: + return _apexZone.NotifyFailed; default: throw new InvalidOperationException(); @@ -1201,10 +1981,10 @@ namespace DnsServerCore.Dns.Zones switch (_type) { case AuthZoneType.Secondary: - return (_apexZone as SecondaryZone).SyncFailed; - + case AuthZoneType.SecondaryForwarder: + case AuthZoneType.SecondaryCatalog: case AuthZoneType.Stub: - return (_apexZone as StubZone).SyncFailed; + return _apexZone.SyncFailed; default: throw new InvalidOperationException();