2021-09-18 19:02:40 +05:30
/ *
Technitium DNS Server
2025-02-15 12:51:16 +05:30
Copyright ( C ) 2025 Shreyas Zare ( shreyas @technitium . com )
2021-09-18 19:02:40 +05:30
This program is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
* /
2022-09-18 18:00:21 +05:30
using DnsServerCore.Auth ;
2025-04-19 16:03:13 +05:30
using DnsServerCore.Dns ;
2022-02-20 17:13:52 +05:30
using DnsServerCore.Dns.Dnssec ;
2021-09-18 19:02:40 +05:30
using DnsServerCore.Dns.ResourceRecords ;
2025-04-19 16:03:13 +05:30
using DnsServerCore.Dns.ZoneManagers ;
2021-09-18 19:02:40 +05:30
using DnsServerCore.Dns.Zones ;
2023-01-01 18:39:46 +05:30
using Microsoft.AspNetCore.Http ;
2021-09-18 19:02:40 +05:30
using System ;
using System.Collections.Generic ;
2023-10-29 20:18:58 +05:30
using System.IO ;
2021-09-18 19:02:40 +05:30
using System.Net ;
2024-05-19 16:40:40 +05:30
using System.Text ;
2022-12-24 13:44:04 +05:30
using System.Text.Json ;
2021-09-18 19:02:40 +05:30
using System.Threading.Tasks ;
2023-01-01 18:39:46 +05:30
using TechnitiumLibrary ;
2022-05-08 15:35:21 +05:30
using TechnitiumLibrary.Net ;
2021-09-18 19:02:40 +05:30
using TechnitiumLibrary.Net.Dns ;
using TechnitiumLibrary.Net.Dns.ResourceRecords ;
namespace DnsServerCore
{
2025-02-15 12:51:16 +05:30
public partial class DnsWebService
2021-09-18 19:02:40 +05:30
{
2025-02-15 12:51:16 +05:30
class WebServiceZonesApi
{
#region variables
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
static readonly char [ ] _commaSeparator = new char [ ] { ',' } ;
static readonly char [ ] _pipeSeparator = new char [ ] { '|' } ;
static readonly char [ ] _commaSpaceSeparator = new char [ ] { ',' , ' ' } ;
static readonly char [ ] _newLineSeparator = new char [ ] { '\r' , '\n' } ;
2024-02-04 18:08:15 +05:30
2025-02-15 12:51:16 +05:30
readonly DnsWebService _dnsWebService ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
uint _defaultRecordTtl = 3600 ;
2021-09-25 13:45:03 +05:30
2025-02-15 12:51:16 +05:30
#endregion
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
#region constructor
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
public WebServiceZonesApi ( DnsWebService dnsWebService )
{
_dnsWebService = dnsWebService ;
}
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
#endregion
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
#region static
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
public static void WriteRecordsAsJson ( List < DnsResourceRecord > records , Utf8JsonWriter jsonWriter , bool authoritativeZoneRecords , AuthZoneInfo zoneInfo = null )
2021-09-18 19:02:40 +05:30
{
2025-02-15 12:51:16 +05:30
if ( records is null )
{
jsonWriter . WritePropertyName ( "records" ) ;
jsonWriter . WriteStartArray ( ) ;
jsonWriter . WriteEndArray ( ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
return ;
}
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
records . Sort ( ) ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
Dictionary < string , Dictionary < DnsResourceRecordType , List < DnsResourceRecord > > > groupedByDomainRecords = DnsResourceRecord . GroupRecords ( records ) ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WritePropertyName ( "records" ) ;
jsonWriter . WriteStartArray ( ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
foreach ( KeyValuePair < string , Dictionary < DnsResourceRecordType , List < DnsResourceRecord > > > groupedByTypeRecords in groupedByDomainRecords )
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
foreach ( KeyValuePair < DnsResourceRecordType , List < DnsResourceRecord > > groupedRecords in groupedByTypeRecords . Value )
{
foreach ( DnsResourceRecord record in groupedRecords . Value )
WriteRecordAsJson ( record , jsonWriter , authoritativeZoneRecords , zoneInfo ) ;
}
2021-09-18 19:02:40 +05:30
}
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndArray ( ) ;
}
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
#endregion
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
#region private
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
private static void WriteRecordAsJson ( DnsResourceRecord record , Utf8JsonWriter jsonWriter , bool authoritativeZoneRecords , AuthZoneInfo zoneInfo = null )
{
jsonWriter . WriteStartObject ( ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteString ( "name" , record . Name ) ;
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . TryConvertDomainNameToUnicode ( record . Name , out string idn ) )
jsonWriter . WriteString ( "nameIdn" , idn ) ;
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteString ( "type" , record . Type . ToString ( ) ) ;
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
if ( authoritativeZoneRecords )
{
GenericRecordInfo authRecordInfo = record . GetAuthGenericRecordInfo ( ) ;
2023-01-14 15:16:46 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteNumber ( "ttl" , record . TTL ) ;
2025-03-29 18:58:25 +05:30
jsonWriter . WriteString ( "ttlString" , ZoneFile . GetTtlString ( record . TTL ) ) ;
2025-02-15 12:51:16 +05:30
jsonWriter . WriteBoolean ( "disabled" , authRecordInfo . Disabled ) ;
2023-01-14 15:16:46 +05:30
2025-02-15 12:51:16 +05:30
string comments = authRecordInfo . Comments ;
if ( ! string . IsNullOrEmpty ( comments ) )
jsonWriter . WriteString ( "comments" , comments ) ;
}
2023-01-14 15:16:46 +05:30
else
2025-02-15 12:51:16 +05:30
{
if ( record . IsStale )
2025-03-29 18:58:25 +05:30
jsonWriter . WriteString ( "ttl" , "0 (0s)" ) ;
2025-02-15 12:51:16 +05:30
else
2025-03-29 18:58:25 +05:30
jsonWriter . WriteString ( "ttl" , record . TTL + " (" + ZoneFile . GetTtlString ( record . TTL ) + ")" ) ;
2025-02-15 12:51:16 +05:30
}
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WritePropertyName ( "rData" ) ;
jsonWriter . WriteStartObject ( ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
switch ( record . Type )
{
case DnsResourceRecordType . A :
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
if ( record . RDATA is DnsARecordData rdata )
{
jsonWriter . WriteString ( "ipAddress" , rdata . Address . ToString ( ) ) ;
}
else
{
jsonWriter . WriteString ( "dataType" , record . RDATA . GetType ( ) . Name ) ;
jsonWriter . WriteString ( "data" , record . RDATA . ToString ( ) ) ;
}
2022-04-30 16:19:02 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . NS :
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
if ( record . RDATA is DnsNSRecordData rdata )
{
jsonWriter . WriteString ( "nameServer" , rdata . NameServer . Length = = 0 ? "." : rdata . NameServer ) ;
2022-05-08 15:35:21 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . TryConvertDomainNameToUnicode ( rdata . NameServer , out string nameServerIdn ) )
jsonWriter . WriteString ( "nameServerIdn" , nameServerIdn ) ;
}
else
2022-05-08 15:35:21 +05:30
{
2025-02-15 12:51:16 +05:30
jsonWriter . WriteString ( "dataType" , record . RDATA . GetType ( ) . Name ) ;
jsonWriter . WriteString ( "data" , record . RDATA . ToString ( ) ) ;
2022-05-08 15:35:21 +05:30
}
2022-04-30 16:19:02 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . CNAME :
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
if ( record . RDATA is DnsCNAMERecordData rdata )
{
jsonWriter . WriteString ( "cname" , rdata . Domain . Length = = 0 ? "." : rdata . Domain ) ;
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . TryConvertDomainNameToUnicode ( rdata . Domain , out string cnameIdn ) )
jsonWriter . WriteString ( "cnameIdn" , cnameIdn ) ;
}
else
{
jsonWriter . WriteString ( "dataType" , record . RDATA . GetType ( ) . Name ) ;
jsonWriter . WriteString ( "data" , record . RDATA . ToString ( ) ) ;
}
2022-04-30 16:19:02 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . SOA :
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
if ( record . RDATA is DnsSOARecordData rdata )
{
jsonWriter . WriteString ( "primaryNameServer" , rdata . PrimaryNameServer ) ;
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . TryConvertDomainNameToUnicode ( rdata . PrimaryNameServer , out string primaryNameServerIdn ) )
jsonWriter . WriteString ( "primaryNameServerIdn" , primaryNameServerIdn ) ;
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteString ( "responsiblePerson" , rdata . ResponsiblePerson ) ;
jsonWriter . WriteNumber ( "serial" , rdata . Serial ) ;
2025-03-29 18:58:25 +05:30
if ( authoritativeZoneRecords )
{
jsonWriter . WriteNumber ( "refresh" , rdata . Refresh ) ;
jsonWriter . WriteNumber ( "retry" , rdata . Retry ) ;
jsonWriter . WriteNumber ( "expire" , rdata . Expire ) ;
jsonWriter . WriteNumber ( "minimum" , rdata . Minimum ) ;
jsonWriter . WriteString ( "refreshString" , ZoneFile . GetTtlString ( rdata . Refresh ) ) ;
jsonWriter . WriteString ( "retryString" , ZoneFile . GetTtlString ( rdata . Retry ) ) ;
jsonWriter . WriteString ( "expireString" , ZoneFile . GetTtlString ( rdata . Expire ) ) ;
jsonWriter . WriteString ( "minimumString" , ZoneFile . GetTtlString ( rdata . Minimum ) ) ;
}
else
{
jsonWriter . WriteString ( "refresh" , rdata . Refresh + " (" + ZoneFile . GetTtlString ( rdata . Refresh ) + ")" ) ;
jsonWriter . WriteString ( "retry" , rdata . Retry + " (" + ZoneFile . GetTtlString ( rdata . Retry ) + ")" ) ;
jsonWriter . WriteString ( "expire" , rdata . Expire + " (" + ZoneFile . GetTtlString ( rdata . Expire ) + ")" ) ;
jsonWriter . WriteString ( "minimum" , rdata . Minimum + " (" + ZoneFile . GetTtlString ( rdata . Minimum ) + ")" ) ;
}
2025-02-15 12:51:16 +05:30
}
else
{
jsonWriter . WriteString ( "dataType" , record . RDATA . GetType ( ) . Name ) ;
jsonWriter . WriteString ( "data" , record . RDATA . ToString ( ) ) ;
}
2022-01-23 18:22:17 +05:30
2025-02-15 12:51:16 +05:30
if ( authoritativeZoneRecords & & ( zoneInfo is not null ) )
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
switch ( zoneInfo . Type )
{
case AuthZoneType . Primary :
case AuthZoneType . Forwarder :
case AuthZoneType . Catalog :
jsonWriter . WriteBoolean ( "useSerialDateScheme" , record . GetAuthSOARecordInfo ( ) . UseSoaSerialDateScheme ) ;
break ;
}
2022-04-30 16:19:02 +05:30
}
}
2025-02-15 12:51:16 +05:30
break ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . PTR :
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
if ( record . RDATA is DnsPTRRecordData rdata )
{
jsonWriter . WriteString ( "ptrName" , rdata . Domain . Length = = 0 ? "." : rdata . Domain ) ;
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . TryConvertDomainNameToUnicode ( rdata . Domain , out string ptrNameIdn ) )
jsonWriter . WriteString ( "ptrNameIdn" , ptrNameIdn ) ;
}
else
{
jsonWriter . WriteString ( "dataType" , record . RDATA . GetType ( ) . Name ) ;
jsonWriter . WriteString ( "data" , record . RDATA . ToString ( ) ) ;
}
2022-04-30 16:19:02 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . MX :
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
if ( record . RDATA is DnsMXRecordData rdata )
{
jsonWriter . WriteNumber ( "preference" , rdata . Preference ) ;
jsonWriter . WriteString ( "exchange" , rdata . Exchange . Length = = 0 ? "." : rdata . Exchange ) ;
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . TryConvertDomainNameToUnicode ( rdata . Exchange , out string exchangeIdn ) )
jsonWriter . WriteString ( "exchangeIdn" , exchangeIdn ) ;
}
else
{
jsonWriter . WriteString ( "dataType" , record . RDATA . GetType ( ) . Name ) ;
jsonWriter . WriteString ( "data" , record . RDATA . ToString ( ) ) ;
}
2022-04-30 16:19:02 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . TXT :
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
if ( record . RDATA is DnsTXTRecordData rdata )
{
jsonWriter . WriteString ( "text" , rdata . GetText ( ) ) ;
jsonWriter . WriteBoolean ( "splitText" , rdata . CharacterStrings . Count > 1 ) ;
2024-05-19 16:40:40 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteStartArray ( "characterStrings" ) ;
2024-05-19 16:40:40 +05:30
2025-02-15 12:51:16 +05:30
foreach ( string characterString in rdata . CharacterStrings )
jsonWriter . WriteStringValue ( characterString ) ;
2024-05-19 16:40:40 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndArray ( ) ;
}
else
{
jsonWriter . WriteString ( "dataType" , record . RDATA . GetType ( ) . Name ) ;
jsonWriter . WriteString ( "data" , record . RDATA . ToString ( ) ) ;
}
2022-04-30 16:19:02 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . RP :
2024-09-15 15:14:12 +05:30
{
2025-02-15 12:51:16 +05:30
if ( record . RDATA is DnsRPRecordData rdata )
{
jsonWriter . WriteString ( "mailbox" , rdata . Mailbox ) ;
jsonWriter . WriteString ( "txtDomain" , rdata . TxtDomain ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . TryConvertDomainNameToUnicode ( rdata . Mailbox , out string txtDomainIdn ) )
jsonWriter . WriteString ( "txtDomainIdn" , txtDomainIdn ) ;
}
else
{
jsonWriter . WriteString ( "dataType" , record . RDATA . GetType ( ) . Name ) ;
jsonWriter . WriteString ( "data" , record . RDATA . ToString ( ) ) ;
}
2024-09-15 15:14:12 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . AAAA :
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
if ( record . RDATA is DnsAAAARecordData rdata )
{
jsonWriter . WriteString ( "ipAddress" , rdata . Address . ToString ( ) ) ;
}
else
{
jsonWriter . WriteString ( "dataType" , record . RDATA . GetType ( ) . Name ) ;
jsonWriter . WriteString ( "data" , record . RDATA . ToString ( ) ) ;
}
2022-04-30 16:19:02 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . SRV :
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
if ( record . RDATA is DnsSRVRecordData rdata )
{
jsonWriter . WriteNumber ( "priority" , rdata . Priority ) ;
jsonWriter . WriteNumber ( "weight" , rdata . Weight ) ;
jsonWriter . WriteNumber ( "port" , rdata . Port ) ;
jsonWriter . WriteString ( "target" , rdata . Target . Length = = 0 ? "." : rdata . Target ) ;
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . TryConvertDomainNameToUnicode ( rdata . Target , out string targetIdn ) )
jsonWriter . WriteString ( "targetIdn" , targetIdn ) ;
}
else
{
jsonWriter . WriteString ( "dataType" , record . RDATA . GetType ( ) . Name ) ;
jsonWriter . WriteString ( "data" , record . RDATA . ToString ( ) ) ;
}
2022-04-30 16:19:02 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
2024-05-19 16:40:40 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . NAPTR :
2024-05-19 16:40:40 +05:30
{
2025-02-15 12:51:16 +05:30
if ( record . RDATA is DnsNAPTRRecordData rdata )
{
jsonWriter . WriteNumber ( "order" , rdata . Order ) ;
jsonWriter . WriteNumber ( "preference" , rdata . Preference ) ;
jsonWriter . WriteString ( "flags" , rdata . Flags ) ;
jsonWriter . WriteString ( "services" , rdata . Services ) ;
jsonWriter . WriteString ( "regexp" , rdata . Regexp ) ;
jsonWriter . WriteString ( "replacement" , rdata . Replacement . Length = = 0 ? "." : rdata . Replacement ) ;
if ( DnsClient . TryConvertDomainNameToUnicode ( rdata . Replacement , out string replacementIdn ) )
jsonWriter . WriteString ( "replacementIdn" , replacementIdn ) ;
}
else
{
jsonWriter . WriteString ( "dataType" , record . RDATA . GetType ( ) . Name ) ;
jsonWriter . WriteString ( "data" , record . RDATA . ToString ( ) ) ;
}
2024-05-19 16:40:40 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
2024-05-19 16:40:40 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . DNAME :
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
if ( record . RDATA is DnsDNAMERecordData rdata )
{
jsonWriter . WriteString ( "dname" , rdata . Domain . Length = = 0 ? "." : rdata . Domain ) ;
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . TryConvertDomainNameToUnicode ( rdata . Domain , out string dnameIdn ) )
jsonWriter . WriteString ( "dnameIdn" , dnameIdn ) ;
}
else
{
jsonWriter . WriteString ( "dataType" , record . RDATA . GetType ( ) . Name ) ;
jsonWriter . WriteString ( "data" , record . RDATA . ToString ( ) ) ;
}
2022-04-30 16:19:02 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . APL :
2024-09-15 15:14:12 +05:30
{
2025-02-15 12:51:16 +05:30
if ( record . RDATA is DnsAPLRecordData rdata )
2024-09-15 15:14:12 +05:30
{
2025-02-15 12:51:16 +05:30
jsonWriter . WriteStartArray ( "addressPrefixes" ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
foreach ( DnsAPLRecordData . APItem apItem in rdata . APItems )
{
jsonWriter . WriteStartObject ( ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteString ( "addressFamily" , apItem . AddressFamily . ToString ( ) ) ;
jsonWriter . WriteNumber ( "prefix" , apItem . Prefix ) ;
jsonWriter . WriteBoolean ( "negation" , apItem . Negation ) ;
jsonWriter . WriteString ( "afdPart" , apItem . NetworkAddress . Address . ToString ( ) ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndObject ( ) ;
}
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndArray ( ) ;
}
else
{
jsonWriter . WriteString ( "dataType" , record . RDATA . GetType ( ) . Name ) ;
jsonWriter . WriteString ( "data" , record . RDATA . ToString ( ) ) ;
}
2022-04-30 16:19:02 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . DS :
2022-10-30 19:13:48 +05:30
{
2025-02-15 12:51:16 +05:30
if ( record . RDATA is DnsDSRecordData rdata )
{
jsonWriter . WriteNumber ( "keyTag" , rdata . KeyTag ) ;
jsonWriter . WriteString ( "algorithm" , rdata . Algorithm . ToString ( ) ) ;
2025-03-29 18:58:25 +05:30
jsonWriter . WriteNumber ( "algorithmNumber" , ( byte ) rdata . Algorithm ) ;
2025-02-15 12:51:16 +05:30
jsonWriter . WriteString ( "digestType" , rdata . DigestType . ToString ( ) ) ;
2025-03-29 18:58:25 +05:30
jsonWriter . WriteNumber ( "digestTypeNumber" , ( byte ) rdata . DigestType ) ;
2025-02-15 12:51:16 +05:30
jsonWriter . WriteString ( "digest" , Convert . ToHexString ( rdata . Digest ) ) ;
}
else
{
jsonWriter . WriteString ( "dataType" , record . RDATA . GetType ( ) . Name ) ;
jsonWriter . WriteString ( "data" , record . RDATA . ToString ( ) ) ;
}
2022-10-30 19:13:48 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
case DnsResourceRecordType . SSHFP :
2022-10-30 19:13:48 +05:30
{
2025-02-15 12:51:16 +05:30
if ( record . RDATA is DnsSSHFPRecordData rdata )
{
jsonWriter . WriteString ( "algorithm" , rdata . Algorithm . ToString ( ) ) ;
jsonWriter . WriteString ( "fingerprintType" , rdata . FingerprintType . ToString ( ) ) ;
jsonWriter . WriteString ( "fingerprint" , Convert . ToHexString ( rdata . Fingerprint ) ) ;
}
else
{
jsonWriter . WriteString ( "dataType" , record . RDATA . GetType ( ) . Name ) ;
jsonWriter . WriteString ( "data" , record . RDATA . ToString ( ) ) ;
}
2022-10-30 19:13:48 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
2022-10-30 19:13:48 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . RRSIG :
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
if ( record . RDATA is DnsRRSIGRecordData rdata )
{
jsonWriter . WriteString ( "typeCovered" , rdata . TypeCovered . ToString ( ) ) ;
jsonWriter . WriteString ( "algorithm" , rdata . Algorithm . ToString ( ) ) ;
2025-03-29 18:58:25 +05:30
jsonWriter . WriteNumber ( "algorithmNumber" , ( byte ) rdata . Algorithm ) ;
2025-02-15 12:51:16 +05:30
jsonWriter . WriteNumber ( "labels" , rdata . Labels ) ;
jsonWriter . WriteNumber ( "originalTtl" , rdata . OriginalTtl ) ;
jsonWriter . WriteString ( "signatureExpiration" , DateTime . UnixEpoch . AddSeconds ( rdata . SignatureExpiration ) ) ;
jsonWriter . WriteString ( "signatureInception" , DateTime . UnixEpoch . AddSeconds ( rdata . SignatureInception ) ) ;
jsonWriter . WriteNumber ( "keyTag" , rdata . KeyTag ) ;
jsonWriter . WriteString ( "signersName" , rdata . SignersName . Length = = 0 ? "." : rdata . SignersName ) ;
jsonWriter . WriteString ( "signature" , Convert . ToBase64String ( rdata . Signature ) ) ;
}
else
{
jsonWriter . WriteString ( "dataType" , record . RDATA . GetType ( ) . Name ) ;
jsonWriter . WriteString ( "data" , record . RDATA . ToString ( ) ) ;
}
2022-04-30 16:19:02 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . NSEC :
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
if ( record . RDATA is DnsNSECRecordData rdata )
{
jsonWriter . WriteString ( "nextDomainName" , rdata . NextDomainName ) ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WritePropertyName ( "types" ) ;
jsonWriter . WriteStartArray ( ) ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
foreach ( DnsResourceRecordType type in rdata . Types )
jsonWriter . WriteStringValue ( type . ToString ( ) ) ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndArray ( ) ;
}
else
{
jsonWriter . WriteString ( "dataType" , record . RDATA . GetType ( ) . Name ) ;
jsonWriter . WriteString ( "data" , record . RDATA . ToString ( ) ) ;
}
2022-04-30 16:19:02 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . DNSKEY :
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
if ( record . RDATA is DnsDNSKEYRecordData rdata )
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
jsonWriter . WriteString ( "flags" , rdata . Flags . ToString ( ) ) ;
jsonWriter . WriteNumber ( "protocol" , rdata . Protocol ) ;
jsonWriter . WriteString ( "algorithm" , rdata . Algorithm . ToString ( ) ) ;
2025-03-29 18:58:25 +05:30
jsonWriter . WriteNumber ( "algorithmNumber" , ( byte ) rdata . Algorithm ) ;
2025-02-15 12:51:16 +05:30
jsonWriter . WriteString ( "publicKey" , rdata . PublicKey . ToString ( ) ) ;
jsonWriter . WriteNumber ( "computedKeyTag" , rdata . ComputedKeyTag ) ;
if ( authoritativeZoneRecords )
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
if ( ( zoneInfo is not null ) & & ( zoneInfo . Type = = AuthZoneType . Primary ) )
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
IReadOnlyCollection < DnssecPrivateKey > dnssecPrivateKeys = zoneInfo . DnssecPrivateKeys ;
if ( dnssecPrivateKeys is not null )
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
foreach ( DnssecPrivateKey dnssecPrivateKey in dnssecPrivateKeys )
2023-02-18 11:44:57 +05:30
{
2025-02-15 12:51:16 +05:30
if ( dnssecPrivateKey . KeyTag = = rdata . ComputedKeyTag )
{
jsonWriter . WriteString ( "dnsKeyState" , dnssecPrivateKey . State . ToString ( ) ) ;
2022-05-21 13:04:03 +05:30
2025-03-29 18:58:25 +05:30
if ( dnssecPrivateKey . State = = DnssecPrivateKeyState . Published )
{
switch ( dnssecPrivateKey . KeyType )
{
case DnssecPrivateKeyType . KeySigningKey :
jsonWriter . WriteString ( "dnsKeyStateReadyBy" , dnssecPrivateKey . StateTransitionByWithDelays ) ;
break ;
case DnssecPrivateKeyType . ZoneSigningKey :
jsonWriter . WriteString ( "dnsKeyStateActiveBy" , dnssecPrivateKey . StateTransitionByWithDelays ) ;
break ;
}
}
2022-12-24 13:44:04 +05:30
2025-02-15 12:51:16 +05:30
break ;
}
2023-02-18 11:44:57 +05:30
}
2022-04-30 16:19:02 +05:30
}
}
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
if ( rdata . Flags . HasFlag ( DnsDnsKeyFlag . SecureEntryPoint ) )
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
jsonWriter . WritePropertyName ( "computedDigests" ) ;
jsonWriter . WriteStartArray ( ) ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
{
jsonWriter . WriteStartObject ( ) ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteString ( "digestType" , "SHA256" ) ;
jsonWriter . WriteString ( "digest" , Convert . ToHexString ( rdata . CreateDS ( record . Name , DnssecDigestType . SHA256 ) . Digest ) ) ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndObject ( ) ;
}
{
jsonWriter . WriteStartObject ( ) ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteString ( "digestType" , "SHA384" ) ;
jsonWriter . WriteString ( "digest" , Convert . ToHexString ( rdata . CreateDS ( record . Name , DnssecDigestType . SHA384 ) . Digest ) ) ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndObject ( ) ;
}
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndArray ( ) ;
}
2022-04-30 16:19:02 +05:30
}
}
2025-02-15 12:51:16 +05:30
else
{
jsonWriter . WriteString ( "dataType" , record . RDATA . GetType ( ) . Name ) ;
jsonWriter . WriteString ( "data" , record . RDATA . ToString ( ) ) ;
}
2022-04-30 16:19:02 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . NSEC3 :
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
if ( record . RDATA is DnsNSEC3RecordData rdata )
{
jsonWriter . WriteString ( "hashAlgorithm" , rdata . HashAlgorithm . ToString ( ) ) ;
jsonWriter . WriteString ( "flags" , rdata . Flags . ToString ( ) ) ;
jsonWriter . WriteNumber ( "iterations" , rdata . Iterations ) ;
jsonWriter . WriteString ( "salt" , Convert . ToHexString ( rdata . Salt ) ) ;
jsonWriter . WriteString ( "nextHashedOwnerName" , rdata . NextHashedOwnerName ) ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WritePropertyName ( "types" ) ;
jsonWriter . WriteStartArray ( ) ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
foreach ( DnsResourceRecordType type in rdata . Types )
jsonWriter . WriteStringValue ( type . ToString ( ) ) ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndArray ( ) ;
}
else
{
jsonWriter . WriteString ( "dataType" , record . RDATA . GetType ( ) . Name ) ;
jsonWriter . WriteString ( "data" , record . RDATA . ToString ( ) ) ;
}
2022-04-30 16:19:02 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . NSEC3PARAM :
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
if ( record . RDATA is DnsNSEC3PARAMRecordData rdata )
{
jsonWriter . WriteString ( "hashAlgorithm" , rdata . HashAlgorithm . ToString ( ) ) ;
jsonWriter . WriteString ( "flags" , rdata . Flags . ToString ( ) ) ;
jsonWriter . WriteNumber ( "iterations" , rdata . Iterations ) ;
jsonWriter . WriteString ( "salt" , Convert . ToHexString ( rdata . Salt ) ) ;
}
else
{
jsonWriter . WriteString ( "dataType" , record . RDATA . GetType ( ) . Name ) ;
jsonWriter . WriteString ( "data" , record . RDATA . ToString ( ) ) ;
}
2022-04-30 16:19:02 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . TLSA :
2022-10-30 19:13:48 +05:30
{
2025-02-15 12:51:16 +05:30
if ( record . RDATA is DnsTLSARecordData rdata )
{
jsonWriter . WriteString ( "certificateUsage" , rdata . CertificateUsage . ToString ( ) . Replace ( '_' , '-' ) ) ;
jsonWriter . WriteString ( "selector" , rdata . Selector . ToString ( ) ) ;
jsonWriter . WriteString ( "matchingType" , rdata . MatchingType . ToString ( ) . Replace ( '_' , '-' ) ) ;
jsonWriter . WriteString ( "certificateAssociationData" , Convert . ToHexString ( rdata . CertificateAssociationData ) ) ;
}
else
{
jsonWriter . WriteString ( "dataType" , record . RDATA . GetType ( ) . Name ) ;
jsonWriter . WriteString ( "data" , record . RDATA . ToString ( ) ) ;
}
2024-06-15 15:08:04 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
2024-06-15 15:08:04 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . ZONEMD :
2024-06-15 15:08:04 +05:30
{
2025-02-15 12:51:16 +05:30
if ( record . RDATA is DnsZONEMDRecordData rdata )
{
jsonWriter . WriteNumber ( "serial" , rdata . Serial ) ;
jsonWriter . WriteString ( "scheme" , rdata . Scheme . ToString ( ) ) ;
jsonWriter . WriteString ( "hashAlgorithm" , rdata . HashAlgorithm . ToString ( ) ) ;
jsonWriter . WriteString ( "digest" , Convert . ToHexString ( rdata . Digest ) ) ;
}
else
{
jsonWriter . WriteString ( "dataType" , record . RDATA . GetType ( ) . Name ) ;
jsonWriter . WriteString ( "data" , record . RDATA . ToString ( ) ) ;
}
2022-10-30 19:13:48 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
2022-10-30 19:13:48 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . SVCB :
case DnsResourceRecordType . HTTPS :
2023-05-20 18:40:44 +05:30
{
2025-02-15 12:51:16 +05:30
if ( record . RDATA is DnsSVCBRecordData rdata )
{
jsonWriter . WriteNumber ( "svcPriority" , rdata . SvcPriority ) ;
jsonWriter . WriteString ( "svcTargetName" , rdata . TargetName ) ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WritePropertyName ( "svcParams" ) ;
jsonWriter . WriteStartObject ( ) ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
foreach ( KeyValuePair < DnsSvcParamKey , DnsSvcParamValue > svcParam in rdata . SvcParams )
jsonWriter . WriteString ( svcParam . Key . ToString ( ) . ToLowerInvariant ( ) . Replace ( '_' , '-' ) , svcParam . Value . ToString ( ) ) ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndObject ( ) ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
if ( authoritativeZoneRecords )
{
SVCBRecordInfo rrInfo = record . GetAuthSVCBRecordInfo ( ) ;
2024-06-01 19:25:07 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteBoolean ( "autoIpv4Hint" , rrInfo . AutoIpv4Hint ) ;
jsonWriter . WriteBoolean ( "autoIpv6Hint" , rrInfo . AutoIpv6Hint ) ;
}
}
else
{
jsonWriter . WriteString ( "dataType" , record . RDATA . GetType ( ) . Name ) ;
jsonWriter . WriteString ( "data" , record . RDATA . ToString ( ) ) ;
2024-06-01 19:25:07 +05:30
}
2023-05-20 18:40:44 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . URI :
2023-07-02 15:47:55 +05:30
{
2025-02-15 12:51:16 +05:30
if ( record . RDATA is DnsURIRecordData rdata )
{
jsonWriter . WriteNumber ( "priority" , rdata . Priority ) ;
jsonWriter . WriteNumber ( "weight" , rdata . Weight ) ;
jsonWriter . WriteString ( "uri" , rdata . Uri . AbsoluteUri ) ;
}
else
{
jsonWriter . WriteString ( "dataType" , record . RDATA . GetType ( ) . Name ) ;
jsonWriter . WriteString ( "data" , record . RDATA . ToString ( ) ) ;
}
2023-07-02 15:47:55 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
2023-07-02 15:47:55 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . CAA :
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
if ( record . RDATA is DnsCAARecordData rdata )
{
jsonWriter . WriteNumber ( "flags" , rdata . Flags ) ;
jsonWriter . WriteString ( "tag" , rdata . Tag ) ;
jsonWriter . WriteString ( "value" , rdata . Value ) ;
}
else
{
jsonWriter . WriteString ( "dataType" , record . RDATA . GetType ( ) . Name ) ;
jsonWriter . WriteString ( "data" , record . RDATA . ToString ( ) ) ;
}
2022-04-30 16:19:02 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
case DnsResourceRecordType . ANAME :
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
if ( record . RDATA is DnsANAMERecordData rdata )
{
jsonWriter . WriteString ( "aname" , rdata . Domain . Length = = 0 ? "." : rdata . Domain ) ;
if ( DnsClient . TryConvertDomainNameToUnicode ( rdata . Domain , out string anameIdn ) )
jsonWriter . WriteString ( "anameIdn" , anameIdn ) ;
}
else
{
jsonWriter . WriteString ( "dataType" , record . RDATA . GetType ( ) . Name ) ;
jsonWriter . WriteString ( "data" , record . RDATA . ToString ( ) ) ;
}
2022-04-30 16:19:02 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . FWD :
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
if ( record . RDATA is DnsForwarderRecordData rdata )
{
jsonWriter . WriteString ( "protocol" , rdata . Protocol . ToString ( ) ) ;
jsonWriter . WriteString ( "forwarder" , rdata . Forwarder ) ;
jsonWriter . WriteNumber ( "priority" , rdata . Priority ) ;
jsonWriter . WriteBoolean ( "dnssecValidation" , rdata . DnssecValidation ) ;
jsonWriter . WriteString ( "proxyType" , rdata . ProxyType . ToString ( ) ) ;
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
switch ( rdata . ProxyType )
{
case DnsForwarderRecordProxyType . Http :
case DnsForwarderRecordProxyType . Socks5 :
jsonWriter . WriteString ( "proxyAddress" , rdata . ProxyAddress ) ;
jsonWriter . WriteNumber ( "proxyPort" , rdata . ProxyPort ) ;
jsonWriter . WriteString ( "proxyUsername" , rdata . ProxyUsername ) ;
jsonWriter . WriteString ( "proxyPassword" , rdata . ProxyPassword ) ;
break ;
}
}
2022-04-30 16:19:02 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
case DnsResourceRecordType . APP :
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
if ( record . RDATA is DnsApplicationRecordData rdata )
{
jsonWriter . WriteString ( "appName" , rdata . AppName ) ;
jsonWriter . WriteString ( "classPath" , rdata . ClassPath ) ;
jsonWriter . WriteString ( "data" , rdata . Data ) ;
}
2022-04-30 16:19:02 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . ALIAS :
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
if ( record . RDATA is DnsALIASRecordData rdata )
{
jsonWriter . WriteString ( "type" , rdata . Type . ToString ( ) ) ;
jsonWriter . WriteString ( "alias" , rdata . Domain . Length = = 0 ? "." : rdata . Domain ) ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . TryConvertDomainNameToUnicode ( rdata . Domain , out string aliasIdn ) )
jsonWriter . WriteString ( "aliasIdn" , aliasIdn ) ;
}
else
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
jsonWriter . WriteString ( "dataType" , record . RDATA . GetType ( ) . Name ) ;
jsonWriter . WriteString ( "data" , record . RDATA . ToString ( ) ) ;
2022-04-30 16:19:02 +05:30
}
}
2025-02-15 12:51:16 +05:30
break ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
default :
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
if ( record . RDATA is DnsUnknownRecordData rdata )
{
jsonWriter . WriteString ( "value" , BitConverter . ToString ( rdata . DATA ) . Replace ( '-' , ':' ) ) ;
}
else
{
jsonWriter . WriteString ( "dataType" , record . RDATA . GetType ( ) . Name ) ;
jsonWriter . WriteString ( "data" , record . RDATA . ToString ( ) ) ;
}
2022-04-30 16:19:02 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
}
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndObject ( ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteString ( "dnssecStatus" , record . DnssecStatus . ToString ( ) ) ;
if ( authoritativeZoneRecords )
{
GenericRecordInfo authRecordInfo = record . GetAuthGenericRecordInfo ( ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
if ( authRecordInfo is NSRecordInfo nsRecordInfo )
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
IReadOnlyList < DnsResourceRecord > glueRecords = nsRecordInfo . GlueRecords ;
if ( glueRecords is not null )
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
jsonWriter . WritePropertyName ( "glueRecords" ) ;
jsonWriter . WriteStartArray ( ) ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
foreach ( DnsResourceRecord glueRecord in glueRecords )
jsonWriter . WriteStringValue ( glueRecord . RDATA . ToString ( ) ) ;
2023-01-14 15:16:46 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndArray ( ) ;
}
}
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteString ( "lastUsedOn" , authRecordInfo . LastUsedOn ) ;
jsonWriter . WriteString ( "lastModified" , authRecordInfo . LastModified ) ;
jsonWriter . WriteNumber ( "expiryTtl" , authRecordInfo . ExpiryTtl ) ;
2025-03-31 19:36:23 +05:30
jsonWriter . WriteString ( "expiryTtlString" , ZoneFile . GetTtlString ( authRecordInfo . ExpiryTtl ) ) ;
2025-02-15 12:51:16 +05:30
}
else
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
CacheRecordInfo cacheRecordInfo = record . GetCacheRecordInfo ( ) ;
IReadOnlyList < DnsResourceRecord > glueRecords = cacheRecordInfo . GlueRecords ;
2024-06-01 19:25:07 +05:30
if ( glueRecords is not null )
{
jsonWriter . WritePropertyName ( "glueRecords" ) ;
jsonWriter . WriteStartArray ( ) ;
2022-02-20 17:13:52 +05:30
2024-06-01 19:25:07 +05:30
foreach ( DnsResourceRecord glueRecord in glueRecords )
jsonWriter . WriteStringValue ( glueRecord . RDATA . ToString ( ) ) ;
2022-02-20 17:13:52 +05:30
2024-06-01 19:25:07 +05:30
jsonWriter . WriteEndArray ( ) ;
}
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
IReadOnlyList < DnsResourceRecord > rrsigRecords = cacheRecordInfo . RRSIGRecords ;
IReadOnlyList < DnsResourceRecord > nsecRecords = cacheRecordInfo . NSECRecords ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
if ( ( rrsigRecords is not null ) | | ( nsecRecords is not null ) )
{
jsonWriter . WritePropertyName ( "dnssecRecords" ) ;
jsonWriter . WriteStartArray ( ) ;
2023-01-14 15:16:46 +05:30
2025-02-15 12:51:16 +05:30
if ( rrsigRecords is not null )
{
foreach ( DnsResourceRecord rrsigRecord in rrsigRecords )
jsonWriter . WriteStringValue ( rrsigRecord . ToString ( ) ) ;
}
2023-01-14 15:16:46 +05:30
2025-02-15 12:51:16 +05:30
if ( nsecRecords is not null )
{
foreach ( DnsResourceRecord nsecRecord in nsecRecords )
jsonWriter . WriteStringValue ( nsecRecord . ToString ( ) ) ;
}
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndArray ( ) ;
}
2023-01-14 15:16:46 +05:30
2025-02-15 12:51:16 +05:30
NetworkAddress eDnsClientSubnet = cacheRecordInfo . EDnsClientSubnet ;
if ( eDnsClientSubnet is not null )
jsonWriter . WriteString ( "eDnsClientSubnet" , eDnsClientSubnet . ToString ( ) ) ;
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
if ( record . RDATA is DnsNSRecordData nsRData )
2023-01-14 15:16:46 +05:30
{
2025-02-15 12:51:16 +05:30
NameServerMetadata metadata = nsRData . Metadata ;
jsonWriter . WriteStartObject ( "nameServerMetadata" ) ;
jsonWriter . WriteNumber ( "totalQueries" , metadata . TotalQueries ) ;
jsonWriter . WriteString ( "answerRate" , Math . Round ( metadata . GetAnswerRate ( ) , 2 ) + "%" ) ;
jsonWriter . WriteString ( "smoothedRoundTripTime" , Math . Round ( metadata . SRTT , 2 ) + " ms" ) ;
jsonWriter . WriteString ( "smoothedPenaltyRoundTripTime" , Math . Round ( metadata . SPRTT , 2 ) + " ms" ) ;
jsonWriter . WriteString ( "netRoundTripTime" , Math . Round ( metadata . GetNetRTT ( ) , 2 ) + " ms" ) ;
jsonWriter . WriteEndObject ( ) ;
2023-01-14 15:16:46 +05:30
}
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
DnsDatagramMetadata responseMetadata = cacheRecordInfo . ResponseMetadata ;
if ( responseMetadata is not null )
2023-01-14 15:16:46 +05:30
{
2025-02-15 12:51:16 +05:30
jsonWriter . WritePropertyName ( "responseMetadata" ) ;
jsonWriter . WriteStartObject ( ) ;
jsonWriter . WriteString ( "nameServer" , responseMetadata . NameServer ? . ToString ( ) ) ;
jsonWriter . WriteString ( "protocol" , ( responseMetadata . NameServer is null ? DnsTransportProtocol . Udp : responseMetadata . NameServer . Protocol ) . ToString ( ) ) ;
jsonWriter . WriteString ( "datagramSize" , responseMetadata . DatagramSize + " bytes" ) ;
jsonWriter . WriteString ( "roundTripTime" , Math . Round ( responseMetadata . RoundTripTime , 2 ) + " ms" ) ;
jsonWriter . WriteEndObject ( ) ;
2023-01-14 15:16:46 +05:30
}
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteString ( "lastUsedOn" , cacheRecordInfo . LastUsedOn ) ;
2023-01-14 15:16:46 +05:30
}
2022-11-20 16:36:12 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndObject ( ) ;
}
2023-01-14 15:16:46 +05:30
2025-02-15 12:51:16 +05:30
private static void WriteZoneInfoAsJson ( AuthZoneInfo zoneInfo , Utf8JsonWriter jsonWriter )
{
jsonWriter . WriteStartObject ( ) ;
jsonWriter . WriteString ( "name" , zoneInfo . Name ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . TryConvertDomainNameToUnicode ( zoneInfo . Name , out string nameIdn ) )
jsonWriter . WriteString ( "nameIdn" , nameIdn ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteString ( "type" , zoneInfo . Type . ToString ( ) ) ;
jsonWriter . WriteString ( "lastModified" , zoneInfo . LastModified ) ;
jsonWriter . WriteBoolean ( "disabled" , zoneInfo . Disabled ) ;
jsonWriter . WriteNumber ( "soaSerial" , zoneInfo . ApexZone . GetZoneSoaSerial ( ) ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
switch ( zoneInfo . Type )
{
case AuthZoneType . Primary :
jsonWriter . WriteBoolean ( "internal" , zoneInfo . Internal ) ;
break ;
2024-09-15 15:14:12 +05:30
}
2025-02-15 12:51:16 +05:30
switch ( zoneInfo . Type )
2024-03-16 15:46:55 +05:30
{
2025-02-15 12:51:16 +05:30
case AuthZoneType . Primary :
case AuthZoneType . Secondary :
case AuthZoneType . Stub :
case AuthZoneType . Forwarder :
case AuthZoneType . SecondaryForwarder :
jsonWriter . WriteString ( "catalog" , zoneInfo . CatalogZoneName ) ;
break ;
}
2024-03-16 15:46:55 +05:30
2025-02-15 12:51:16 +05:30
switch ( zoneInfo . Type )
{
case AuthZoneType . Primary :
case AuthZoneType . Secondary :
jsonWriter . WriteString ( "dnssecStatus" , zoneInfo . ApexZone . DnssecStatus . ToString ( ) ) ;
break ;
}
2024-03-16 15:46:55 +05:30
2025-02-15 12:51:16 +05:30
switch ( zoneInfo . Type )
{
case AuthZoneType . Secondary :
jsonWriter . WriteBoolean ( "validationFailed" , zoneInfo . ValidationFailed ) ;
break ;
2024-03-16 15:46:55 +05:30
}
2025-02-15 12:51:16 +05:30
switch ( zoneInfo . Type )
{
case AuthZoneType . Secondary :
case AuthZoneType . Stub :
case AuthZoneType . SecondaryForwarder :
case AuthZoneType . SecondaryCatalog :
jsonWriter . WriteString ( "expiry" , zoneInfo . Expiry ) ;
jsonWriter . WriteBoolean ( "isExpired" , zoneInfo . IsExpired ) ;
jsonWriter . WriteBoolean ( "syncFailed" , zoneInfo . SyncFailed ) ;
break ;
}
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
switch ( zoneInfo . Type )
{
case AuthZoneType . Primary :
case AuthZoneType . Secondary :
case AuthZoneType . Forwarder :
case AuthZoneType . Catalog :
if ( ! zoneInfo . Internal )
{
string [ ] notifyFailed = zoneInfo . NotifyFailed ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteBoolean ( "notifyFailed" , notifyFailed . Length > 0 ) ;
2022-03-26 12:11:10 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WritePropertyName ( "notifyFailedFor" ) ;
jsonWriter . WriteStartArray ( ) ;
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
foreach ( string server in notifyFailed )
jsonWriter . WriteStringValue ( server ) ;
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndArray ( ) ;
}
break ;
}
2022-03-26 12:11:10 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndObject ( ) ;
2024-09-15 15:14:12 +05:30
}
2023-07-02 15:47:55 +05:30
2025-02-15 12:51:16 +05:30
private static string [ ] DecodeCharacterStrings ( string text )
2024-09-15 15:14:12 +05:30
{
2025-02-15 12:51:16 +05:30
string [ ] characterStrings = text . Split ( _newLineSeparator , StringSplitOptions . RemoveEmptyEntries ) ;
2023-07-02 15:47:55 +05:30
2025-02-15 12:51:16 +05:30
for ( int i = 0 ; i < characterStrings . Length ; i + + )
characterStrings [ i ] = Unescape ( characterStrings [ i ] ) ;
2022-12-24 13:44:04 +05:30
2025-02-15 12:51:16 +05:30
return characterStrings ;
2024-09-15 15:14:12 +05:30
}
2022-03-26 12:11:10 +05:30
2025-02-15 12:51:16 +05:30
private static string Unescape ( string text )
2024-09-15 15:14:12 +05:30
{
2025-02-15 12:51:16 +05:30
StringBuilder sb = new StringBuilder ( text . Length ) ;
2023-07-02 15:47:55 +05:30
2025-02-15 12:51:16 +05:30
for ( int i = 0 , j ; i < text . Length ; i + + )
{
char c = text [ i ] ;
if ( c = = '\\' )
2023-07-02 15:47:55 +05:30
{
2025-02-15 12:51:16 +05:30
j = i + 1 ;
2023-07-02 15:47:55 +05:30
2025-02-15 12:51:16 +05:30
if ( j = = text . Length )
{
sb . Append ( c ) ;
break ;
}
2023-07-02 15:47:55 +05:30
2025-02-15 12:51:16 +05:30
char next = text [ j ] ;
switch ( next )
{
case 'n' :
sb . Append ( '\n' ) ;
break ;
2023-07-02 15:47:55 +05:30
2025-02-15 12:51:16 +05:30
case 'r' :
sb . Append ( '\r' ) ;
break ;
2023-07-02 15:47:55 +05:30
2025-02-15 12:51:16 +05:30
case 't' :
sb . Append ( '\t' ) ;
break ;
2024-05-19 16:40:40 +05:30
2025-02-15 12:51:16 +05:30
case '\\' :
sb . Append ( '\\' ) ;
break ;
2024-05-19 16:40:40 +05:30
2025-02-15 12:51:16 +05:30
default :
sb . Append ( c ) . Append ( next ) ;
break ;
}
2024-05-19 16:40:40 +05:30
2025-02-15 12:51:16 +05:30
i + + ;
}
else
2024-05-19 16:40:40 +05:30
{
sb . Append ( c ) ;
}
2025-02-15 12:51:16 +05:30
}
2024-05-19 16:40:40 +05:30
2025-02-15 12:51:16 +05:30
return sb . ToString ( ) ;
}
2024-05-19 16:40:40 +05:30
2025-02-15 12:51:16 +05:30
private static string GetSvcbTargetName ( DnsResourceRecord svcbRecord )
{
DnsSVCBRecordData rData = svcbRecord . RDATA as DnsSVCBRecordData ;
2024-05-19 16:40:40 +05:30
2025-02-15 12:51:16 +05:30
if ( rData . TargetName . Length > 0 )
return rData . TargetName ;
2024-05-19 16:40:40 +05:30
2025-02-15 12:51:16 +05:30
if ( rData . SvcPriority = = 0 ) //alias mode
return null ;
2024-05-19 16:40:40 +05:30
2025-02-15 12:51:16 +05:30
//service mode
return svcbRecord . Name ;
}
2024-05-19 16:40:40 +05:30
2025-02-15 12:51:16 +05:30
private void ResolveSvcbAutoHints ( string zoneName , DnsResourceRecord svcbRecord , bool resolveIpv4Hint , bool resolveIpv6Hint , Dictionary < DnsSvcParamKey , DnsSvcParamValue > svcParams , IReadOnlyCollection < DnsResourceRecord > importRecords = null )
{
string targetName = GetSvcbTargetName ( svcbRecord ) ;
if ( targetName is not null )
ResolveSvcbAutoHints ( zoneName , targetName , resolveIpv4Hint , resolveIpv6Hint , svcParams , importRecords ) ;
2024-05-19 16:40:40 +05:30
}
2025-02-15 12:51:16 +05:30
private void ResolveSvcbAutoHints ( string zoneName , string targetName , bool resolveIpv4Hint , bool resolveIpv6Hint , Dictionary < DnsSvcParamKey , DnsSvcParamValue > svcParams , IReadOnlyCollection < DnsResourceRecord > importRecords = null )
{
if ( resolveIpv4Hint )
{
List < IPAddress > ipv4Hint = new List < IPAddress > ( ) ;
2024-05-19 16:40:40 +05:30
2025-02-15 12:51:16 +05:30
IReadOnlyList < DnsResourceRecord > records = _dnsWebService . _dnsServer . AuthZoneManager . GetRecords ( zoneName , targetName , DnsResourceRecordType . A ) ;
2024-06-01 19:25:07 +05:30
2025-02-15 12:51:16 +05:30
foreach ( DnsResourceRecord record in records )
{
if ( record . GetAuthGenericRecordInfo ( ) . Disabled )
continue ;
2024-06-01 19:25:07 +05:30
2025-02-15 12:51:16 +05:30
ipv4Hint . Add ( ( record . RDATA as DnsARecordData ) . Address ) ;
}
2024-06-01 19:25:07 +05:30
2025-02-15 12:51:16 +05:30
if ( importRecords is not null )
{
foreach ( DnsResourceRecord record in importRecords )
{
if ( record . Type ! = DnsResourceRecordType . A )
continue ;
2024-06-01 19:25:07 +05:30
2025-02-15 12:51:16 +05:30
if ( record . Name . Equals ( targetName , StringComparison . OrdinalIgnoreCase ) )
{
IPAddress address = ( record . RDATA as DnsARecordData ) . Address ;
2024-06-01 19:25:07 +05:30
2025-02-15 12:51:16 +05:30
if ( ! ipv4Hint . Contains ( address ) )
ipv4Hint . Add ( address ) ;
}
}
}
2024-06-01 19:25:07 +05:30
2025-02-15 12:51:16 +05:30
if ( ipv4Hint . Count > 0 )
svcParams [ DnsSvcParamKey . IPv4Hint ] = new DnsSvcIPv4HintParamValue ( ipv4Hint ) ;
else
svcParams . Remove ( DnsSvcParamKey . IPv4Hint ) ;
}
2024-06-01 19:25:07 +05:30
2025-02-15 12:51:16 +05:30
if ( resolveIpv6Hint )
2024-06-01 19:25:07 +05:30
{
2025-02-15 12:51:16 +05:30
List < IPAddress > ipv6Hint = new List < IPAddress > ( ) ;
2024-06-01 19:25:07 +05:30
2025-02-15 12:51:16 +05:30
IReadOnlyList < DnsResourceRecord > records = _dnsWebService . _dnsServer . AuthZoneManager . GetRecords ( zoneName , targetName , DnsResourceRecordType . AAAA ) ;
2024-06-01 19:25:07 +05:30
2025-02-15 12:51:16 +05:30
foreach ( DnsResourceRecord record in records )
2024-06-01 19:25:07 +05:30
{
2025-02-15 12:51:16 +05:30
if ( record . GetAuthGenericRecordInfo ( ) . Disabled )
2024-06-01 19:25:07 +05:30
continue ;
2025-02-15 12:51:16 +05:30
ipv6Hint . Add ( ( record . RDATA as DnsAAAARecordData ) . Address ) ;
}
if ( importRecords is not null )
{
foreach ( DnsResourceRecord record in importRecords )
2024-06-01 19:25:07 +05:30
{
2025-02-15 12:51:16 +05:30
if ( record . Type ! = DnsResourceRecordType . AAAA )
continue ;
2024-06-01 19:25:07 +05:30
2025-02-15 12:51:16 +05:30
if ( record . Name . Equals ( targetName , StringComparison . OrdinalIgnoreCase ) )
{
IPAddress address = ( record . RDATA as DnsAAAARecordData ) . Address ;
if ( ! ipv6Hint . Contains ( address ) )
ipv6Hint . Add ( address ) ;
}
2024-06-01 19:25:07 +05:30
}
}
2025-02-15 12:51:16 +05:30
if ( ipv6Hint . Count > 0 )
svcParams [ DnsSvcParamKey . IPv6Hint ] = new DnsSvcIPv6HintParamValue ( ipv6Hint ) ;
else
svcParams . Remove ( DnsSvcParamKey . IPv6Hint ) ;
}
2024-06-01 19:25:07 +05:30
}
2025-02-15 12:51:16 +05:30
private void UpdateSvcbAutoHints ( string zoneName , string targetName , bool resolveIpv4Hint , bool resolveIpv6Hint )
2024-06-01 19:25:07 +05:30
{
2025-02-15 12:51:16 +05:30
List < DnsResourceRecord > allSvcbRecords = new List < DnsResourceRecord > ( ) ;
_dnsWebService . _dnsServer . AuthZoneManager . ListAllZoneRecords ( zoneName , [ DnsResourceRecordType . SVCB , DnsResourceRecordType . HTTPS ] , allSvcbRecords ) ;
2024-06-01 19:25:07 +05:30
2025-02-15 12:51:16 +05:30
foreach ( DnsResourceRecord record in allSvcbRecords )
2024-06-01 19:25:07 +05:30
{
2025-02-15 12:51:16 +05:30
SVCBRecordInfo info = record . GetAuthSVCBRecordInfo ( ) ;
if ( ( info . AutoIpv4Hint & & resolveIpv4Hint ) | | ( info . AutoIpv6Hint & & resolveIpv6Hint ) )
2024-06-01 19:25:07 +05:30
{
2025-02-15 12:51:16 +05:30
string scvbTargetName = GetSvcbTargetName ( record ) ;
if ( targetName . Equals ( scvbTargetName , StringComparison . OrdinalIgnoreCase ) )
2024-06-01 19:25:07 +05:30
{
2025-02-15 12:51:16 +05:30
DnsSVCBRecordData oldRData = record . RDATA as DnsSVCBRecordData ;
Dictionary < DnsSvcParamKey , DnsSvcParamValue > newSvcParams = new Dictionary < DnsSvcParamKey , DnsSvcParamValue > ( oldRData . SvcParams ) ;
ResolveSvcbAutoHints ( zoneName , targetName , resolveIpv4Hint , resolveIpv6Hint , newSvcParams ) ;
2024-06-01 19:25:07 +05:30
2025-02-15 12:51:16 +05:30
DnsSVCBRecordData newRData = new DnsSVCBRecordData ( oldRData . SvcPriority , oldRData . TargetName , newSvcParams ) ;
DnsResourceRecord newRecord = new DnsResourceRecord ( record . Name , record . Type , record . Class , record . TTL , newRData ) { Tag = record . Tag } ;
_dnsWebService . _dnsServer . AuthZoneManager . UpdateRecord ( zoneName , record , newRecord ) ;
2024-06-01 19:25:07 +05:30
}
}
}
}
2025-04-19 16:03:13 +05:30
private async Task < List < DnsResourceRecord > > ReadRecordsToImportFromAsync ( string zoneName , TextReader zoneFile )
{
List < DnsResourceRecord > records = await ZoneFile . ReadZoneFileFromAsync ( zoneFile , zoneName , _dnsWebService . _zonesApi . DefaultRecordTtl ) ;
List < DnsResourceRecord > newRecords = new List < DnsResourceRecord > ( records . Count ) ;
foreach ( DnsResourceRecord record in records )
{
if ( record . Class ! = DnsClass . IN )
throw new DnsWebServiceException ( "Cannot import records: only IN class is supported by the DNS server." ) ;
if ( ! AuthZoneManager . DomainBelongsToZone ( zoneName , record . Name ) )
{
switch ( record . Type )
{
case DnsResourceRecordType . A :
case DnsResourceRecordType . AAAA :
continue ; //glue records
default :
throw new DnsServerException ( "Cannot import records: the domain name '" + record . Name + "' does not belong to the zone '" + zoneName + "'." ) ;
}
}
switch ( record . Type )
{
case DnsResourceRecordType . DNSKEY :
case DnsResourceRecordType . RRSIG :
case DnsResourceRecordType . NSEC :
case DnsResourceRecordType . NSEC3 :
case DnsResourceRecordType . NSEC3PARAM :
continue ; //skip DNSSEC records
case DnsResourceRecordType . NS :
{
if ( record . Tag is string comments )
{
NSRecordInfo rrInfo = new NSRecordInfo ( ) ;
rrInfo . Comments = comments ;
record . Tag = rrInfo ;
}
record . SyncGlueRecords ( records ) ;
newRecords . Add ( record ) ;
}
break ;
case DnsResourceRecordType . SOA :
{
if ( record . Tag is string comments )
{
SOARecordInfo rrInfo = new SOARecordInfo ( ) ;
rrInfo . Comments = comments ;
record . Tag = rrInfo ;
}
newRecords . Add ( record ) ;
}
break ;
case DnsResourceRecordType . SVCB :
case DnsResourceRecordType . HTTPS :
{
if ( record . Tag is string comments )
{
SVCBRecordInfo rrInfo = new SVCBRecordInfo ( ) ;
rrInfo . Comments = comments ;
record . Tag = rrInfo ;
}
if ( record . RDATA is DnsSVCBRecordData rdata & & ( rdata . AutoIpv4Hint | | rdata . AutoIpv6Hint ) )
{
if ( rdata . AutoIpv4Hint )
record . GetAuthSVCBRecordInfo ( ) . AutoIpv4Hint = true ;
if ( rdata . AutoIpv6Hint )
record . GetAuthSVCBRecordInfo ( ) . AutoIpv6Hint = true ;
Dictionary < DnsSvcParamKey , DnsSvcParamValue > svcParams = new Dictionary < DnsSvcParamKey , DnsSvcParamValue > ( rdata . SvcParams ) ;
DnsResourceRecord newRecord = new DnsResourceRecord ( record . Name , record . Type , record . Class , record . TTL , new DnsSVCBRecordData ( rdata . SvcPriority , rdata . TargetName , svcParams ) ) { Tag = record . Tag } ;
ResolveSvcbAutoHints ( zoneName , record , rdata . AutoIpv4Hint , rdata . AutoIpv6Hint , svcParams , records ) ;
newRecords . Add ( newRecord ) ;
break ;
}
newRecords . Add ( record ) ;
}
break ;
default :
{
if ( record . Tag is string comments )
{
GenericRecordInfo rrInfo = new GenericRecordInfo ( ) ;
rrInfo . Comments = comments ;
record . Tag = rrInfo ;
}
newRecords . Add ( record ) ;
}
break ;
}
}
return newRecords ;
}
2025-02-15 12:51:16 +05:30
#endregion
#region public
2024-06-01 19:25:07 +05:30
2025-02-15 12:51:16 +05:30
public void ListZones ( HttpContext context )
2024-06-01 19:25:07 +05:30
{
2025-02-15 12:51:16 +05:30
UserSession session = context . GetCurrentSession ( ) ;
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , session . User , PermissionFlag . View ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
HttpRequest request = context . Request ;
Utf8JsonWriter jsonWriter = context . GetCurrentJsonWriter ( ) ;
IReadOnlyList < AuthZoneInfo > zoneInfoList = _dnsWebService . _dnsServer . AuthZoneManager . GetZones ( delegate ( AuthZoneInfo zoneInfo )
{
return _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , zoneInfo . Name , session . User , PermissionFlag . View ) ;
} ) ;
if ( request . TryGetQueryOrForm ( "pageNumber" , int . Parse , out int pageNumber ) )
2024-06-01 19:25:07 +05:30
{
2025-02-15 12:51:16 +05:30
int zonesPerPage = request . GetQueryOrForm ( "zonesPerPage" , int . Parse , 10 ) ;
int totalPages ;
int totalZones = zoneInfoList . Count ;
if ( totalZones > 0 )
2024-06-01 19:25:07 +05:30
{
2025-02-15 12:51:16 +05:30
if ( pageNumber = = 0 )
pageNumber = 1 ;
2024-06-01 19:25:07 +05:30
2025-02-15 12:51:16 +05:30
totalPages = ( totalZones / zonesPerPage ) + ( totalZones % zonesPerPage > 0 ? 1 : 0 ) ;
2024-06-01 19:25:07 +05:30
2025-02-15 12:51:16 +05:30
if ( ( pageNumber > totalPages ) | | ( pageNumber < 0 ) )
pageNumber = totalPages ;
2024-06-01 19:25:07 +05:30
2025-02-15 12:51:16 +05:30
int start = ( pageNumber - 1 ) * zonesPerPage ;
int end = Math . Min ( start + zonesPerPage , totalZones ) ;
2024-06-01 19:25:07 +05:30
2025-02-15 12:51:16 +05:30
List < AuthZoneInfo > zoneInfoPageList = new List < AuthZoneInfo > ( end - start ) ;
2022-05-14 13:49:05 +05:30
2025-02-15 12:51:16 +05:30
for ( int i = start ; i < end ; i + + )
zoneInfoPageList . Add ( zoneInfoList [ i ] ) ;
2022-05-14 13:49:05 +05:30
2025-02-15 12:51:16 +05:30
zoneInfoList = zoneInfoPageList ;
}
else
{
pageNumber = 0 ;
totalPages = 0 ;
}
jsonWriter . WriteNumber ( "pageNumber" , pageNumber ) ;
jsonWriter . WriteNumber ( "totalPages" , totalPages ) ;
jsonWriter . WriteNumber ( "totalZones" , totalZones ) ;
}
2023-01-01 18:39:46 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WritePropertyName ( "zones" ) ;
jsonWriter . WriteStartArray ( ) ;
2023-01-01 18:39:46 +05:30
2025-02-15 12:51:16 +05:30
foreach ( AuthZoneInfo zoneInfo in zoneInfoList )
WriteZoneInfoAsJson ( zoneInfo , jsonWriter ) ;
2024-10-19 17:10:15 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndArray ( ) ;
}
2023-02-12 13:19:41 +05:30
2025-02-15 12:51:16 +05:30
public void ListCatalogZones ( HttpContext context )
2023-02-12 13:19:41 +05:30
{
2025-02-15 12:51:16 +05:30
UserSession session = context . GetCurrentSession ( ) ;
2023-02-12 13:19:41 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , session . User , PermissionFlag . View ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
Utf8JsonWriter jsonWriter = context . GetCurrentJsonWriter ( ) ;
IReadOnlyList < AuthZoneInfo > catalogZoneInfoList = _dnsWebService . _dnsServer . AuthZoneManager . GetCatalogZones ( delegate ( AuthZoneInfo catalogZoneInfo )
2024-10-19 17:10:15 +05:30
{
2025-02-15 12:51:16 +05:30
return ! catalogZoneInfo . Disabled & & _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , catalogZoneInfo . Name , session . User , PermissionFlag . Modify ) ;
} ) ;
jsonWriter . WritePropertyName ( "catalogZoneNames" ) ;
jsonWriter . WriteStartArray ( ) ;
foreach ( AuthZoneInfo catalogZoneInfo in catalogZoneInfoList )
jsonWriter . WriteStringValue ( catalogZoneInfo . Name ) ;
2023-02-12 13:19:41 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndArray ( ) ;
}
2024-10-19 17:10:15 +05:30
2025-02-15 12:51:16 +05:30
public async Task CreateZoneAsync ( HttpContext context )
{
UserSession session = context . GetCurrentSession ( ) ;
2024-10-19 17:10:15 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , session . User , PermissionFlag . Modify ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2024-10-19 17:10:15 +05:30
2025-02-15 12:51:16 +05:30
HttpRequest request = context . Request ;
2024-10-19 17:10:15 +05:30
2025-02-15 12:51:16 +05:30
string zoneName = request . GetQueryOrFormAlt ( "zone" , "domain" ) ;
if ( zoneName . Contains ( '*' ) )
throw new DnsWebServiceException ( "Domain name for a zone cannot contain wildcard character." ) ;
2024-10-19 17:10:15 +05:30
2025-02-15 12:51:16 +05:30
if ( IPAddress . TryParse ( zoneName , out IPAddress ipAddress ) )
{
zoneName = ipAddress . GetReverseDomain ( ) . ToLowerInvariant ( ) ;
2024-10-19 17:10:15 +05:30
}
2025-02-15 12:51:16 +05:30
else if ( zoneName . Contains ( '/' ) )
{
string [ ] parts = zoneName . Split ( '/' ) ;
if ( ( parts . Length = = 2 ) & & IPAddress . TryParse ( parts [ 0 ] , out ipAddress ) & & int . TryParse ( parts [ 1 ] , out int subnetMaskWidth ) )
zoneName = Zone . GetReverseZone ( ipAddress , subnetMaskWidth ) ;
}
else if ( zoneName . EndsWith ( '.' ) )
2024-10-19 17:10:15 +05:30
{
2025-02-15 12:51:16 +05:30
zoneName = zoneName . Substring ( 0 , zoneName . Length - 1 ) ;
2024-10-19 17:10:15 +05:30
}
2025-02-15 12:51:16 +05:30
if ( DnsClient . IsDomainNameUnicode ( zoneName ) )
zoneName = DnsClient . ConvertDomainNameToAscii ( zoneName ) ;
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
AuthZoneType type = request . GetQueryOrFormEnum ( "type" , AuthZoneType . Primary ) ;
2025-04-19 16:03:13 +05:30
//read records to import, if any
List < DnsResourceRecord > importRecords = null ;
switch ( type )
{
case AuthZoneType . Primary :
case AuthZoneType . Forwarder :
if ( request . HasFormContentType & & ( request . Form . Files . Count > 0 ) )
{
using ( TextReader zoneFile = new StreamReader ( request . Form . Files [ 0 ] . OpenReadStream ( ) ) )
{
importRecords = await ReadRecordsToImportFromAsync ( zoneName , zoneFile ) ;
}
}
break ;
}
//create zone
2025-02-15 12:51:16 +05:30
AuthZoneInfo zoneInfo ;
2022-05-14 13:49:05 +05:30
2025-02-15 12:51:16 +05:30
switch ( type )
{
case AuthZoneType . Primary :
{
bool useSoaSerialDateScheme = request . GetQueryOrForm ( "useSoaSerialDateScheme" , bool . Parse , _dnsWebService . _dnsServer . AuthZoneManager . UseSoaSerialDateScheme ) ;
string catalogZoneName = request . GetQueryOrForm ( "catalog" , null ) ;
2022-05-14 13:49:05 +05:30
2025-02-15 12:51:16 +05:30
AuthZoneInfo catalogZoneInfo = null ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
if ( catalogZoneName is not null )
{
catalogZoneInfo = _dnsWebService . _dnsServer . AuthZoneManager . GetAuthZoneInfo ( catalogZoneName ) ;
if ( catalogZoneInfo is null )
throw new DnsWebServiceException ( "No such Catalog zone was found: " + catalogZoneName ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , catalogZoneInfo . Name , session . User , PermissionFlag . Modify ) )
throw new DnsWebServiceException ( "Access was denied to use Catalog zone: " + catalogZoneInfo . Name ) ;
}
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
zoneInfo = _dnsWebService . _dnsServer . AuthZoneManager . CreatePrimaryZone ( zoneName , useSoaSerialDateScheme ) ;
if ( zoneInfo is null )
throw new DnsWebServiceException ( "Zone already exists: " + zoneName ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
//set permissions
_dnsWebService . _authManager . SetPermission ( PermissionSection . Zones , zoneInfo . Name , session . User , PermissionFlag . ViewModifyDelete ) ;
_dnsWebService . _authManager . SetPermission ( PermissionSection . Zones , zoneInfo . Name , _dnsWebService . _authManager . GetGroup ( Group . ADMINISTRATORS ) , PermissionFlag . ViewModifyDelete ) ;
_dnsWebService . _authManager . SetPermission ( PermissionSection . Zones , zoneInfo . Name , _dnsWebService . _authManager . GetGroup ( Group . DNS_ADMINISTRATORS ) , PermissionFlag . ViewModifyDelete ) ;
_dnsWebService . _authManager . SaveConfigFile ( ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
//add membership for catalog zone
if ( catalogZoneInfo is not null )
_dnsWebService . _dnsServer . AuthZoneManager . AddCatalogMemberZone ( catalogZoneInfo . Name , zoneInfo ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _log . Write ( context . GetRemoteEndPoint ( _dnsWebService . _webServiceRealIpHeader ) , "[" + session . User . Username + "] Authoritative Primary zone was created: " + zoneInfo . DisplayName ) ;
}
break ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
case AuthZoneType . Secondary :
{
string primaryNameServerAddresses = request . GetQueryOrForm ( "primaryNameServerAddresses" , null ) ;
DnsTransportProtocol primaryZoneTransferProtocol = request . GetQueryOrFormEnum ( "zoneTransferProtocol" , DnsTransportProtocol . Tcp ) ;
string primaryZoneTransferTsigKeyName = request . GetQueryOrForm ( "tsigKeyName" , null ) ;
bool validateZone = request . GetQueryOrForm ( "validateZone" , bool . Parse , false ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
if ( primaryZoneTransferProtocol = = DnsTransportProtocol . Quic )
DnsWebService . ValidateQuicSupport ( ) ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
zoneInfo = await _dnsWebService . _dnsServer . AuthZoneManager . CreateSecondaryZoneAsync ( zoneName , primaryNameServerAddresses , primaryZoneTransferProtocol , primaryZoneTransferTsigKeyName , validateZone ) ;
if ( zoneInfo is null )
throw new DnsWebServiceException ( "Zone already exists: " + zoneName ) ;
2023-01-01 18:39:46 +05:30
2025-02-15 12:51:16 +05:30
//set permissions
_dnsWebService . _authManager . SetPermission ( PermissionSection . Zones , zoneInfo . Name , session . User , PermissionFlag . ViewModifyDelete ) ;
_dnsWebService . _authManager . SetPermission ( PermissionSection . Zones , zoneInfo . Name , _dnsWebService . _authManager . GetGroup ( Group . ADMINISTRATORS ) , PermissionFlag . ViewModifyDelete ) ;
_dnsWebService . _authManager . SetPermission ( PermissionSection . Zones , zoneInfo . Name , _dnsWebService . _authManager . GetGroup ( Group . DNS_ADMINISTRATORS ) , PermissionFlag . ViewModifyDelete ) ;
_dnsWebService . _authManager . SaveConfigFile ( ) ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _log . Write ( context . GetRemoteEndPoint ( _dnsWebService . _webServiceRealIpHeader ) , "[" + session . User . Username + "] Authoritative Secondary zone was created: " + zoneInfo . DisplayName ) ;
}
break ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
case AuthZoneType . Stub :
{
string primaryNameServerAddresses = request . GetQueryOrForm ( "primaryNameServerAddresses" , null ) ;
string catalogZoneName = request . GetQueryOrForm ( "catalog" , null ) ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
AuthZoneInfo catalogZoneInfo = null ;
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
if ( catalogZoneName is not null )
{
catalogZoneInfo = _dnsWebService . _dnsServer . AuthZoneManager . GetAuthZoneInfo ( catalogZoneName ) ;
if ( catalogZoneInfo is null )
throw new DnsWebServiceException ( "No such Catalog zone was found: " + catalogZoneName ) ;
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , catalogZoneInfo . Name , session . User , PermissionFlag . Modify ) )
throw new DnsWebServiceException ( "Access was denied to use Catalog zone: " + catalogZoneInfo . Name ) ;
}
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
zoneInfo = await _dnsWebService . _dnsServer . AuthZoneManager . CreateStubZoneAsync ( zoneName , primaryNameServerAddresses ) ;
if ( zoneInfo is null )
throw new DnsWebServiceException ( "Zone already exists: " + zoneName ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
//set permissions
_dnsWebService . _authManager . SetPermission ( PermissionSection . Zones , zoneInfo . Name , session . User , PermissionFlag . ViewModifyDelete ) ;
_dnsWebService . _authManager . SetPermission ( PermissionSection . Zones , zoneInfo . Name , _dnsWebService . _authManager . GetGroup ( Group . ADMINISTRATORS ) , PermissionFlag . ViewModifyDelete ) ;
_dnsWebService . _authManager . SetPermission ( PermissionSection . Zones , zoneInfo . Name , _dnsWebService . _authManager . GetGroup ( Group . DNS_ADMINISTRATORS ) , PermissionFlag . ViewModifyDelete ) ;
_dnsWebService . _authManager . SaveConfigFile ( ) ;
2024-10-19 17:10:15 +05:30
2025-02-15 12:51:16 +05:30
//add membership for catalog zone
if ( catalogZoneInfo is not null )
_dnsWebService . _dnsServer . AuthZoneManager . AddCatalogMemberZone ( catalogZoneInfo . Name , zoneInfo ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _log . Write ( context . GetRemoteEndPoint ( _dnsWebService . _webServiceRealIpHeader ) , "[" + session . User . Username + "] Stub zone was created: " + zoneInfo . DisplayName ) ;
}
break ;
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
case AuthZoneType . Forwarder :
{
2025-04-19 16:03:13 +05:30
bool initializeForwarder = request . GetQueryOrForm ( "initializeForwarder" , bool . Parse , true ) ;
2025-02-15 12:51:16 +05:30
string catalogZoneName = request . GetQueryOrForm ( "catalog" , null ) ;
2023-01-14 15:16:46 +05:30
2025-02-15 12:51:16 +05:30
AuthZoneInfo catalogZoneInfo = null ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( catalogZoneName is not null )
{
catalogZoneInfo = _dnsWebService . _dnsServer . AuthZoneManager . GetAuthZoneInfo ( catalogZoneName ) ;
if ( catalogZoneInfo is null )
throw new DnsWebServiceException ( "No such Catalog zone was found: " + catalogZoneName ) ;
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , catalogZoneInfo . Name , session . User , PermissionFlag . Modify ) )
throw new DnsWebServiceException ( "Access was denied to use Catalog zone: " + catalogZoneInfo . Name ) ;
}
2021-09-18 19:02:40 +05:30
2025-04-19 16:03:13 +05:30
if ( initializeForwarder )
{
DnsTransportProtocol forwarderProtocol = request . GetQueryOrFormEnum ( "protocol" , DnsTransportProtocol . Udp ) ;
string forwarder = request . GetQueryOrForm ( "forwarder" ) ;
bool dnssecValidation = request . GetQueryOrForm ( "dnssecValidation" , bool . Parse , false ) ;
DnsForwarderRecordProxyType proxyType = request . GetQueryOrFormEnum ( "proxyType" , DnsForwarderRecordProxyType . DefaultProxy ) ;
string proxyAddress = null ;
ushort proxyPort = 0 ;
string proxyUsername = null ;
string proxyPassword = null ;
switch ( proxyType )
{
case DnsForwarderRecordProxyType . Http :
case DnsForwarderRecordProxyType . Socks5 :
proxyAddress = request . GetQueryOrForm ( "proxyAddress" ) ;
proxyPort = request . GetQueryOrForm ( "proxyPort" , ushort . Parse ) ;
proxyUsername = request . QueryOrForm ( "proxyUsername" ) ;
proxyPassword = request . QueryOrForm ( "proxyPassword" ) ;
break ;
}
if ( forwarderProtocol = = DnsTransportProtocol . Quic )
DnsWebService . ValidateQuicSupport ( ) ;
zoneInfo = _dnsWebService . _dnsServer . AuthZoneManager . CreateForwarderZone ( zoneName , forwarderProtocol , forwarder , dnssecValidation , proxyType , proxyAddress , proxyPort , proxyUsername , proxyPassword , null ) ;
if ( zoneInfo is null )
throw new DnsWebServiceException ( "Zone already exists: " + zoneName ) ;
}
else
{
zoneInfo = _dnsWebService . _dnsServer . AuthZoneManager . CreateForwarderZone ( zoneName ) ;
if ( zoneInfo is null )
throw new DnsWebServiceException ( "Zone already exists: " + zoneName ) ;
}
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
//set permissions
_dnsWebService . _authManager . SetPermission ( PermissionSection . Zones , zoneInfo . Name , session . User , PermissionFlag . ViewModifyDelete ) ;
_dnsWebService . _authManager . SetPermission ( PermissionSection . Zones , zoneInfo . Name , _dnsWebService . _authManager . GetGroup ( Group . ADMINISTRATORS ) , PermissionFlag . ViewModifyDelete ) ;
_dnsWebService . _authManager . SetPermission ( PermissionSection . Zones , zoneInfo . Name , _dnsWebService . _authManager . GetGroup ( Group . DNS_ADMINISTRATORS ) , PermissionFlag . ViewModifyDelete ) ;
_dnsWebService . _authManager . SaveConfigFile ( ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
//add membership for catalog zone
if ( catalogZoneInfo is not null )
_dnsWebService . _dnsServer . AuthZoneManager . AddCatalogMemberZone ( catalogZoneInfo . Name , zoneInfo ) ;
2024-10-19 17:10:15 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _log . Write ( context . GetRemoteEndPoint ( _dnsWebService . _webServiceRealIpHeader ) , "[" + session . User . Username + "] Forwarder zone was created: " + zoneInfo . DisplayName ) ;
2024-09-15 15:14:12 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
case AuthZoneType . SecondaryForwarder :
{
string primaryNameServerAddresses = request . GetQueryOrForm ( "primaryNameServerAddresses" ) ;
DnsTransportProtocol primaryZoneTransferProtocol = request . GetQueryOrFormEnum ( "zoneTransferProtocol" , DnsTransportProtocol . Tcp ) ;
string primaryZoneTransferTsigKeyName = request . GetQueryOrForm ( "tsigKeyName" , null ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( primaryZoneTransferProtocol = = DnsTransportProtocol . Quic )
DnsWebService . ValidateQuicSupport ( ) ;
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
zoneInfo = _dnsWebService . _dnsServer . AuthZoneManager . CreateSecondaryForwarderZone ( zoneName , primaryNameServerAddresses , primaryZoneTransferProtocol , primaryZoneTransferTsigKeyName ) ;
if ( zoneInfo is null )
throw new DnsWebServiceException ( "Zone already exists: " + zoneName ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
//set permissions
_dnsWebService . _authManager . SetPermission ( PermissionSection . Zones , zoneInfo . Name , session . User , PermissionFlag . ViewModifyDelete ) ;
_dnsWebService . _authManager . SetPermission ( PermissionSection . Zones , zoneInfo . Name , _dnsWebService . _authManager . GetGroup ( Group . ADMINISTRATORS ) , PermissionFlag . ViewModifyDelete ) ;
_dnsWebService . _authManager . SetPermission ( PermissionSection . Zones , zoneInfo . Name , _dnsWebService . _authManager . GetGroup ( Group . DNS_ADMINISTRATORS ) , PermissionFlag . ViewModifyDelete ) ;
_dnsWebService . _authManager . SaveConfigFile ( ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _log . Write ( context . GetRemoteEndPoint ( _dnsWebService . _webServiceRealIpHeader ) , "[" + session . User . Username + "] Secondary Forwarder zone was created: " + zoneInfo . DisplayName ) ;
2023-01-14 15:16:46 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
2023-01-14 15:16:46 +05:30
2025-02-15 12:51:16 +05:30
case AuthZoneType . Catalog :
{
zoneInfo = _dnsWebService . _dnsServer . AuthZoneManager . CreateCatalogZone ( zoneName ) ;
if ( zoneInfo is null )
throw new DnsWebServiceException ( "Zone already exists: " + zoneName ) ;
2023-01-14 15:16:46 +05:30
2025-02-15 12:51:16 +05:30
//set permissions
_dnsWebService . _authManager . SetPermission ( PermissionSection . Zones , zoneInfo . Name , session . User , PermissionFlag . ViewModifyDelete ) ;
_dnsWebService . _authManager . SetPermission ( PermissionSection . Zones , zoneInfo . Name , _dnsWebService . _authManager . GetGroup ( Group . ADMINISTRATORS ) , PermissionFlag . ViewModifyDelete ) ;
_dnsWebService . _authManager . SetPermission ( PermissionSection . Zones , zoneInfo . Name , _dnsWebService . _authManager . GetGroup ( Group . DNS_ADMINISTRATORS ) , PermissionFlag . ViewModifyDelete ) ;
_dnsWebService . _authManager . SaveConfigFile ( ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _log . Write ( context . GetRemoteEndPoint ( _dnsWebService . _webServiceRealIpHeader ) , "[" + session . User . Username + "] Catalog zone was created: " + zoneInfo . DisplayName ) ;
}
break ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
case AuthZoneType . SecondaryCatalog :
2024-09-15 15:14:12 +05:30
{
2025-02-15 12:51:16 +05:30
string primaryNameServerAddresses = request . GetQueryOrForm ( "primaryNameServerAddresses" ) ;
DnsTransportProtocol primaryZoneTransferProtocol = request . GetQueryOrFormEnum ( "zoneTransferProtocol" , DnsTransportProtocol . Tcp ) ;
string primaryZoneTransferTsigKeyName = request . GetQueryOrForm ( "tsigKeyName" , null ) ;
if ( primaryZoneTransferProtocol = = DnsTransportProtocol . Quic )
DnsWebService . ValidateQuicSupport ( ) ;
zoneInfo = _dnsWebService . _dnsServer . AuthZoneManager . CreateSecondaryCatalogZone ( zoneName , primaryNameServerAddresses , primaryZoneTransferProtocol , primaryZoneTransferTsigKeyName ) ;
if ( zoneInfo is null )
throw new DnsWebServiceException ( "Zone already exists: " + zoneName ) ;
//set permissions
_dnsWebService . _authManager . SetPermission ( PermissionSection . Zones , zoneInfo . Name , session . User , PermissionFlag . ViewModifyDelete ) ;
_dnsWebService . _authManager . SetPermission ( PermissionSection . Zones , zoneInfo . Name , _dnsWebService . _authManager . GetGroup ( Group . ADMINISTRATORS ) , PermissionFlag . ViewModifyDelete ) ;
_dnsWebService . _authManager . SetPermission ( PermissionSection . Zones , zoneInfo . Name , _dnsWebService . _authManager . GetGroup ( Group . DNS_ADMINISTRATORS ) , PermissionFlag . ViewModifyDelete ) ;
_dnsWebService . _authManager . SaveConfigFile ( ) ;
2024-10-19 17:10:15 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _log . Write ( context . GetRemoteEndPoint ( _dnsWebService . _webServiceRealIpHeader ) , "[" + session . User . Username + "] Secondary Catalog zone was created: " + zoneInfo . DisplayName ) ;
2022-04-30 16:19:02 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
default :
throw new NotSupportedException ( "Zone type not supported." ) ;
}
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
//delete cache for this zone to allow rebuilding cache data as needed by stub or forwarder zones
_dnsWebService . _dnsServer . CacheZoneManager . DeleteZone ( zoneInfo . Name ) ;
2022-09-18 18:00:21 +05:30
2025-04-19 16:03:13 +05:30
//import records, if any
if ( importRecords is not null )
{
//delete existing NS/FWD record
switch ( type )
{
case AuthZoneType . Primary :
_dnsWebService . _dnsServer . AuthZoneManager . DeleteRecords ( zoneInfo . Name , zoneInfo . Name , DnsResourceRecordType . NS ) ;
break ;
case AuthZoneType . Forwarder :
_dnsWebService . _dnsServer . AuthZoneManager . DeleteRecords ( zoneInfo . Name , zoneInfo . Name , DnsResourceRecordType . FWD ) ;
break ;
}
//import records
_dnsWebService . _dnsServer . AuthZoneManager . ImportRecords ( zoneInfo . Name , importRecords , false , false ) ;
}
2025-02-15 12:51:16 +05:30
Utf8JsonWriter jsonWriter = context . GetCurrentJsonWriter ( ) ;
jsonWriter . WriteString ( "domain" , string . IsNullOrEmpty ( zoneInfo . Name ) ? "." : zoneInfo . Name ) ;
}
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
public async Task ImportZoneAsync ( HttpContext context )
{
UserSession session = context . GetCurrentSession ( ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , session . User , PermissionFlag . Modify ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
HttpRequest request = context . Request ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
string zoneName = request . GetQueryOrForm ( "zone" ) . TrimEnd ( '.' ) ;
if ( DnsClient . IsDomainNameUnicode ( zoneName ) )
zoneName = DnsClient . ConvertDomainNameToAscii ( zoneName ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
AuthZoneInfo zoneInfo = _dnsWebService . _dnsServer . AuthZoneManager . GetAuthZoneInfo ( zoneName ) ;
if ( zoneInfo is null )
throw new DnsWebServiceException ( "No such zone was found: " + zoneName ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
if ( zoneInfo . Internal )
throw new DnsWebServiceException ( "Access was denied to manage internal DNS Server zone." ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , zoneInfo . Name , session . User , PermissionFlag . Modify ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2024-09-15 15:14:12 +05:30
2025-03-29 18:58:25 +05:30
string importType = request . GetQueryOrForm ( "importType" , "Text" ) ;
2025-02-15 12:51:16 +05:30
bool overwrite = request . GetQueryOrForm ( "overwrite" , bool . Parse , true ) ;
bool overwriteSoaSerial = request . GetQueryOrForm ( "overwriteSoaSerial" , bool . Parse , false ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
TextReader textReader ;
2024-09-15 15:14:12 +05:30
2025-03-29 18:58:25 +05:30
switch ( importType . ToUpperInvariant ( ) )
2025-02-15 12:51:16 +05:30
{
2025-03-29 18:58:25 +05:30
case "FILE" :
2025-04-19 16:03:13 +05:30
if ( ! request . HasFormContentType | | ( request . Form . Files . Count = = 0 ) )
2025-03-29 18:58:25 +05:30
throw new DnsWebServiceException ( "The zone file to import is missing." ) ;
textReader = new StreamReader ( request . Form . Files [ 0 ] . OpenReadStream ( ) ) ;
2025-02-15 12:51:16 +05:30
break ;
2024-09-15 15:14:12 +05:30
2025-03-29 18:58:25 +05:30
case "TEXT" :
switch ( request . ContentType ? . ToLowerInvariant ( ) )
{
case "application/x-www-form-urlencoded" :
string zoneRecords = request . GetQueryOrForm ( "records" ) ;
textReader = new StringReader ( zoneRecords ) ;
break ;
case "text/plain" :
textReader = new StreamReader ( request . Body ) ;
break ;
default :
throw new DnsWebServiceException ( "Content type is not supported: " + request . ContentType ) ;
}
2025-02-15 12:51:16 +05:30
break ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
default :
2025-03-29 18:58:25 +05:30
throw new DnsWebServiceException ( "Import type is not supported: " + importType ) ;
2025-02-15 12:51:16 +05:30
}
2024-09-15 15:14:12 +05:30
2025-04-19 16:03:13 +05:30
List < DnsResourceRecord > records ;
2024-09-15 15:14:12 +05:30
2025-04-19 16:03:13 +05:30
using ( TextReader zoneFile = textReader )
2025-02-15 12:51:16 +05:30
{
2025-04-19 16:03:13 +05:30
records = await ReadRecordsToImportFromAsync ( zoneInfo . Name , zoneFile ) ;
2025-02-15 12:51:16 +05:30
}
2023-10-29 20:18:58 +05:30
2025-04-19 16:03:13 +05:30
_dnsWebService . _dnsServer . AuthZoneManager . ImportRecords ( zoneInfo . Name , records , overwrite , overwriteSoaSerial ) ;
2023-10-29 20:18:58 +05:30
2025-04-19 16:03:13 +05:30
_dnsWebService . _log . Write ( context . GetRemoteEndPoint ( _dnsWebService . _webServiceRealIpHeader ) , "[" + session . User . Username + "] Total " + records . Count + " record(s) were imported successfully into " + zoneInfo . TypeName + " zone: " + zoneInfo . DisplayName ) ;
2023-10-29 20:18:58 +05:30
}
2025-02-15 12:51:16 +05:30
public async Task ExportZoneAsync ( HttpContext context )
{
UserSession session = context . GetCurrentSession ( ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , session . User , PermissionFlag . View ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
HttpRequest request = context . Request ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
string zoneName = request . GetQueryOrForm ( "zone" ) . TrimEnd ( '.' ) ;
if ( DnsClient . IsDomainNameUnicode ( zoneName ) )
zoneName = DnsClient . ConvertDomainNameToAscii ( zoneName ) ;
2024-06-01 19:25:07 +05:30
2025-02-15 12:51:16 +05:30
AuthZoneInfo zoneInfo = _dnsWebService . _dnsServer . AuthZoneManager . GetAuthZoneInfo ( zoneName ) ;
if ( zoneInfo is null )
throw new DnsWebServiceException ( "No such zone was found: " + zoneName ) ;
2024-06-01 19:25:07 +05:30
2025-02-15 12:51:16 +05:30
if ( zoneInfo . Internal )
throw new DnsWebServiceException ( "Access was denied to manage internal DNS Server zone." ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , zoneInfo . Name , session . User , PermissionFlag . View ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2024-06-01 19:25:07 +05:30
2025-02-15 12:51:16 +05:30
List < DnsResourceRecord > records = new List < DnsResourceRecord > ( ) ;
2024-06-01 19:25:07 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _dnsServer . AuthZoneManager . ListAllZoneRecords ( zoneInfo . Name , records ) ;
2024-06-01 19:25:07 +05:30
2025-02-15 12:51:16 +05:30
foreach ( DnsResourceRecord record in records )
{
switch ( record . Type )
{
case DnsResourceRecordType . SVCB :
case DnsResourceRecordType . HTTPS :
SVCBRecordInfo info = record . GetAuthSVCBRecordInfo ( ) ;
2024-06-01 19:25:07 +05:30
2025-02-15 12:51:16 +05:30
if ( info . AutoIpv4Hint )
( record . RDATA as DnsSVCBRecordData ) . AutoIpv4Hint = true ;
2024-06-01 19:25:07 +05:30
2025-02-15 12:51:16 +05:30
if ( info . AutoIpv6Hint )
( record . RDATA as DnsSVCBRecordData ) . AutoIpv6Hint = true ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
break ;
}
2023-10-29 20:18:58 +05:30
}
2025-02-15 12:51:16 +05:30
HttpResponse response = context . Response ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
response . ContentType = "text/plain" ;
response . Headers . ContentDisposition = "attachment;filename=" + ( zoneInfo . Name . Length = = 0 ? "root.zone" : zoneInfo . Name + ".zone" ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
await using ( StreamWriter sW = new StreamWriter ( response . Body ) )
{
await ZoneFile . WriteZoneFileToAsync ( sW , zoneInfo . Name , records , delegate ( DnsResourceRecord record )
{
if ( record . Tag is null )
return null ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
return record . GetAuthGenericRecordInfo ( ) . Comments ;
} ) ;
}
}
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
public void CloneZone ( HttpContext context )
{
UserSession session = context . GetCurrentSession ( ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , session . User , PermissionFlag . Modify ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
HttpRequest request = context . Request ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
string zoneName = request . GetQueryOrForm ( "zone" ) . TrimEnd ( '.' ) ;
if ( DnsClient . IsDomainNameUnicode ( zoneName ) )
zoneName = DnsClient . ConvertDomainNameToAscii ( zoneName ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
string sourceZoneName = request . GetQueryOrForm ( "sourceZone" ) . TrimEnd ( '.' ) ;
if ( DnsClient . IsDomainNameUnicode ( sourceZoneName ) )
sourceZoneName = DnsClient . ConvertDomainNameToAscii ( sourceZoneName ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
AuthZoneInfo sourceZoneInfo = _dnsWebService . _dnsServer . AuthZoneManager . GetAuthZoneInfo ( sourceZoneName ) ;
if ( sourceZoneInfo is null )
throw new DnsWebServiceException ( "No such zone was found: " + sourceZoneName ) ;
2024-06-01 19:25:07 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , sourceZoneInfo . Name , session . User , PermissionFlag . View ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2024-06-01 19:25:07 +05:30
2025-02-15 12:51:16 +05:30
AuthZoneInfo zoneInfo = _dnsWebService . _dnsServer . AuthZoneManager . CloneZone ( zoneName , sourceZoneInfo . Name ) ;
2024-06-01 19:25:07 +05:30
2025-02-15 12:51:16 +05:30
//clone user/group permissions from source zone
Permission sourceZonePermissions = _dnsWebService . _authManager . GetPermission ( PermissionSection . Zones , sourceZoneInfo . Name ) ;
2024-06-01 19:25:07 +05:30
2025-02-15 12:51:16 +05:30
foreach ( KeyValuePair < User , PermissionFlag > userPermission in sourceZonePermissions . UserPermissions )
_dnsWebService . _authManager . SetPermission ( PermissionSection . Zones , zoneInfo . Name , userPermission . Key , userPermission . Value ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
foreach ( KeyValuePair < Group , PermissionFlag > groupPermissions in sourceZonePermissions . GroupPermissions )
_dnsWebService . _authManager . SetPermission ( PermissionSection . Zones , zoneInfo . Name , groupPermissions . Key , groupPermissions . Value ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
//set default permissions
_dnsWebService . _authManager . SetPermission ( PermissionSection . Zones , zoneInfo . Name , session . User , PermissionFlag . ViewModifyDelete ) ;
_dnsWebService . _authManager . SetPermission ( PermissionSection . Zones , zoneInfo . Name , _dnsWebService . _authManager . GetGroup ( Group . ADMINISTRATORS ) , PermissionFlag . ViewModifyDelete ) ;
_dnsWebService . _authManager . SetPermission ( PermissionSection . Zones , zoneInfo . Name , _dnsWebService . _authManager . GetGroup ( Group . DNS_ADMINISTRATORS ) , PermissionFlag . ViewModifyDelete ) ;
_dnsWebService . _authManager . SaveConfigFile ( ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _log . Write ( context . GetRemoteEndPoint ( _dnsWebService . _webServiceRealIpHeader ) , "[" + session . User . Username + "] " + sourceZoneInfo . TypeName + " zone '" + sourceZoneInfo . DisplayName + "' was cloned as '" + zoneInfo . DisplayName + "' sucessfully." ) ;
2023-10-29 20:18:58 +05:30
}
2023-09-24 16:42:39 +05:30
2025-02-15 12:51:16 +05:30
public void ConvertZone ( HttpContext context )
{
UserSession session = context . GetCurrentSession ( ) ;
2023-09-24 16:42:39 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , session . User , PermissionFlag . Delete ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2023-09-24 16:42:39 +05:30
2025-02-15 12:51:16 +05:30
HttpRequest request = context . Request ;
2023-09-24 16:42:39 +05:30
2025-02-15 12:51:16 +05:30
string zoneName = request . GetQueryOrForm ( "zone" ) . TrimEnd ( '.' ) ;
AuthZoneType type = request . GetQueryOrFormEnum < AuthZoneType > ( "type" ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . IsDomainNameUnicode ( zoneName ) )
zoneName = DnsClient . ConvertDomainNameToAscii ( zoneName ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
AuthZoneInfo zoneInfo = _dnsWebService . _dnsServer . AuthZoneManager . GetAuthZoneInfo ( zoneName ) ;
if ( zoneInfo is null )
throw new DnsWebServiceException ( "No such zone was found: " + zoneName ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
if ( zoneInfo . Internal )
throw new DnsWebServiceException ( "Access was denied to manage internal DNS Server zone." ) ;
2023-09-24 16:42:39 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , zoneInfo . Name , session . User , PermissionFlag . Delete ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2023-09-24 16:42:39 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _dnsServer . AuthZoneManager . ConvertZoneType ( zoneInfo . Name , type ) ;
2023-09-24 16:42:39 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _log . Write ( context . GetRemoteEndPoint ( _dnsWebService . _webServiceRealIpHeader ) , "[" + session . User . Username + "] " + zoneInfo . TypeName + " zone '" + zoneInfo . DisplayName + "' was converted to " + AuthZoneInfo . GetZoneTypeName ( type ) + " zone sucessfully." ) ;
}
2023-07-02 15:47:55 +05:30
2025-02-15 12:51:16 +05:30
public void SignPrimaryZone ( HttpContext context )
{
UserSession session = context . GetCurrentSession ( ) ;
2023-07-02 15:47:55 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , session . User , PermissionFlag . Modify ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2023-07-02 15:47:55 +05:30
2025-02-15 12:51:16 +05:30
HttpRequest request = context . Request ;
2023-07-02 15:47:55 +05:30
2025-02-15 12:51:16 +05:30
string zoneName = request . GetQueryOrForm ( "zone" ) . TrimEnd ( '.' ) ;
2023-07-02 15:47:55 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . IsDomainNameUnicode ( zoneName ) )
zoneName = DnsClient . ConvertDomainNameToAscii ( zoneName ) ;
2023-07-02 15:47:55 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , zoneName , session . User , PermissionFlag . Delete ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2023-07-02 15:47:55 +05:30
2025-02-15 12:51:16 +05:30
string algorithm = request . GetQueryOrForm ( "algorithm" ) ;
2025-03-29 18:58:25 +05:30
string pemKskPrivateKey = request . GetQueryOrForm ( "pemKskPrivateKey" , null ) ;
string pemZskPrivateKey = request . GetQueryOrForm ( "pemZskPrivateKey" , null ) ;
2025-03-31 19:36:23 +05:30
uint dnsKeyTtl = request . GetQueryOrForm ( "dnsKeyTtl" , ZoneFile . ParseTtl , 3600 u ) ;
2025-03-29 18:58:25 +05:30
ushort zskRolloverDays = request . GetQueryOrForm ( "zskRolloverDays" , ushort . Parse , Convert . ToUInt16 ( pemZskPrivateKey is null ? 30 : 0 ) ) ;
2023-07-02 15:47:55 +05:30
2025-02-15 12:51:16 +05:30
bool useNSEC3 = false ;
string strNxProof = request . QueryOrForm ( "nxProof" ) ;
if ( ! string . IsNullOrEmpty ( strNxProof ) )
{
switch ( strNxProof . ToUpper ( ) )
{
case "NSEC" :
useNSEC3 = false ;
break ;
2023-07-02 15:47:55 +05:30
2025-02-15 12:51:16 +05:30
case "NSEC3" :
useNSEC3 = true ;
break ;
2023-07-02 15:47:55 +05:30
2025-02-15 12:51:16 +05:30
default :
throw new NotSupportedException ( "Non-existence proof type is not supported: " + strNxProof ) ;
}
}
2023-01-01 18:39:46 +05:30
2025-02-15 12:51:16 +05:30
ushort iterations = 0 ;
byte saltLength = 0 ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( useNSEC3 )
{
iterations = request . GetQueryOrForm < ushort > ( "iterations" , ushort . Parse , 0 ) ;
saltLength = request . GetQueryOrForm < byte > ( "saltLength" , byte . Parse , 0 ) ;
}
2022-02-20 17:13:52 +05:30
2025-03-29 18:58:25 +05:30
DnssecPrivateKey kskPrivateKey ;
DnssecPrivateKey zskPrivateKey ;
2025-02-15 12:51:16 +05:30
switch ( algorithm . ToUpper ( ) )
{
case "RSA" :
2025-03-29 18:58:25 +05:30
{
string hashAlgorithm = request . GetQueryOrForm ( "hashAlgorithm" ) ;
2022-09-18 18:00:21 +05:30
2025-03-29 18:58:25 +05:30
DnssecAlgorithm dnssecAlgorithm ;
switch ( hashAlgorithm . ToUpper ( ) )
{
case "MD5" :
dnssecAlgorithm = DnssecAlgorithm . RSAMD5 ;
break ;
case "SHA1" :
dnssecAlgorithm = DnssecAlgorithm . RSASHA1 ;
break ;
case "SHA256" :
dnssecAlgorithm = DnssecAlgorithm . RSASHA256 ;
break ;
case "SHA512" :
dnssecAlgorithm = DnssecAlgorithm . RSASHA512 ;
break ;
default :
throw new NotSupportedException ( "Hash algorithm is not supported: " + hashAlgorithm ) ;
}
if ( pemKskPrivateKey is null )
kskPrivateKey = DnssecPrivateKey . Create ( dnssecAlgorithm , DnssecPrivateKeyType . KeySigningKey , request . GetQueryOrForm ( "kskKeySize" , int . Parse ) ) ;
else
kskPrivateKey = DnssecPrivateKey . Create ( dnssecAlgorithm , DnssecPrivateKeyType . KeySigningKey , pemKskPrivateKey ) ;
2023-04-23 16:34:17 +05:30
2025-03-29 18:58:25 +05:30
if ( pemZskPrivateKey is null )
zskPrivateKey = DnssecPrivateKey . Create ( dnssecAlgorithm , DnssecPrivateKeyType . ZoneSigningKey , request . GetQueryOrForm ( "zskKeySize" , int . Parse ) ) ;
else
zskPrivateKey = DnssecPrivateKey . Create ( dnssecAlgorithm , DnssecPrivateKeyType . ZoneSigningKey , pemZskPrivateKey ) ;
}
2025-02-15 12:51:16 +05:30
break ;
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
case "ECDSA" :
2025-03-29 18:58:25 +05:30
{
string curve = request . GetQueryOrForm ( "curve" ) ;
2021-09-18 19:02:40 +05:30
2025-03-29 18:58:25 +05:30
DnssecAlgorithm dnssecAlgorithm ;
switch ( curve . ToUpper ( ) )
{
case "P256" :
dnssecAlgorithm = DnssecAlgorithm . ECDSAP256SHA256 ;
break ;
case "P384" :
dnssecAlgorithm = DnssecAlgorithm . ECDSAP384SHA384 ;
break ;
2021-09-18 19:02:40 +05:30
2025-03-29 18:58:25 +05:30
default :
throw new NotSupportedException ( "ECDSA curve is not supported: " + curve ) ;
}
if ( pemKskPrivateKey is null )
kskPrivateKey = DnssecPrivateKey . Create ( dnssecAlgorithm , DnssecPrivateKeyType . KeySigningKey ) ;
else
kskPrivateKey = DnssecPrivateKey . Create ( dnssecAlgorithm , DnssecPrivateKeyType . KeySigningKey , pemKskPrivateKey ) ;
if ( pemZskPrivateKey is null )
zskPrivateKey = DnssecPrivateKey . Create ( dnssecAlgorithm , DnssecPrivateKeyType . ZoneSigningKey ) ;
else
zskPrivateKey = DnssecPrivateKey . Create ( dnssecAlgorithm , DnssecPrivateKeyType . ZoneSigningKey , pemZskPrivateKey ) ;
}
break ;
case "EDDSA" :
{
string curve = request . GetQueryOrForm ( "curve" ) ;
DnssecAlgorithm dnssecAlgorithm ;
switch ( curve . ToUpper ( ) )
{
case "ED25519" :
dnssecAlgorithm = DnssecAlgorithm . ED25519 ;
break ;
case "ED448" :
dnssecAlgorithm = DnssecAlgorithm . ED448 ;
break ;
default :
throw new NotSupportedException ( "EdDSA curve is not supported: " + curve ) ;
}
if ( pemKskPrivateKey is null )
kskPrivateKey = DnssecPrivateKey . Create ( dnssecAlgorithm , DnssecPrivateKeyType . KeySigningKey ) ;
else
kskPrivateKey = DnssecPrivateKey . Create ( dnssecAlgorithm , DnssecPrivateKeyType . KeySigningKey , pemKskPrivateKey ) ;
if ( pemZskPrivateKey is null )
zskPrivateKey = DnssecPrivateKey . Create ( dnssecAlgorithm , DnssecPrivateKeyType . ZoneSigningKey ) ;
else
zskPrivateKey = DnssecPrivateKey . Create ( dnssecAlgorithm , DnssecPrivateKeyType . ZoneSigningKey , pemZskPrivateKey ) ;
}
2022-04-30 16:19:02 +05:30
break ;
2021-09-18 19:02:40 +05:30
2022-04-30 16:19:02 +05:30
default :
2025-02-15 12:51:16 +05:30
throw new NotSupportedException ( "Algorithm is not supported: " + algorithm ) ;
2022-04-30 16:19:02 +05:30
}
2021-09-18 19:02:40 +05:30
2025-03-29 18:58:25 +05:30
zskPrivateKey . RolloverDays = zskRolloverDays ;
_dnsWebService . _dnsServer . AuthZoneManager . SignPrimaryZone ( zoneName , kskPrivateKey , zskPrivateKey , dnsKeyTtl , useNSEC3 , iterations , saltLength ) ;
2025-02-15 12:51:16 +05:30
_dnsWebService . _log . Write ( context . GetRemoteEndPoint ( _dnsWebService . _webServiceRealIpHeader ) , "[" + session . User . Username + "] Primary zone was signed successfully: " + zoneName ) ;
2022-04-30 16:19:02 +05:30
}
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
public void UnsignPrimaryZone ( HttpContext context )
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
UserSession session = context . GetCurrentSession ( ) ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , session . User , PermissionFlag . Modify ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
string zoneName = context . Request . GetQueryOrForm ( "zone" ) . TrimEnd ( '.' ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . IsDomainNameUnicode ( zoneName ) )
zoneName = DnsClient . ConvertDomainNameToAscii ( zoneName ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , zoneName , session . User , PermissionFlag . Delete ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _dnsServer . AuthZoneManager . UnsignPrimaryZone ( zoneName ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _log . Write ( context . GetRemoteEndPoint ( _dnsWebService . _webServiceRealIpHeader ) , "[" + session . User . Username + "] Primary zone was unsigned successfully: " + zoneName ) ;
2021-09-18 19:02:40 +05:30
}
2025-02-15 12:51:16 +05:30
public void GetPrimaryZoneDsInfo ( HttpContext context )
{
UserSession session = context . GetCurrentSession ( ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , session . User , PermissionFlag . View ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
string zoneName = context . Request . GetQueryOrForm ( "zone" ) . TrimEnd ( '.' ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . IsDomainNameUnicode ( zoneName ) )
zoneName = DnsClient . ConvertDomainNameToAscii ( zoneName ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
AuthZoneInfo zoneInfo = _dnsWebService . _dnsServer . AuthZoneManager . GetAuthZoneInfo ( zoneName ) ;
if ( zoneInfo is null )
throw new DnsWebServiceException ( "No such zone was found: " + zoneName ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
if ( zoneInfo . Internal )
throw new DnsWebServiceException ( "Access was denied to manage internal DNS Server zone." ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
if ( zoneInfo . Type ! = AuthZoneType . Primary )
throw new DnsWebServiceException ( "The zone must be a primary zone." ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , zoneInfo . Name , session . User , PermissionFlag . View ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
if ( zoneInfo . ApexZone . DnssecStatus = = AuthZoneDnssecStatus . Unsigned )
throw new DnsWebServiceException ( "The zone must be signed with DNSSEC." ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
IReadOnlyList < DnsResourceRecord > dnsKeyRecords = zoneInfo . ApexZone . GetRecords ( DnsResourceRecordType . DNSKEY ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
Utf8JsonWriter jsonWriter = context . GetCurrentJsonWriter ( ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteString ( "name" , zoneInfo . Name ) ;
jsonWriter . WriteString ( "type" , zoneInfo . Type . ToString ( ) ) ;
jsonWriter . WriteBoolean ( "internal" , zoneInfo . Internal ) ;
jsonWriter . WriteBoolean ( "disabled" , zoneInfo . Disabled ) ;
jsonWriter . WriteString ( "dnssecStatus" , zoneInfo . ApexZone . DnssecStatus . ToString ( ) ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WritePropertyName ( "dsRecords" ) ;
jsonWriter . WriteStartArray ( ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
foreach ( DnsResourceRecord record in dnsKeyRecords )
2023-10-29 20:18:58 +05:30
{
2025-02-15 12:51:16 +05:30
if ( record . RDATA is DnsDNSKEYRecordData rdata & & rdata . Flags . HasFlag ( DnsDnsKeyFlag . SecureEntryPoint ) )
{
jsonWriter . WriteStartObject ( ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteNumber ( "keyTag" , rdata . ComputedKeyTag ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
IReadOnlyCollection < DnssecPrivateKey > dnssecPrivateKeys = zoneInfo . DnssecPrivateKeys ;
if ( dnssecPrivateKeys is not null )
2023-10-29 20:18:58 +05:30
{
2025-02-15 12:51:16 +05:30
foreach ( DnssecPrivateKey dnssecPrivateKey in dnssecPrivateKeys )
2023-10-29 20:18:58 +05:30
{
2025-02-15 12:51:16 +05:30
if ( ( dnssecPrivateKey . KeyType = = DnssecPrivateKeyType . KeySigningKey ) & & ( dnssecPrivateKey . KeyTag = = rdata . ComputedKeyTag ) )
{
jsonWriter . WriteString ( "dnsKeyState" , dnssecPrivateKey . State . ToString ( ) ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
if ( dnssecPrivateKey . State = = DnssecPrivateKeyState . Published )
2025-03-29 18:58:25 +05:30
jsonWriter . WriteString ( "dnsKeyStateReadyBy" , dnssecPrivateKey . StateTransitionByWithDelays ) ;
2023-10-29 20:18:58 +05:30
2025-03-29 18:58:25 +05:30
jsonWriter . WriteBoolean ( "isRetiring" , dnssecPrivateKey . IsRetiring ) ;
2025-02-15 12:51:16 +05:30
break ;
}
2023-10-29 20:18:58 +05:30
}
}
2025-02-15 12:51:16 +05:30
jsonWriter . WriteString ( "algorithm" , rdata . Algorithm . ToString ( ) ) ;
2025-03-29 18:58:25 +05:30
jsonWriter . WriteNumber ( "algorithmNumber" , ( byte ) rdata . Algorithm ) ;
2025-02-15 12:51:16 +05:30
jsonWriter . WriteString ( "publicKey" , rdata . PublicKey . ToString ( ) ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WritePropertyName ( "digests" ) ;
jsonWriter . WriteStartArray ( ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
{
jsonWriter . WriteStartObject ( ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteString ( "digestType" , "SHA256" ) ;
2025-03-29 18:58:25 +05:30
jsonWriter . WriteString ( "digestTypeNumber" , "2" ) ;
2025-02-15 12:51:16 +05:30
jsonWriter . WriteString ( "digest" , Convert . ToHexString ( rdata . CreateDS ( record . Name , DnssecDigestType . SHA256 ) . Digest ) ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndObject ( ) ;
}
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
{
jsonWriter . WriteStartObject ( ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteString ( "digestType" , "SHA384" ) ;
2025-03-29 18:58:25 +05:30
jsonWriter . WriteString ( "digestTypeNumber" , "4" ) ;
2025-02-15 12:51:16 +05:30
jsonWriter . WriteString ( "digest" , Convert . ToHexString ( rdata . CreateDS ( record . Name , DnssecDigestType . SHA384 ) . Digest ) ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndObject ( ) ;
}
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndArray ( ) ;
2023-10-29 20:18:58 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndObject ( ) ;
}
2023-10-29 20:18:58 +05:30
}
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndArray ( ) ;
}
2023-01-01 18:39:46 +05:30
2025-02-15 12:51:16 +05:30
public void GetPrimaryZoneDnssecProperties ( HttpContext context )
{
UserSession session = context . GetCurrentSession ( ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , session . User , PermissionFlag . Modify ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
string zoneName = context . Request . GetQueryOrForm ( "zone" ) . TrimEnd ( '.' ) ;
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . IsDomainNameUnicode ( zoneName ) )
zoneName = DnsClient . ConvertDomainNameToAscii ( zoneName ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
AuthZoneInfo zoneInfo = _dnsWebService . _dnsServer . AuthZoneManager . GetAuthZoneInfo ( zoneName ) ;
if ( zoneInfo is null )
throw new DnsWebServiceException ( "No such zone was found: " + zoneName ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( zoneInfo . Internal )
throw new DnsWebServiceException ( "Access was denied to manage internal DNS Server zone." ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( zoneInfo . Type ! = AuthZoneType . Primary )
throw new DnsWebServiceException ( "The zone must be a primary zone." ) ;
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , zoneInfo . Name , session . User , PermissionFlag . View ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2023-01-01 18:39:46 +05:30
2025-02-15 12:51:16 +05:30
Utf8JsonWriter jsonWriter = context . GetCurrentJsonWriter ( ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteString ( "name" , zoneInfo . Name ) ;
jsonWriter . WriteString ( "type" , zoneInfo . Type . ToString ( ) ) ;
jsonWriter . WriteBoolean ( "internal" , zoneInfo . Internal ) ;
jsonWriter . WriteBoolean ( "disabled" , zoneInfo . Disabled ) ;
jsonWriter . WriteString ( "dnssecStatus" , zoneInfo . ApexZone . DnssecStatus . ToString ( ) ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( zoneInfo . ApexZone . DnssecStatus = = AuthZoneDnssecStatus . SignedWithNSEC3 )
{
IReadOnlyList < DnsResourceRecord > nsec3ParamRecords = zoneInfo . ApexZone . GetRecords ( DnsResourceRecordType . NSEC3PARAM ) ;
DnsNSEC3PARAMRecordData nsec3Param = nsec3ParamRecords [ 0 ] . RDATA as DnsNSEC3PARAMRecordData ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteNumber ( "nsec3Iterations" , nsec3Param . Iterations ) ;
jsonWriter . WriteNumber ( "nsec3SaltLength" , nsec3Param . Salt . Length ) ;
}
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteNumber ( "dnsKeyTtl" , zoneInfo . DnsKeyTtl ) ;
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WritePropertyName ( "dnssecPrivateKeys" ) ;
jsonWriter . WriteStartArray ( ) ;
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
IReadOnlyCollection < DnssecPrivateKey > dnssecPrivateKeys = zoneInfo . DnssecPrivateKeys ;
if ( dnssecPrivateKeys is not null )
2021-09-18 19:02:40 +05:30
{
2025-02-15 12:51:16 +05:30
List < DnssecPrivateKey > sortedDnssecPrivateKey = new List < DnssecPrivateKey > ( dnssecPrivateKeys ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
sortedDnssecPrivateKey . Sort ( delegate ( DnssecPrivateKey key1 , DnssecPrivateKey key2 )
{
int value = key1 . KeyType . CompareTo ( key2 . KeyType ) ;
if ( value = = 0 )
value = key1 . StateChangedOn . CompareTo ( key2 . StateChangedOn ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
return value ;
} ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
foreach ( DnssecPrivateKey dnssecPrivateKey in sortedDnssecPrivateKey )
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
jsonWriter . WriteStartObject ( ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteNumber ( "keyTag" , dnssecPrivateKey . KeyTag ) ;
jsonWriter . WriteString ( "keyType" , dnssecPrivateKey . KeyType . ToString ( ) ) ;
switch ( dnssecPrivateKey . Algorithm )
{
case DnssecAlgorithm . RSAMD5 :
case DnssecAlgorithm . RSASHA1 :
case DnssecAlgorithm . RSASHA1_NSEC3_SHA1 :
case DnssecAlgorithm . RSASHA256 :
case DnssecAlgorithm . RSASHA512 :
jsonWriter . WriteString ( "algorithm" , dnssecPrivateKey . Algorithm . ToString ( ) + " (" + ( dnssecPrivateKey as DnssecRsaPrivateKey ) . KeySize + " bits)" ) ;
break ;
default :
jsonWriter . WriteString ( "algorithm" , dnssecPrivateKey . Algorithm . ToString ( ) ) ;
break ;
}
2021-09-18 19:02:40 +05:30
2025-03-29 18:58:25 +05:30
jsonWriter . WriteNumber ( "algorithmNumber" , ( byte ) dnssecPrivateKey . Algorithm ) ;
2025-02-15 12:51:16 +05:30
jsonWriter . WriteString ( "state" , dnssecPrivateKey . State . ToString ( ) ) ;
jsonWriter . WriteString ( "stateChangedOn" , dnssecPrivateKey . StateChangedOn ) ;
2021-09-18 19:02:40 +05:30
2025-03-29 18:58:25 +05:30
if ( dnssecPrivateKey . State = = DnssecPrivateKeyState . Published )
{
switch ( dnssecPrivateKey . KeyType )
{
case DnssecPrivateKeyType . KeySigningKey :
jsonWriter . WriteString ( "stateReadyBy" , dnssecPrivateKey . StateTransitionByWithDelays ) ;
break ;
case DnssecPrivateKeyType . ZoneSigningKey :
jsonWriter . WriteString ( "stateActiveBy" , dnssecPrivateKey . StateTransitionByWithDelays ) ;
break ;
}
}
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteBoolean ( "isRetiring" , dnssecPrivateKey . IsRetiring ) ;
jsonWriter . WriteNumber ( "rolloverDays" , dnssecPrivateKey . RolloverDays ) ;
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndObject ( ) ;
}
2022-04-30 16:19:02 +05:30
}
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndArray ( ) ;
2021-09-18 19:02:40 +05:30
}
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
public void ConvertPrimaryZoneToNSEC ( HttpContext context )
{
UserSession session = context . GetCurrentSession ( ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , session . User , PermissionFlag . Modify ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2022-03-12 15:53:15 +05:30
2025-02-15 12:51:16 +05:30
string zoneName = context . Request . GetQueryOrForm ( "zone" ) . TrimEnd ( '.' ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . IsDomainNameUnicode ( zoneName ) )
zoneName = DnsClient . ConvertDomainNameToAscii ( zoneName ) ;
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , zoneName , session . User , PermissionFlag . Delete ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _dnsServer . AuthZoneManager . ConvertPrimaryZoneToNSEC ( zoneName ) ;
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _log . Write ( context . GetRemoteEndPoint ( _dnsWebService . _webServiceRealIpHeader ) , "[" + session . User . Username + "] Primary zone was converted to NSEC successfully: " + zoneName ) ;
}
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
public void ConvertPrimaryZoneToNSEC3 ( HttpContext context )
{
UserSession session = context . GetCurrentSession ( ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , session . User , PermissionFlag . Modify ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
HttpRequest request = context . Request ;
2023-01-01 18:39:46 +05:30
2025-02-15 12:51:16 +05:30
string zoneName = request . GetQueryOrForm ( "zone" ) . TrimEnd ( '.' ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . IsDomainNameUnicode ( zoneName ) )
zoneName = DnsClient . ConvertDomainNameToAscii ( zoneName ) ;
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , zoneName , session . User , PermissionFlag . Delete ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
ushort iterations = request . GetQueryOrForm < ushort > ( "iterations" , ushort . Parse , 0 ) ;
byte saltLength = request . GetQueryOrForm < byte > ( "saltLength" , byte . Parse , 0 ) ;
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _dnsServer . AuthZoneManager . ConvertPrimaryZoneToNSEC3 ( zoneName , iterations , saltLength ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _log . Write ( context . GetRemoteEndPoint ( _dnsWebService . _webServiceRealIpHeader ) , "[" + session . User . Username + "] Primary zone was converted to NSEC3 successfully: " + zoneName ) ;
}
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
public void UpdatePrimaryZoneNSEC3Parameters ( HttpContext context )
{
UserSession session = context . GetCurrentSession ( ) ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , session . User , PermissionFlag . Modify ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
HttpRequest request = context . Request ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
string zoneName = request . GetQueryOrForm ( "zone" ) . TrimEnd ( '.' ) ;
2023-01-01 18:39:46 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . IsDomainNameUnicode ( zoneName ) )
zoneName = DnsClient . ConvertDomainNameToAscii ( zoneName ) ;
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , zoneName , session . User , PermissionFlag . Delete ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
ushort iterations = request . GetQueryOrForm < ushort > ( "iterations" , ushort . Parse , 0 ) ;
byte saltLength = request . GetQueryOrForm < byte > ( "saltLength" , byte . Parse , 0 ) ;
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _dnsServer . AuthZoneManager . UpdatePrimaryZoneNSEC3Parameters ( zoneName , iterations , saltLength ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _log . Write ( context . GetRemoteEndPoint ( _dnsWebService . _webServiceRealIpHeader ) , "[" + session . User . Username + "] Primary zone NSEC3 parameters were updated successfully: " + zoneName ) ;
}
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
public void UpdatePrimaryZoneDnssecDnsKeyTtl ( HttpContext context )
{
UserSession session = context . GetCurrentSession ( ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , session . User , PermissionFlag . Modify ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2023-01-01 18:39:46 +05:30
2025-02-15 12:51:16 +05:30
HttpRequest request = context . Request ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
string zoneName = request . GetQueryOrForm ( "zone" ) . TrimEnd ( '.' ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . IsDomainNameUnicode ( zoneName ) )
zoneName = DnsClient . ConvertDomainNameToAscii ( zoneName ) ;
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , zoneName , session . User , PermissionFlag . Delete ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2023-04-23 16:34:17 +05:30
2025-03-31 19:36:23 +05:30
uint dnsKeyTtl = request . GetQueryOrForm ( "ttl" , ZoneFile . ParseTtl ) ;
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _dnsServer . AuthZoneManager . UpdatePrimaryZoneDnsKeyTtl ( zoneName , dnsKeyTtl ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _log . Write ( context . GetRemoteEndPoint ( _dnsWebService . _webServiceRealIpHeader ) , "[" + session . User . Username + "] Primary zone DNSKEY TTL was updated successfully: " + zoneName ) ;
}
2021-09-18 19:02:40 +05:30
2025-03-29 18:58:25 +05:30
public void AddPrimaryZoneDnssecPrivateKey ( HttpContext context )
2025-02-15 12:51:16 +05:30
{
UserSession session = context . GetCurrentSession ( ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , session . User , PermissionFlag . Modify ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
HttpRequest request = context . Request ;
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
string zoneName = request . GetQueryOrForm ( "zone" ) . TrimEnd ( '.' ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . IsDomainNameUnicode ( zoneName ) )
zoneName = DnsClient . ConvertDomainNameToAscii ( zoneName ) ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , zoneName , session . User , PermissionFlag . Delete ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
DnssecPrivateKeyType keyType = request . GetQueryOrFormEnum < DnssecPrivateKeyType > ( "keyType" ) ;
ushort rolloverDays = request . GetQueryOrForm ( "rolloverDays" , ushort . Parse , ( ushort ) ( keyType = = DnssecPrivateKeyType . ZoneSigningKey ? 30 : 0 ) ) ;
string algorithm = request . GetQueryOrForm ( "algorithm" ) ;
2025-03-29 18:58:25 +05:30
string pemPrivateKey = request . GetQueryOrForm ( "pemPrivateKey" , null ) ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
switch ( algorithm . ToUpper ( ) )
{
case "RSA" :
2025-03-29 18:58:25 +05:30
{
string hashAlgorithm = request . GetQueryOrForm ( "hashAlgorithm" ) ;
DnssecAlgorithm dnssecAlgorithm ;
switch ( hashAlgorithm . ToUpper ( ) )
{
case "MD5" :
dnssecAlgorithm = DnssecAlgorithm . RSAMD5 ;
break ;
2021-09-18 19:02:40 +05:30
2025-03-29 18:58:25 +05:30
case "SHA1" :
dnssecAlgorithm = DnssecAlgorithm . RSASHA1 ;
break ;
case "SHA256" :
dnssecAlgorithm = DnssecAlgorithm . RSASHA256 ;
break ;
case "SHA512" :
dnssecAlgorithm = DnssecAlgorithm . RSASHA512 ;
break ;
default :
throw new NotSupportedException ( "Hash algorithm is not supported: " + hashAlgorithm ) ;
}
if ( pemPrivateKey is null )
{
int keySize = request . GetQueryOrForm ( "keySize" , int . Parse ) ;
_dnsWebService . _dnsServer . AuthZoneManager . GenerateAndAddPrimaryZoneDnssecPrivateKey ( zoneName , keyType , dnssecAlgorithm , rolloverDays , keySize ) ;
}
else
{
DnssecPrivateKey privateKey = DnssecPrivateKey . Create ( dnssecAlgorithm , keyType , pemPrivateKey ) ;
privateKey . RolloverDays = rolloverDays ;
_dnsWebService . _dnsServer . AuthZoneManager . AddPrimaryZoneDnssecPrivateKey ( zoneName , privateKey ) ;
}
}
2025-02-15 12:51:16 +05:30
break ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
case "ECDSA" :
2025-03-29 18:58:25 +05:30
{
string curve = request . GetQueryOrForm ( "curve" ) ;
DnssecAlgorithm dnssecAlgorithm ;
switch ( curve . ToUpper ( ) )
{
case "P256" :
dnssecAlgorithm = DnssecAlgorithm . ECDSAP256SHA256 ;
break ;
case "P384" :
dnssecAlgorithm = DnssecAlgorithm . ECDSAP384SHA384 ;
break ;
2022-03-06 16:56:54 +05:30
2025-03-29 18:58:25 +05:30
default :
throw new NotSupportedException ( "ECDSA curve is not supported: " + curve ) ;
}
if ( pemPrivateKey is null )
{
_dnsWebService . _dnsServer . AuthZoneManager . GenerateAndAddPrimaryZoneDnssecPrivateKey ( zoneName , keyType , dnssecAlgorithm , rolloverDays ) ;
}
else
{
DnssecPrivateKey privateKey = DnssecPrivateKey . Create ( dnssecAlgorithm , keyType , pemPrivateKey ) ;
privateKey . RolloverDays = rolloverDays ;
_dnsWebService . _dnsServer . AuthZoneManager . AddPrimaryZoneDnssecPrivateKey ( zoneName , privateKey ) ;
}
}
break ;
case "EDDSA" :
{
string curve = request . GetQueryOrForm ( "curve" ) ;
DnssecAlgorithm dnssecAlgorithm ;
switch ( curve . ToUpper ( ) )
{
case "ED25519" :
dnssecAlgorithm = DnssecAlgorithm . ED25519 ;
break ;
case "ED448" :
dnssecAlgorithm = DnssecAlgorithm . ED448 ;
break ;
default :
throw new NotSupportedException ( "EdDSA curve is not supported: " + curve ) ;
}
if ( pemPrivateKey is null )
{
_dnsWebService . _dnsServer . AuthZoneManager . GenerateAndAddPrimaryZoneDnssecPrivateKey ( zoneName , keyType , dnssecAlgorithm , rolloverDays ) ;
}
else
{
DnssecPrivateKey privateKey = DnssecPrivateKey . Create ( dnssecAlgorithm , keyType , pemPrivateKey ) ;
privateKey . RolloverDays = rolloverDays ;
_dnsWebService . _dnsServer . AuthZoneManager . AddPrimaryZoneDnssecPrivateKey ( zoneName , privateKey ) ;
}
}
2025-02-15 12:51:16 +05:30
break ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
default :
throw new NotSupportedException ( "Algorithm is not supported: " + algorithm ) ;
}
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _log . Write ( context . GetRemoteEndPoint ( _dnsWebService . _webServiceRealIpHeader ) , "[" + session . User . Username + "] DNSSEC private key was generated and added to the primary zone successfully: " + zoneName ) ;
2022-04-30 16:19:02 +05:30
}
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
public void UpdatePrimaryZoneDnssecPrivateKey ( HttpContext context )
{
UserSession session = context . GetCurrentSession ( ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , session . User , PermissionFlag . Modify ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
HttpRequest request = context . Request ;
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
string zoneName = request . GetQueryOrForm ( "zone" ) . TrimEnd ( '.' ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . IsDomainNameUnicode ( zoneName ) )
zoneName = DnsClient . ConvertDomainNameToAscii ( zoneName ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , zoneName , session . User , PermissionFlag . Delete ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
ushort keyTag = request . GetQueryOrForm ( "keyTag" , ushort . Parse ) ;
ushort rolloverDays = request . GetQueryOrForm ( "rolloverDays" , ushort . Parse ) ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _dnsServer . AuthZoneManager . UpdatePrimaryZoneDnssecPrivateKey ( zoneName , keyTag , rolloverDays ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _log . Write ( context . GetRemoteEndPoint ( _dnsWebService . _webServiceRealIpHeader ) , "[" + session . User . Username + "] Primary zone DNSSEC private key config was updated successfully: " + zoneName ) ;
}
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
public void DeletePrimaryZoneDnssecPrivateKey ( HttpContext context )
{
UserSession session = context . GetCurrentSession ( ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , session . User , PermissionFlag . Modify ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2023-01-01 18:39:46 +05:30
2025-02-15 12:51:16 +05:30
HttpRequest request = context . Request ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
string zoneName = request . GetQueryOrForm ( "zone" ) . TrimEnd ( '.' ) ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . IsDomainNameUnicode ( zoneName ) )
zoneName = DnsClient . ConvertDomainNameToAscii ( zoneName ) ;
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , zoneName , session . User , PermissionFlag . Delete ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
ushort keyTag = request . GetQueryOrForm ( "keyTag" , ushort . Parse ) ;
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _dnsServer . AuthZoneManager . DeletePrimaryZoneDnssecPrivateKey ( zoneName , keyTag ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _log . Write ( context . GetRemoteEndPoint ( _dnsWebService . _webServiceRealIpHeader ) , "[" + session . User . Username + "] DNSSEC private key was deleted from primary zone successfully: " + zoneName ) ;
}
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
public void PublishAllGeneratedPrimaryZoneDnssecPrivateKeys ( HttpContext context )
{
UserSession session = context . GetCurrentSession ( ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , session . User , PermissionFlag . Modify ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
string zoneName = context . Request . GetQueryOrForm ( "zone" ) . TrimEnd ( '.' ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . IsDomainNameUnicode ( zoneName ) )
zoneName = DnsClient . ConvertDomainNameToAscii ( zoneName ) ;
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , zoneName , session . User , PermissionFlag . Delete ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _dnsServer . AuthZoneManager . PublishAllGeneratedPrimaryZoneDnssecPrivateKeys ( zoneName ) ;
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _log . Write ( context . GetRemoteEndPoint ( _dnsWebService . _webServiceRealIpHeader ) , "[" + session . User . Username + "] All DNSSEC private keys from the primary zone were published successfully: " + zoneName ) ;
}
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
public void RolloverPrimaryZoneDnsKey ( HttpContext context )
{
UserSession session = context . GetCurrentSession ( ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , session . User , PermissionFlag . Modify ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
HttpRequest request = context . Request ;
2023-01-01 18:39:46 +05:30
2025-02-15 12:51:16 +05:30
string zoneName = request . GetQueryOrForm ( "zone" ) . TrimEnd ( '.' ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . IsDomainNameUnicode ( zoneName ) )
zoneName = DnsClient . ConvertDomainNameToAscii ( zoneName ) ;
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , zoneName , session . User , PermissionFlag . Delete ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
ushort keyTag = request . GetQueryOrForm ( "keyTag" , ushort . Parse ) ;
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _dnsServer . AuthZoneManager . RolloverPrimaryZoneDnsKey ( zoneName , keyTag ) ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _log . Write ( context . GetRemoteEndPoint ( _dnsWebService . _webServiceRealIpHeader ) , "[" + session . User . Username + "] The DNSKEY (" + keyTag + ") from the primary zone was rolled over successfully: " + zoneName ) ;
}
2022-03-06 16:56:54 +05:30
2025-03-29 18:58:25 +05:30
public async Task RetirePrimaryZoneDnsKeyAsync ( HttpContext context )
2025-02-15 12:51:16 +05:30
{
UserSession session = context . GetCurrentSession ( ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , session . User , PermissionFlag . Modify ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
HttpRequest request = context . Request ;
2023-01-01 18:39:46 +05:30
2025-02-15 12:51:16 +05:30
string zoneName = request . GetQueryOrForm ( "zone" ) . TrimEnd ( '.' ) ;
2022-02-27 18:23:41 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . IsDomainNameUnicode ( zoneName ) )
zoneName = DnsClient . ConvertDomainNameToAscii ( zoneName ) ;
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , zoneName , session . User , PermissionFlag . Delete ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
ushort keyTag = request . GetQueryOrForm ( "keyTag" , ushort . Parse ) ;
2022-09-18 18:00:21 +05:30
2025-03-29 18:58:25 +05:30
await _dnsWebService . _dnsServer . AuthZoneManager . RetirePrimaryZoneDnsKeyAsync ( zoneName , keyTag ) ;
2022-02-27 18:23:41 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _log . Write ( context . GetRemoteEndPoint ( _dnsWebService . _webServiceRealIpHeader ) , "[" + session . User . Username + "] The DNSKEY (" + keyTag + ") from the primary zone was retired successfully: " + zoneName ) ;
}
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
public void DeleteZone ( HttpContext context )
{
UserSession session = context . GetCurrentSession ( ) ;
2022-02-27 18:23:41 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , session . User , PermissionFlag . Delete ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2022-02-27 18:23:41 +05:30
2025-02-15 12:51:16 +05:30
string zoneName = context . Request . GetQueryOrFormAlt ( "zone" , "domain" ) . TrimEnd ( '.' ) ;
2022-02-27 18:23:41 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . IsDomainNameUnicode ( zoneName ) )
zoneName = DnsClient . ConvertDomainNameToAscii ( zoneName ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
AuthZoneInfo zoneInfo = _dnsWebService . _dnsServer . AuthZoneManager . GetAuthZoneInfo ( zoneName ) ;
if ( zoneInfo is null )
throw new DnsWebServiceException ( "No such zone was found: " + zoneName ) ;
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
if ( zoneInfo . Internal )
throw new DnsWebServiceException ( "Access was denied to manage internal DNS Server zone." ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , zoneInfo . Name , session . User , PermissionFlag . Delete ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _dnsServer . AuthZoneManager . DeleteZone ( zoneInfo , true ) )
throw new DnsWebServiceException ( "Failed to delete the zone: " + zoneInfo . DisplayName ) ;
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _authManager . RemoveAllPermissions ( PermissionSection . Zones , zoneInfo . Name ) ;
_dnsWebService . _authManager . SaveConfigFile ( ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _log . Write ( context . GetRemoteEndPoint ( _dnsWebService . _webServiceRealIpHeader ) , "[" + session . User . Username + "] " + zoneInfo . TypeName + " zone was deleted: " + zoneInfo . DisplayName ) ;
}
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
public void EnableZone ( HttpContext context )
{
UserSession session = context . GetCurrentSession ( ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , session . User , PermissionFlag . Modify ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
string zoneName = context . Request . GetQueryOrFormAlt ( "zone" , "domain" ) . TrimEnd ( '.' ) ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . IsDomainNameUnicode ( zoneName ) )
zoneName = DnsClient . ConvertDomainNameToAscii ( zoneName ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
AuthZoneInfo zoneInfo = _dnsWebService . _dnsServer . AuthZoneManager . GetAuthZoneInfo ( zoneName ) ;
if ( zoneInfo is null )
throw new DnsWebServiceException ( "No such zone was found: " + zoneName ) ;
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
if ( zoneInfo . Internal )
throw new DnsWebServiceException ( "Access was denied to manage internal DNS Server zone." ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , zoneInfo . Name , session . User , PermissionFlag . Modify ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
zoneInfo . Disabled = false ;
_dnsWebService . _dnsServer . AuthZoneManager . SaveZoneFile ( zoneInfo . Name ) ;
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _log . Write ( context . GetRemoteEndPoint ( _dnsWebService . _webServiceRealIpHeader ) , "[" + session . User . Username + "] " + zoneInfo . TypeName + " zone was enabled: " + zoneInfo . DisplayName ) ;
2022-01-23 18:22:17 +05:30
2025-02-15 12:51:16 +05:30
//delete cache for this zone to allow rebuilding cache data as needed by stub or forwarder zones
_dnsWebService . _dnsServer . CacheZoneManager . DeleteZone ( zoneInfo . Name ) ;
}
2022-01-23 18:22:17 +05:30
2025-02-15 12:51:16 +05:30
public void DisableZone ( HttpContext context )
{
UserSession session = context . GetCurrentSession ( ) ;
2022-03-12 15:53:15 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , session . User , PermissionFlag . Modify ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2022-01-23 18:22:17 +05:30
2025-02-15 12:51:16 +05:30
string zoneName = context . Request . GetQueryOrFormAlt ( "zone" , "domain" ) . TrimEnd ( '.' ) ;
2022-01-23 18:22:17 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . IsDomainNameUnicode ( zoneName ) )
zoneName = DnsClient . ConvertDomainNameToAscii ( zoneName ) ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
AuthZoneInfo zoneInfo = _dnsWebService . _dnsServer . AuthZoneManager . GetAuthZoneInfo ( zoneName ) ;
if ( zoneInfo is null )
throw new DnsWebServiceException ( "No such zone was found: " + zoneName ) ;
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
if ( zoneInfo . Internal )
throw new DnsWebServiceException ( "Access was denied to manage internal DNS Server zone." ) ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , zoneInfo . Name , session . User , PermissionFlag . Modify ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2022-01-23 18:22:17 +05:30
2025-02-15 12:51:16 +05:30
zoneInfo . Disabled = true ;
_dnsWebService . _dnsServer . AuthZoneManager . SaveZoneFile ( zoneInfo . Name ) ;
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _log . Write ( context . GetRemoteEndPoint ( _dnsWebService . _webServiceRealIpHeader ) , "[" + session . User . Username + "] " + zoneInfo . TypeName + " zone was disabled: " + zoneInfo . DisplayName ) ;
}
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
public void GetZoneOptions ( HttpContext context )
{
UserSession session = context . GetCurrentSession ( ) ;
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , session . User , PermissionFlag . Modify ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
HttpRequest request = context . Request ;
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
string zoneName = request . GetQueryOrFormAlt ( "zone" , "domain" ) . TrimEnd ( '.' ) ;
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . IsDomainNameUnicode ( zoneName ) )
zoneName = DnsClient . ConvertDomainNameToAscii ( zoneName ) ;
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
bool includeAvailableCatalogZoneNames = request . GetQueryOrForm ( "includeAvailableCatalogZoneNames" , bool . Parse , false ) ;
bool includeAvailableTsigKeyNames = request . GetQueryOrForm ( "includeAvailableTsigKeyNames" , bool . Parse , false ) ;
2022-10-05 19:22:44 +05:30
2025-02-15 12:51:16 +05:30
AuthZoneInfo zoneInfo = _dnsWebService . _dnsServer . AuthZoneManager . GetAuthZoneInfo ( zoneName ) ;
if ( zoneInfo is null )
throw new DnsWebServiceException ( "No such zone was found: " + zoneName ) ;
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
if ( zoneInfo . Internal )
throw new DnsWebServiceException ( "Access was denied to manage internal DNS Server zone." ) ;
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , zoneInfo . Name , session . User , PermissionFlag . View ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
Utf8JsonWriter jsonWriter = context . GetCurrentJsonWriter ( ) ;
2023-01-01 18:39:46 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteString ( "name" , zoneInfo . Name ) ;
2023-07-02 15:47:55 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . TryConvertDomainNameToUnicode ( zoneInfo . Name , out string nameIdn ) )
jsonWriter . WriteString ( "nameIdn" , nameIdn ) ;
2023-07-02 15:47:55 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteString ( "type" , zoneInfo . Type . ToString ( ) ) ;
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
if ( zoneInfo . Type = = AuthZoneType . Primary )
jsonWriter . WriteBoolean ( "internal" , zoneInfo . Internal ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
switch ( zoneInfo . Type )
{
case AuthZoneType . Primary :
case AuthZoneType . Secondary :
jsonWriter . WriteString ( "dnssecStatus" , zoneInfo . ApexZone . DnssecStatus . ToString ( ) ) ;
break ;
}
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
switch ( zoneInfo . Type )
{
case AuthZoneType . Primary :
case AuthZoneType . Secondary :
case AuthZoneType . Forwarder :
case AuthZoneType . Catalog :
if ( ! zoneInfo . Internal )
{
string [ ] notifyFailed = zoneInfo . NotifyFailed ;
2023-07-02 15:47:55 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteBoolean ( "notifyFailed" , notifyFailed . Length > 0 ) ;
2023-07-02 15:47:55 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WritePropertyName ( "notifyFailedFor" ) ;
jsonWriter . WriteStartArray ( ) ;
2023-07-02 15:47:55 +05:30
2025-02-15 12:51:16 +05:30
foreach ( string server in notifyFailed )
jsonWriter . WriteStringValue ( server ) ;
2023-07-02 15:47:55 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndArray ( ) ;
}
break ;
}
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteBoolean ( "disabled" , zoneInfo . Disabled ) ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
//catalog zone
switch ( zoneInfo . Type )
{
case AuthZoneType . Primary :
case AuthZoneType . Forwarder :
jsonWriter . WriteString ( "catalog" , zoneInfo . CatalogZoneName ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( zoneInfo . CatalogZoneName is not null )
{
jsonWriter . WriteBoolean ( "overrideCatalogQueryAccess" , zoneInfo . OverrideCatalogQueryAccess ) ;
jsonWriter . WriteBoolean ( "overrideCatalogZoneTransfer" , zoneInfo . OverrideCatalogZoneTransfer ) ;
jsonWriter . WriteBoolean ( "overrideCatalogNotify" , zoneInfo . OverrideCatalogNotify ) ;
}
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
break ;
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
case AuthZoneType . Stub :
jsonWriter . WriteString ( "catalog" , zoneInfo . CatalogZoneName ) ;
2022-10-05 19:22:44 +05:30
2025-02-15 12:51:16 +05:30
if ( zoneInfo . CatalogZoneName is not null )
{
jsonWriter . WriteBoolean ( "isSecondaryCatalogMember" , zoneInfo . ApexZone . SecondaryCatalogZone is not null ) ;
jsonWriter . WriteBoolean ( "overrideCatalogQueryAccess" , zoneInfo . OverrideCatalogQueryAccess ) ;
}
break ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
case AuthZoneType . Secondary :
jsonWriter . WriteString ( "catalog" , zoneInfo . CatalogZoneName ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
if ( zoneInfo . CatalogZoneName is not null )
{
jsonWriter . WriteBoolean ( "overrideCatalogQueryAccess" , zoneInfo . OverrideCatalogQueryAccess ) ;
jsonWriter . WriteBoolean ( "overrideCatalogZoneTransfer" , zoneInfo . OverrideCatalogZoneTransfer ) ;
jsonWriter . WriteBoolean ( "overrideCatalogPrimaryNameServers" , zoneInfo . OverrideCatalogPrimaryNameServers ) ;
}
break ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
case AuthZoneType . SecondaryForwarder :
jsonWriter . WriteString ( "catalog" , zoneInfo . CatalogZoneName ) ;
2024-09-21 12:55:52 +05:30
2025-02-15 12:51:16 +05:30
if ( zoneInfo . CatalogZoneName is not null )
jsonWriter . WriteBoolean ( "overrideCatalogQueryAccess" , zoneInfo . OverrideCatalogQueryAccess ) ;
2024-09-21 12:55:52 +05:30
2025-02-15 12:51:16 +05:30
break ;
}
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
//primary server
switch ( zoneInfo . Type )
{
case AuthZoneType . Secondary :
case AuthZoneType . SecondaryForwarder :
case AuthZoneType . SecondaryCatalog :
case AuthZoneType . Stub :
jsonWriter . WriteStartArray ( "primaryNameServerAddresses" ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
IReadOnlyList < NameServerAddress > primaryNameServerAddresses = zoneInfo . PrimaryNameServerAddresses ;
if ( primaryNameServerAddresses is not null )
{
foreach ( NameServerAddress primaryNameServerAddress in primaryNameServerAddresses )
jsonWriter . WriteStringValue ( primaryNameServerAddress . OriginalAddress ) ;
}
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndArray ( ) ;
break ;
}
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
switch ( zoneInfo . Type )
{
case AuthZoneType . Secondary :
case AuthZoneType . SecondaryForwarder :
case AuthZoneType . SecondaryCatalog :
if ( zoneInfo . PrimaryZoneTransferProtocol = = DnsTransportProtocol . Udp )
jsonWriter . WriteString ( "primaryZoneTransferProtocol" , "Tcp" ) ;
else
jsonWriter . WriteString ( "primaryZoneTransferProtocol" , zoneInfo . PrimaryZoneTransferProtocol . ToString ( ) ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteString ( "primaryZoneTransferTsigKeyName" , zoneInfo . PrimaryZoneTransferTsigKeyName ) ;
break ;
}
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
if ( zoneInfo . Type = = AuthZoneType . Secondary )
jsonWriter . WriteBoolean ( "validateZone" , zoneInfo . ValidateZone ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
//query access
2024-09-21 12:55:52 +05:30
{
2025-02-15 12:51:16 +05:30
jsonWriter . WriteString ( "queryAccess" , zoneInfo . QueryAccess . ToString ( ) ) ;
jsonWriter . WriteStartArray ( "queryAccessNetworkACL" ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
if ( zoneInfo . QueryAccessNetworkACL is not null )
2024-09-15 15:14:12 +05:30
{
2025-02-15 12:51:16 +05:30
foreach ( NetworkAccessControl nac in zoneInfo . QueryAccessNetworkACL )
jsonWriter . WriteStringValue ( nac . ToString ( ) ) ;
}
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndArray ( ) ;
}
//zone transfer
switch ( zoneInfo . Type )
{
case AuthZoneType . Primary :
case AuthZoneType . Secondary :
case AuthZoneType . Forwarder :
case AuthZoneType . Catalog :
case AuthZoneType . SecondaryCatalog :
jsonWriter . WriteString ( "zoneTransfer" , zoneInfo . ZoneTransfer . ToString ( ) ) ;
jsonWriter . WritePropertyName ( "zoneTransferNetworkACL" ) ;
2024-09-15 15:14:12 +05:30
{
2025-02-15 12:51:16 +05:30
jsonWriter . WriteStartArray ( ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
if ( zoneInfo . ZoneTransferNetworkACL is not null )
{
foreach ( NetworkAccessControl nac in zoneInfo . ZoneTransferNetworkACL )
jsonWriter . WriteStringValue ( nac . ToString ( ) ) ;
}
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndArray ( ) ;
}
2022-10-05 19:22:44 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WritePropertyName ( "zoneTransferTsigKeyNames" ) ;
2022-10-30 19:13:48 +05:30
{
2025-02-15 12:51:16 +05:30
jsonWriter . WriteStartArray ( ) ;
2022-10-05 19:22:44 +05:30
2025-02-15 12:51:16 +05:30
if ( zoneInfo . ZoneTransferTsigKeyNames is not null )
{
foreach ( KeyValuePair < string , object > tsigKeyName in zoneInfo . ZoneTransferTsigKeyNames )
jsonWriter . WriteStringValue ( tsigKeyName . Key ) ;
}
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndArray ( ) ;
}
2024-09-21 12:55:52 +05:30
2025-02-15 12:51:16 +05:30
break ;
}
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
//notify
switch ( zoneInfo . Type )
{
case AuthZoneType . Primary :
case AuthZoneType . Secondary :
case AuthZoneType . Forwarder :
case AuthZoneType . Catalog :
jsonWriter . WriteString ( "notify" , zoneInfo . Notify . ToString ( ) ) ;
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WritePropertyName ( "notifyNameServers" ) ;
2022-10-30 19:13:48 +05:30
{
2025-02-15 12:51:16 +05:30
jsonWriter . WriteStartArray ( ) ;
2022-10-30 19:13:48 +05:30
2025-02-15 12:51:16 +05:30
if ( zoneInfo . NotifyNameServers is not null )
{
foreach ( IPAddress nameServer in zoneInfo . NotifyNameServers )
jsonWriter . WriteStringValue ( nameServer . ToString ( ) ) ;
}
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndArray ( ) ;
}
2024-10-19 17:10:15 +05:30
2025-02-15 12:51:16 +05:30
if ( zoneInfo . Type = = AuthZoneType . Catalog )
2024-10-19 17:10:15 +05:30
{
2025-02-15 12:51:16 +05:30
jsonWriter . WriteStartArray ( "notifySecondaryCatalogsNameServers" ) ;
2024-10-19 17:10:15 +05:30
2025-02-15 12:51:16 +05:30
if ( zoneInfo . NotifySecondaryCatalogNameServers is not null )
{
foreach ( IPAddress nameServer in zoneInfo . NotifySecondaryCatalogNameServers )
jsonWriter . WriteStringValue ( nameServer . ToString ( ) ) ;
}
2022-10-05 19:22:44 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndArray ( ) ;
}
break ;
}
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
//update
switch ( zoneInfo . Type )
{
case AuthZoneType . Primary :
case AuthZoneType . Secondary :
case AuthZoneType . SecondaryForwarder :
case AuthZoneType . Forwarder :
jsonWriter . WriteString ( "update" , zoneInfo . Update . ToString ( ) ) ;
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WritePropertyName ( "updateNetworkACL" ) ;
2022-10-30 19:13:48 +05:30
{
2025-02-15 12:51:16 +05:30
jsonWriter . WriteStartArray ( ) ;
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
if ( zoneInfo . UpdateNetworkACL is not null )
{
foreach ( NetworkAccessControl nac in zoneInfo . UpdateNetworkACL )
jsonWriter . WriteStringValue ( nac . ToString ( ) ) ;
}
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndArray ( ) ;
}
break ;
}
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
switch ( zoneInfo . Type )
{
case AuthZoneType . Primary :
case AuthZoneType . Forwarder :
jsonWriter . WritePropertyName ( "updateSecurityPolicies" ) ;
2022-10-30 19:13:48 +05:30
{
2025-02-15 12:51:16 +05:30
jsonWriter . WriteStartArray ( ) ;
if ( zoneInfo . UpdateSecurityPolicies is not null )
2022-10-30 19:13:48 +05:30
{
2025-02-15 12:51:16 +05:30
foreach ( KeyValuePair < string , IReadOnlyDictionary < string , IReadOnlyList < DnsResourceRecordType > > > updateSecurityPolicy in zoneInfo . UpdateSecurityPolicies )
2022-10-30 19:13:48 +05:30
{
2025-02-15 12:51:16 +05:30
foreach ( KeyValuePair < string , IReadOnlyList < DnsResourceRecordType > > policy in updateSecurityPolicy . Value )
{
jsonWriter . WriteStartObject ( ) ;
2022-10-30 19:13:48 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteString ( "tsigKeyName" , updateSecurityPolicy . Key ) ;
jsonWriter . WriteString ( "domain" , policy . Key ) ;
2022-10-30 19:13:48 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WritePropertyName ( "allowedTypes" ) ;
jsonWriter . WriteStartArray ( ) ;
2022-10-30 19:13:48 +05:30
2025-02-15 12:51:16 +05:30
foreach ( DnsResourceRecordType allowedType in policy . Value )
jsonWriter . WriteStringValue ( allowedType . ToString ( ) ) ;
2022-10-30 19:13:48 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndArray ( ) ;
2022-10-30 19:13:48 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndObject ( ) ;
}
2022-10-30 19:13:48 +05:30
}
}
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndArray ( ) ;
}
break ;
}
2022-10-05 19:22:44 +05:30
2025-02-15 12:51:16 +05:30
if ( includeAvailableCatalogZoneNames )
2024-10-19 17:10:15 +05:30
{
2025-02-15 12:51:16 +05:30
IReadOnlyList < AuthZoneInfo > catalogZoneInfoList = _dnsWebService . _dnsServer . AuthZoneManager . GetCatalogZones ( delegate ( AuthZoneInfo catalogZoneInfo )
{
return ! catalogZoneInfo . Disabled & & _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , catalogZoneInfo . Name , session . User , PermissionFlag . Modify ) ;
} ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WritePropertyName ( "availableCatalogZoneNames" ) ;
2022-10-05 19:22:44 +05:30
jsonWriter . WriteStartArray ( ) ;
2025-02-15 12:51:16 +05:30
foreach ( AuthZoneInfo catalogZoneInfo in catalogZoneInfoList )
jsonWriter . WriteStringValue ( catalogZoneInfo . Name ) ;
2022-10-05 19:22:44 +05:30
jsonWriter . WriteEndArray ( ) ;
}
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
if ( includeAvailableTsigKeyNames )
{
jsonWriter . WritePropertyName ( "availableTsigKeyNames" ) ;
{
jsonWriter . WriteStartArray ( ) ;
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
if ( _dnsWebService . _dnsServer . TsigKeys is not null )
{
foreach ( KeyValuePair < string , TsigKey > tsigKey in _dnsWebService . _dnsServer . TsigKeys )
jsonWriter . WriteStringValue ( tsigKey . Key ) ;
}
2023-01-01 18:39:46 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndArray ( ) ;
}
}
}
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
public void SetZoneOptions ( HttpContext context )
{
UserSession session = context . GetCurrentSession ( ) ;
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , session . User , PermissionFlag . Modify ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
HttpRequest request = context . Request ;
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
string zoneName = request . GetQueryOrFormAlt ( "zone" , "domain" ) . TrimEnd ( '.' ) ;
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . IsDomainNameUnicode ( zoneName ) )
zoneName = DnsClient . ConvertDomainNameToAscii ( zoneName ) ;
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
AuthZoneInfo zoneInfo = _dnsWebService . _dnsServer . AuthZoneManager . GetAuthZoneInfo ( zoneName ) ;
if ( zoneInfo is null )
throw new DnsWebServiceException ( "No such zone was found: " + zoneName ) ;
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
if ( zoneInfo . Internal )
throw new DnsWebServiceException ( "Access was denied to manage internal DNS Server zone." ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , zoneInfo . Name , session . User , PermissionFlag . Delete ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
if ( request . TryGetQueryOrForm ( "disabled" , bool . Parse , out bool disabled ) )
zoneInfo . Disabled = disabled ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
//catalog zone override options
switch ( zoneInfo . Type )
{
case AuthZoneType . Primary :
case AuthZoneType . Forwarder :
{
if ( request . TryGetQueryOrForm ( "overrideCatalogQueryAccess" , bool . Parse , out bool overrideCatalogQueryAccess ) )
zoneInfo . OverrideCatalogQueryAccess = overrideCatalogQueryAccess ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
if ( request . TryGetQueryOrForm ( "overrideCatalogZoneTransfer" , bool . Parse , out bool overrideCatalogZoneTransfer ) )
zoneInfo . OverrideCatalogZoneTransfer = overrideCatalogZoneTransfer ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
if ( request . TryGetQueryOrForm ( "overrideCatalogNotify" , bool . Parse , out bool overrideCatalogNotify ) )
zoneInfo . OverrideCatalogNotify = overrideCatalogNotify ;
}
break ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
case AuthZoneType . Stub :
2024-09-15 15:14:12 +05:30
{
2025-02-15 12:51:16 +05:30
if ( zoneInfo . ApexZone . SecondaryCatalogZone is not null )
break ; //cannot set option for Stub zone that is a member of Secondary Catalog Zone
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
if ( request . TryGetQueryOrForm ( "overrideCatalogQueryAccess" , bool . Parse , out bool overrideCatalogQueryAccess ) )
zoneInfo . OverrideCatalogQueryAccess = overrideCatalogQueryAccess ;
2024-09-15 15:14:12 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
}
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
//primary server
switch ( zoneInfo . Type )
{
case AuthZoneType . Secondary :
case AuthZoneType . SecondaryForwarder :
case AuthZoneType . SecondaryCatalog :
2024-09-15 15:14:12 +05:30
{
2025-02-15 12:51:16 +05:30
if ( zoneInfo . ApexZone . SecondaryCatalogZone is not null )
break ; //cannot set option for zone that is a member of Secondary Catalog Zone
if ( request . TryGetQueryOrFormEnum ( "primaryZoneTransferProtocol" , out DnsTransportProtocol primaryZoneTransferProtocol ) )
2024-09-15 15:14:12 +05:30
{
2025-02-15 12:51:16 +05:30
if ( primaryZoneTransferProtocol = = DnsTransportProtocol . Quic )
DnsWebService . ValidateQuicSupport ( ) ;
zoneInfo . PrimaryZoneTransferProtocol = primaryZoneTransferProtocol ;
2024-09-15 15:14:12 +05:30
}
2025-02-15 12:51:16 +05:30
string primaryNameServerAddresses = request . QueryOrForm ( "primaryNameServerAddresses" ) ;
if ( primaryNameServerAddresses is not null )
2024-09-15 15:14:12 +05:30
{
2025-02-15 12:51:16 +05:30
if ( primaryNameServerAddresses . Length = = 0 )
2024-09-15 15:14:12 +05:30
{
2025-02-15 12:51:16 +05:30
zoneInfo . PrimaryNameServerAddresses = null ;
}
else
{
zoneInfo . PrimaryNameServerAddresses = primaryNameServerAddresses . Split ( delegate ( string address )
{
NameServerAddress nameServer = NameServerAddress . Parse ( address ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
if ( nameServer . Protocol ! = primaryZoneTransferProtocol )
nameServer = nameServer . ChangeProtocol ( primaryZoneTransferProtocol ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
return nameServer ;
} , ',' ) ;
}
2024-09-15 15:14:12 +05:30
}
2025-02-15 12:51:16 +05:30
string primaryZoneTransferTsigKeyName = request . QueryOrForm ( "primaryZoneTransferTsigKeyName" ) ;
if ( primaryZoneTransferTsigKeyName is not null )
{
if ( primaryZoneTransferTsigKeyName . Length = = 0 )
zoneInfo . PrimaryZoneTransferTsigKeyName = null ;
else
zoneInfo . PrimaryZoneTransferTsigKeyName = primaryZoneTransferTsigKeyName ;
}
2024-09-15 15:14:12 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
case AuthZoneType . Stub :
2024-09-15 15:14:12 +05:30
{
2025-02-15 12:51:16 +05:30
if ( zoneInfo . ApexZone . SecondaryCatalogZone is not null )
break ; //cannot set option for Stub zone that is a member of Secondary Catalog Zone
string primaryNameServerAddresses = request . QueryOrForm ( "primaryNameServerAddresses" ) ;
if ( primaryNameServerAddresses is not null )
2024-09-15 15:14:12 +05:30
{
2025-02-15 12:51:16 +05:30
if ( primaryNameServerAddresses . Length = = 0 )
{
zoneInfo . PrimaryNameServerAddresses = null ;
}
else
2024-09-15 15:14:12 +05:30
{
2025-02-15 12:51:16 +05:30
zoneInfo . PrimaryNameServerAddresses = primaryNameServerAddresses . Split ( delegate ( string address )
{
NameServerAddress nameServer = NameServerAddress . Parse ( address ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
if ( nameServer . Protocol ! = DnsTransportProtocol . Udp )
nameServer = nameServer . ChangeProtocol ( DnsTransportProtocol . Udp ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
return nameServer ;
} , ',' ) ;
}
2024-09-15 15:14:12 +05:30
}
}
2025-02-15 12:51:16 +05:30
break ;
2024-09-15 15:14:12 +05:30
}
2025-02-15 12:51:16 +05:30
if ( zoneInfo . Type = = AuthZoneType . Secondary )
{
2024-09-21 12:55:52 +05:30
if ( zoneInfo . ApexZone . SecondaryCatalogZone is not null )
2022-10-30 19:13:48 +05:30
{
2025-02-15 12:51:16 +05:30
//cannot set option for zone that is a member of Secondary Catalog Zone
}
else if ( request . TryGetQueryOrForm ( "validateZone" , bool . Parse , out bool validateZone ) )
{
zoneInfo . ValidateZone = validateZone ;
2022-10-30 19:13:48 +05:30
}
2025-02-15 12:51:16 +05:30
}
2022-10-05 19:22:44 +05:30
2025-02-15 12:51:16 +05:30
//query access
switch ( zoneInfo . Type )
{
case AuthZoneType . Primary :
case AuthZoneType . Secondary :
case AuthZoneType . Stub :
case AuthZoneType . Forwarder :
case AuthZoneType . SecondaryForwarder :
case AuthZoneType . Catalog :
if ( zoneInfo . ApexZone . SecondaryCatalogZone is not null )
break ; //cannot set option for zone that is a member of Secondary Catalog Zone
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
string queryAccessNetworkACL = request . QueryOrForm ( "queryAccessNetworkACL" ) ;
if ( queryAccessNetworkACL is not null )
{
if ( ( queryAccessNetworkACL . Length = = 0 ) | | queryAccessNetworkACL . Equals ( "false" , StringComparison . OrdinalIgnoreCase ) )
zoneInfo . QueryAccessNetworkACL = null ;
else
zoneInfo . QueryAccessNetworkACL = queryAccessNetworkACL . Split ( NetworkAccessControl . Parse , ',' ) ;
}
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
if ( request . TryGetQueryOrFormEnum ( "queryAccess" , out AuthZoneQueryAccess queryAccess ) )
zoneInfo . QueryAccess = queryAccess ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
break ;
}
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
//zone transfer
switch ( zoneInfo . Type )
{
case AuthZoneType . Primary :
case AuthZoneType . Secondary :
case AuthZoneType . Forwarder :
case AuthZoneType . Catalog :
if ( zoneInfo . ApexZone . SecondaryCatalogZone is not null )
break ; //cannot set option for zone that is a member of Secondary Catalog Zone
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
string strZoneTransferNetworkACL = request . QueryOrForm ( "zoneTransferNetworkACL" ) ;
if ( strZoneTransferNetworkACL is not null )
2022-10-30 19:13:48 +05:30
{
2025-02-15 12:51:16 +05:30
if ( ( strZoneTransferNetworkACL . Length = = 0 ) | | strZoneTransferNetworkACL . Equals ( "false" , StringComparison . OrdinalIgnoreCase ) )
zoneInfo . ZoneTransferNetworkACL = null ;
else
zoneInfo . ZoneTransferNetworkACL = strZoneTransferNetworkACL . Split ( NetworkAccessControl . Parse , ',' ) ;
2022-10-30 19:13:48 +05:30
}
2025-02-15 12:51:16 +05:30
if ( request . TryGetQueryOrFormEnum ( "zoneTransfer" , out AuthZoneTransfer zoneTransfer ) )
zoneInfo . ZoneTransfer = zoneTransfer ;
string strZoneTransferTsigKeyNames = request . QueryOrForm ( "zoneTransferTsigKeyNames" ) ;
if ( strZoneTransferTsigKeyNames is not null )
2022-10-30 19:13:48 +05:30
{
2025-02-15 12:51:16 +05:30
if ( ( strZoneTransferTsigKeyNames . Length = = 0 ) | | strZoneTransferTsigKeyNames . Equals ( "false" , StringComparison . OrdinalIgnoreCase ) )
{
zoneInfo . ZoneTransferTsigKeyNames = null ;
}
else
{
string [ ] strZoneTransferTsigKeyNamesParts = strZoneTransferTsigKeyNames . Split ( _commaSeparator , StringSplitOptions . RemoveEmptyEntries ) ;
Dictionary < string , object > zoneTransferTsigKeyNames = new Dictionary < string , object > ( strZoneTransferTsigKeyNamesParts . Length ) ;
2022-10-05 19:22:44 +05:30
2025-02-15 12:51:16 +05:30
for ( int i = 0 ; i < strZoneTransferTsigKeyNamesParts . Length ; i + + )
zoneTransferTsigKeyNames . Add ( strZoneTransferTsigKeyNamesParts [ i ] . TrimEnd ( '.' ) . ToLowerInvariant ( ) , null ) ;
2022-10-05 19:22:44 +05:30
2025-02-15 12:51:16 +05:30
zoneInfo . ZoneTransferTsigKeyNames = zoneTransferTsigKeyNames ;
}
2022-10-30 19:13:48 +05:30
}
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
break ;
}
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
//notify
switch ( zoneInfo . Type )
{
case AuthZoneType . Primary :
case AuthZoneType . Secondary :
case AuthZoneType . Forwarder :
case AuthZoneType . Catalog :
if ( request . TryGetQueryOrFormEnum ( "notify" , out AuthZoneNotify notify ) )
zoneInfo . Notify = notify ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
string strNotifyNameServers = request . QueryOrForm ( "notifyNameServers" ) ;
if ( strNotifyNameServers is not null )
2024-10-19 17:10:15 +05:30
{
2025-02-15 12:51:16 +05:30
if ( ( strNotifyNameServers . Length = = 0 ) | | strNotifyNameServers . Equals ( "false" , StringComparison . OrdinalIgnoreCase ) )
zoneInfo . NotifyNameServers = null ;
2024-10-19 17:10:15 +05:30
else
2025-02-15 12:51:16 +05:30
zoneInfo . NotifyNameServers = strNotifyNameServers . Split ( IPAddress . Parse , ',' ) ;
2024-10-19 17:10:15 +05:30
}
2025-02-15 12:51:16 +05:30
if ( zoneInfo . Type = = AuthZoneType . Catalog )
{
string strNotifySecondaryCatalogNameServers = request . QueryOrForm ( "notifySecondaryCatalogsNameServers" ) ;
if ( strNotifySecondaryCatalogNameServers is not null )
{
if ( ( strNotifySecondaryCatalogNameServers . Length = = 0 ) | | strNotifySecondaryCatalogNameServers . Equals ( "false" , StringComparison . OrdinalIgnoreCase ) )
zoneInfo . NotifySecondaryCatalogNameServers = null ;
else
zoneInfo . NotifySecondaryCatalogNameServers = strNotifySecondaryCatalogNameServers . Split ( IPAddress . Parse , ',' ) ;
}
}
2022-10-05 19:22:44 +05:30
2025-02-15 12:51:16 +05:30
break ;
}
2022-10-05 19:22:44 +05:30
2025-02-15 12:51:16 +05:30
//update
switch ( zoneInfo . Type )
{
case AuthZoneType . Primary :
case AuthZoneType . Secondary :
case AuthZoneType . SecondaryForwarder :
case AuthZoneType . Forwarder :
if ( request . TryGetQueryOrFormEnum ( "update" , out AuthZoneUpdate update ) )
zoneInfo . Update = update ;
string strUpdateNetworkACL = request . QueryOrForm ( "updateNetworkACL" ) ;
if ( strUpdateNetworkACL is not null )
2022-10-30 19:13:48 +05:30
{
2025-02-15 12:51:16 +05:30
if ( ( strUpdateNetworkACL . Length = = 0 ) | | strUpdateNetworkACL . Equals ( "false" , StringComparison . OrdinalIgnoreCase ) )
zoneInfo . UpdateNetworkACL = null ;
else
zoneInfo . UpdateNetworkACL = strUpdateNetworkACL . Split ( NetworkAccessControl . Parse , ',' ) ;
2022-10-30 19:13:48 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
}
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
switch ( zoneInfo . Type )
{
case AuthZoneType . Primary :
case AuthZoneType . Forwarder :
string strUpdateSecurityPolicies = request . QueryOrForm ( "updateSecurityPolicies" ) ;
if ( strUpdateSecurityPolicies is not null )
{
if ( ( strUpdateSecurityPolicies . Length = = 0 ) | | strUpdateSecurityPolicies . Equals ( "false" , StringComparison . OrdinalIgnoreCase ) )
2022-10-30 19:13:48 +05:30
{
2025-02-15 12:51:16 +05:30
zoneInfo . UpdateSecurityPolicies = null ;
}
else
{
string [ ] strUpdateSecurityPoliciesParts = strUpdateSecurityPolicies . Split ( _pipeSeparator , StringSplitOptions . RemoveEmptyEntries ) ;
Dictionary < string , IReadOnlyDictionary < string , IReadOnlyList < DnsResourceRecordType > > > updateSecurityPolicies = new Dictionary < string , IReadOnlyDictionary < string , IReadOnlyList < DnsResourceRecordType > > > ( strUpdateSecurityPoliciesParts . Length ) ;
2022-10-30 19:13:48 +05:30
2025-02-15 12:51:16 +05:30
for ( int i = 0 ; i < strUpdateSecurityPoliciesParts . Length ; i + = 3 )
2022-10-30 19:13:48 +05:30
{
2025-02-15 12:51:16 +05:30
string tsigKeyName = strUpdateSecurityPoliciesParts [ i ] . TrimEnd ( '.' ) . ToLowerInvariant ( ) ;
string domain = strUpdateSecurityPoliciesParts [ i + 1 ] . TrimEnd ( '.' ) . ToLowerInvariant ( ) ;
string strTypes = strUpdateSecurityPoliciesParts [ i + 2 ] ;
2022-10-30 19:13:48 +05:30
2025-02-15 12:51:16 +05:30
if ( ! domain . Equals ( zoneInfo . Name , StringComparison . OrdinalIgnoreCase ) & & ! domain . EndsWith ( "." + zoneInfo . Name , StringComparison . OrdinalIgnoreCase ) )
throw new DnsWebServiceException ( "Cannot set Dynamic Updates security policies: the domain '" + domain + "' must be part of the current zone." ) ;
if ( ! updateSecurityPolicies . TryGetValue ( tsigKeyName , out IReadOnlyDictionary < string , IReadOnlyList < DnsResourceRecordType > > policyMap ) )
{
policyMap = new Dictionary < string , IReadOnlyList < DnsResourceRecordType > > ( ) ;
updateSecurityPolicies . Add ( tsigKeyName , policyMap ) ;
}
if ( ! policyMap . TryGetValue ( domain , out IReadOnlyList < DnsResourceRecordType > types ) )
{
types = new List < DnsResourceRecordType > ( ) ;
( policyMap as Dictionary < string , IReadOnlyList < DnsResourceRecordType > > ) . Add ( domain , types ) ;
}
foreach ( string strType in strTypes . Split ( _commaSpaceSeparator , StringSplitOptions . RemoveEmptyEntries ) )
( types as List < DnsResourceRecordType > ) . Add ( Enum . Parse < DnsResourceRecordType > ( strType , true ) ) ;
2022-10-30 19:13:48 +05:30
}
2025-02-15 12:51:16 +05:30
zoneInfo . UpdateSecurityPolicies = updateSecurityPolicies ;
2022-10-30 19:13:48 +05:30
}
}
2025-02-15 12:51:16 +05:30
break ;
}
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
//catalog zone; done last to allow using updated properties when there is change of ownership
switch ( zoneInfo . Type )
{
case AuthZoneType . Primary :
case AuthZoneType . Stub :
case AuthZoneType . Forwarder :
if ( zoneInfo . ApexZone . SecondaryCatalogZone is not null )
break ; //cannot set option for Stub zone that is a member of Secondary Catalog Zone
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
string catalogZoneName = request . QueryOrForm ( "catalog" ) ;
if ( catalogZoneName is not null )
2024-09-15 15:14:12 +05:30
{
2025-02-15 12:51:16 +05:30
string oldCatalogZoneName = zoneInfo . CatalogZoneName ;
2024-10-19 17:10:15 +05:30
2025-02-15 12:51:16 +05:30
if ( catalogZoneName . Length = = 0 )
{
if ( ! string . IsNullOrEmpty ( oldCatalogZoneName ) )
_dnsWebService . _dnsServer . AuthZoneManager . RemoveCatalogMemberZone ( zoneInfo ) ;
2024-10-19 17:10:15 +05:30
}
2025-02-15 12:51:16 +05:30
else
2024-10-19 17:10:15 +05:30
{
2025-02-15 12:51:16 +05:30
if ( string . IsNullOrEmpty ( oldCatalogZoneName ) )
{
//check catalog permissions
AuthZoneInfo catalogZoneInfo = _dnsWebService . _dnsServer . AuthZoneManager . GetAuthZoneInfo ( catalogZoneName ) ;
if ( catalogZoneInfo is null )
throw new DnsWebServiceException ( "No such Catalog zone was found: " + catalogZoneName ) ;
2024-10-19 17:10:15 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , catalogZoneInfo . Name , session . User , PermissionFlag . Modify ) )
throw new DnsWebServiceException ( "Access was denied to use Catalog zone: " + catalogZoneInfo . Name ) ;
2024-10-19 17:10:15 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _dnsServer . AuthZoneManager . AddCatalogMemberZone ( catalogZoneName , zoneInfo ) ;
}
else if ( ! catalogZoneName . Equals ( oldCatalogZoneName , StringComparison . OrdinalIgnoreCase ) )
{
//check catalog permissions
AuthZoneInfo catalogZoneInfo = _dnsWebService . _dnsServer . AuthZoneManager . GetAuthZoneInfo ( catalogZoneName ) ;
if ( catalogZoneInfo is null )
throw new DnsWebServiceException ( "No such Catalog zone was found: " + catalogZoneName ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , catalogZoneInfo . Name , session . User , PermissionFlag . Modify ) )
throw new DnsWebServiceException ( "Access was denied to use Catalog zone: " + catalogZoneInfo . Name ) ;
2024-09-21 12:55:52 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _dnsServer . AuthZoneManager . ChangeCatalogMemberZoneOwnership ( zoneInfo , catalogZoneName ) ;
}
}
}
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
if ( zoneInfo . ApexZone . CatalogZone is not null )
_dnsWebService . _dnsServer . AuthZoneManager . SaveZoneFile ( zoneInfo . ApexZone . CatalogZoneName ) ;
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
break ;
}
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _log . Write ( context . GetRemoteEndPoint ( _dnsWebService . _webServiceRealIpHeader ) , "[" + session . User . Username + "] " + zoneInfo . TypeName + " zone options were updated successfully: " + zoneInfo . DisplayName ) ;
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _dnsServer . AuthZoneManager . SaveZoneFile ( zoneInfo . Name ) ;
}
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
public void ResyncZone ( HttpContext context )
{
UserSession session = context . GetCurrentSession ( ) ;
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , session . User , PermissionFlag . Modify ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
string zoneName = context . Request . GetQueryOrFormAlt ( "zone" , "domain" ) . TrimEnd ( '.' ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . IsDomainNameUnicode ( zoneName ) )
zoneName = DnsClient . ConvertDomainNameToAscii ( zoneName ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
AuthZoneInfo zoneInfo = _dnsWebService . _dnsServer . AuthZoneManager . GetAuthZoneInfo ( zoneName ) ;
if ( zoneInfo is null )
throw new DnsWebServiceException ( "No such zone was found: " + zoneName ) ;
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
if ( zoneInfo . Internal )
throw new DnsWebServiceException ( "Access was denied to manage internal DNS Server zone." ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , zoneInfo . Name , session . User , PermissionFlag . Modify ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
switch ( zoneInfo . Type )
{
case AuthZoneType . Secondary :
case AuthZoneType . SecondaryForwarder :
case AuthZoneType . SecondaryCatalog :
case AuthZoneType . Stub :
zoneInfo . TriggerResync ( ) ;
break ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
default :
throw new DnsWebServiceException ( "Only Secondary, Secondary Forwarder, Secondary Catalog, and Stub zones support resync." ) ;
}
}
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
public void AddRecord ( HttpContext context )
2023-04-23 16:34:17 +05:30
{
2025-02-15 12:51:16 +05:30
HttpRequest request = context . Request ;
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
string domain = request . GetQueryOrForm ( "domain" ) . TrimEnd ( '.' ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . IsDomainNameUnicode ( domain ) )
domain = DnsClient . ConvertDomainNameToAscii ( domain ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
string zoneName = request . QueryOrForm ( "zone" ) ;
if ( zoneName is not null )
{
zoneName = zoneName . TrimEnd ( '.' ) ;
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . IsDomainNameUnicode ( zoneName ) )
zoneName = DnsClient . ConvertDomainNameToAscii ( zoneName ) ;
}
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
AuthZoneInfo zoneInfo = _dnsWebService . _dnsServer . AuthZoneManager . FindAuthZoneInfo ( string . IsNullOrEmpty ( zoneName ) ? domain : zoneName ) ;
if ( zoneInfo is null )
throw new DnsWebServiceException ( "No such zone was found: " + domain ) ;
2022-02-20 17:13:52 +05:30
2025-02-15 12:51:16 +05:30
if ( zoneInfo . Internal )
throw new DnsWebServiceException ( "Access was denied to manage internal DNS Server zone." ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
UserSession session = context . GetCurrentSession ( ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , zoneInfo . Name , session . User , PermissionFlag . Modify ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
DnsResourceRecordType type = request . GetQueryOrFormEnum < DnsResourceRecordType > ( "type" ) ;
2025-03-29 18:58:25 +05:30
uint ttl = request . GetQueryOrForm ( "ttl" , ZoneFile . ParseTtl , _defaultRecordTtl ) ;
2025-02-15 12:51:16 +05:30
bool overwrite = request . GetQueryOrForm ( "overwrite" , bool . Parse , false ) ;
string comments = request . QueryOrForm ( "comments" ) ;
2025-03-31 19:36:23 +05:30
uint expiryTtl = request . GetQueryOrForm ( "expiryTtl" , ZoneFile . ParseTtl , 0 u ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
DnsResourceRecord newRecord ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
switch ( type )
{
case DnsResourceRecordType . A :
case DnsResourceRecordType . AAAA :
{
string strIPAddress = request . GetQueryOrFormAlt ( "ipAddress" , "value" ) ;
IPAddress ipAddress ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( strIPAddress . Equals ( "request-ip-address" ) )
ipAddress = context . GetRemoteEndPoint ( _dnsWebService . _webServiceRealIpHeader ) . Address ;
else
ipAddress = IPAddress . Parse ( strIPAddress ) ;
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
bool ptr = request . GetQueryOrForm ( "ptr" , bool . Parse , false ) ;
if ( ptr )
{
string ptrDomain = Zone . GetReverseZone ( ipAddress , type = = DnsResourceRecordType . A ? 32 : 128 ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
AuthZoneInfo reverseZoneInfo = _dnsWebService . _dnsServer . AuthZoneManager . FindAuthZoneInfo ( ptrDomain ) ;
if ( reverseZoneInfo is null )
{
bool createPtrZone = request . GetQueryOrForm ( "createPtrZone" , bool . Parse , false ) ;
if ( ! createPtrZone )
throw new DnsWebServiceException ( "No reverse zone available to add PTR record." ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
string ptrZone = Zone . GetReverseZone ( ipAddress , type = = DnsResourceRecordType . A ? 24 : 64 ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
reverseZoneInfo = _dnsWebService . _dnsServer . AuthZoneManager . CreatePrimaryZone ( ptrZone ) ;
if ( reverseZoneInfo = = null )
throw new DnsWebServiceException ( "Failed to create reverse zone to add PTR record: " + ptrZone ) ;
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
//set permissions
_dnsWebService . _authManager . SetPermission ( PermissionSection . Zones , reverseZoneInfo . Name , session . User , PermissionFlag . ViewModifyDelete ) ;
_dnsWebService . _authManager . SetPermission ( PermissionSection . Zones , reverseZoneInfo . Name , _dnsWebService . _authManager . GetGroup ( Group . ADMINISTRATORS ) , PermissionFlag . ViewModifyDelete ) ;
_dnsWebService . _authManager . SetPermission ( PermissionSection . Zones , reverseZoneInfo . Name , _dnsWebService . _authManager . GetGroup ( Group . DNS_ADMINISTRATORS ) , PermissionFlag . ViewModifyDelete ) ;
_dnsWebService . _authManager . SaveConfigFile ( ) ;
}
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( reverseZoneInfo . Internal )
throw new DnsWebServiceException ( "Reverse zone '" + reverseZoneInfo . DisplayName + "' is an internal zone." ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( ( reverseZoneInfo . Type ! = AuthZoneType . Primary ) & & ( reverseZoneInfo . Type ! = AuthZoneType . Forwarder ) )
throw new DnsWebServiceException ( "Reverse zone '" + reverseZoneInfo . DisplayName + "' is not a primary or forwarder zone." ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
DnsResourceRecord ptrRecord = new DnsResourceRecord ( ptrDomain , DnsResourceRecordType . PTR , DnsClass . IN , ttl , new DnsPTRRecordData ( domain ) ) ;
ptrRecord . GetAuthGenericRecordInfo ( ) . LastModified = DateTime . UtcNow ;
ptrRecord . GetAuthGenericRecordInfo ( ) . ExpiryTtl = expiryTtl ;
2022-01-23 18:22:17 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _dnsServer . AuthZoneManager . SetRecord ( reverseZoneInfo . Name , ptrRecord ) ;
_dnsWebService . _dnsServer . AuthZoneManager . SaveZoneFile ( reverseZoneInfo . Name ) ;
}
2024-11-23 13:14:04 +05:30
2025-02-15 12:51:16 +05:30
if ( type = = DnsResourceRecordType . A )
newRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , ttl , new DnsARecordData ( ipAddress ) ) ;
else
newRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , ttl , new DnsAAAARecordData ( ipAddress ) ) ;
2024-11-23 13:14:04 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . NS :
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
string nameServer = request . GetQueryOrFormAlt ( "nameServer" , "value" ) . TrimEnd ( '.' ) ;
string glueAddresses = request . GetQueryOrForm ( "glue" , null ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
newRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , ttl , new DnsNSRecordData ( nameServer ) ) ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
if ( ! string . IsNullOrEmpty ( glueAddresses ) )
{
if ( zoneInfo . Name . Equals ( domain , StringComparison . OrdinalIgnoreCase ) & & ( nameServer . Equals ( domain , StringComparison . OrdinalIgnoreCase ) | | nameServer . EndsWith ( "." + domain , StringComparison . OrdinalIgnoreCase ) ) )
throw new DnsWebServiceException ( "The zone's own NS records cannot have glue addresses. Please add separate A/AAAA records in the zone instead." ) ;
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
newRecord . SetGlueRecords ( glueAddresses ) ;
}
}
break ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . CNAME :
{
if ( ! overwrite )
{
IReadOnlyList < DnsResourceRecord > existingRecords = _dnsWebService . _dnsServer . AuthZoneManager . GetRecords ( zoneInfo . Name , domain , type ) ;
if ( existingRecords . Count > 0 )
throw new DnsWebServiceException ( "Record already exists. Use overwrite option if you wish to overwrite existing record." ) ;
}
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
string cname = request . GetQueryOrFormAlt ( "cname" , "value" ) . TrimEnd ( '.' ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( cname . Equals ( domain , StringComparison . OrdinalIgnoreCase ) )
throw new DnsWebServiceException ( "CNAME domain name cannot be same as that of the record name." ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
newRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , ttl , new DnsCNAMERecordData ( cname ) ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
overwrite = true ; //force SetRecord
}
break ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . PTR :
{
string ptrName = request . GetQueryOrFormAlt ( "ptrName" , "value" ) . TrimEnd ( '.' ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
newRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , ttl , new DnsPTRRecordData ( ptrName ) ) ;
}
break ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . MX :
{
ushort preference = request . GetQueryOrForm ( "preference" , ushort . Parse ) ;
string exchange = request . GetQueryOrFormAlt ( "exchange" , "value" ) . TrimEnd ( '.' ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
newRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , ttl , new DnsMXRecordData ( preference , exchange ) ) ;
}
break ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . TXT :
{
string text = request . GetQueryOrFormAlt ( "text" , "value" ) ;
bool splitText = request . GetQueryOrForm ( "splitText" , bool . Parse , false ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
newRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , ttl , splitText ? new DnsTXTRecordData ( DecodeCharacterStrings ( text ) ) : new DnsTXTRecordData ( text ) ) ;
}
break ;
2024-05-19 16:40:40 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . RP :
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
string mailbox = request . GetQueryOrForm ( "mailbox" , "" ) . TrimEnd ( '.' ) ;
string txtDomain = request . GetQueryOrForm ( "txtDomain" , "" ) . TrimEnd ( '.' ) ;
newRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , ttl , new DnsRPRecordData ( mailbox , txtDomain ) ) ;
2022-04-30 16:19:02 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . SRV :
{
ushort priority = request . GetQueryOrForm ( "priority" , ushort . Parse ) ;
ushort weight = request . GetQueryOrForm ( "weight" , ushort . Parse ) ;
ushort port = request . GetQueryOrForm ( "port" , ushort . Parse ) ;
string target = request . GetQueryOrFormAlt ( "target" , "value" ) . TrimEnd ( '.' ) ;
2021-11-06 13:30:48 +05:30
2025-02-15 12:51:16 +05:30
newRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , ttl , new DnsSRVRecordData ( priority , weight , port , target ) ) ;
}
break ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . NAPTR :
{
ushort order = request . GetQueryOrForm ( "naptrOrder" , ushort . Parse ) ;
ushort preference = request . GetQueryOrForm ( "naptrPreference" , ushort . Parse ) ;
string flags = request . GetQueryOrForm ( "naptrFlags" , "" ) ;
string services = request . GetQueryOrForm ( "naptrServices" , "" ) ;
string regexp = request . GetQueryOrForm ( "naptrRegexp" , "" ) ;
string replacement = request . GetQueryOrForm ( "naptrReplacement" , "" ) . TrimEnd ( '.' ) ;
newRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , ttl , new DnsNAPTRRecordData ( order , preference , flags , services , regexp , replacement ) ) ;
}
break ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . DNAME :
{
if ( ! overwrite )
{
IReadOnlyList < DnsResourceRecord > existingRecords = _dnsWebService . _dnsServer . AuthZoneManager . GetRecords ( zoneInfo . Name , domain , type ) ;
if ( existingRecords . Count > 0 )
throw new DnsWebServiceException ( "Record already exists. Use overwrite option if you wish to overwrite existing record." ) ;
}
2021-11-06 13:30:48 +05:30
2025-02-15 12:51:16 +05:30
string dname = request . GetQueryOrFormAlt ( "dname" , "value" ) . TrimEnd ( '.' ) ;
2021-11-06 13:30:48 +05:30
2025-02-15 12:51:16 +05:30
if ( dname . EndsWith ( "." + domain , StringComparison . OrdinalIgnoreCase ) )
throw new DnsWebServiceException ( "DNAME domain name cannot be a sub domain of the record name." ) ;
2021-11-06 13:30:48 +05:30
2025-02-15 12:51:16 +05:30
if ( dname . Equals ( domain , StringComparison . OrdinalIgnoreCase ) )
throw new DnsWebServiceException ( "DNAME domain name cannot be same as that of the record name." ) ;
2021-11-06 13:30:48 +05:30
2025-02-15 12:51:16 +05:30
newRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , ttl , new DnsDNAMERecordData ( dname ) ) ;
2022-11-12 15:12:44 +05:30
2025-02-15 12:51:16 +05:30
overwrite = true ; //force SetRecord
}
break ;
2022-11-12 15:12:44 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . DS :
{
ushort keyTag = request . GetQueryOrForm ( "keyTag" , ushort . Parse ) ;
DnssecAlgorithm algorithm = Enum . Parse < DnssecAlgorithm > ( request . GetQueryOrForm ( "algorithm" ) . Replace ( '-' , '_' ) , true ) ;
DnssecDigestType digestType = Enum . Parse < DnssecDigestType > ( request . GetQueryOrForm ( "digestType" ) . Replace ( '-' , '_' ) , true ) ;
byte [ ] digest = request . GetQueryOrFormAlt ( "digest" , "value" , Convert . FromHexString ) ;
2022-11-12 15:12:44 +05:30
2025-02-15 12:51:16 +05:30
newRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , ttl , new DnsDSRecordData ( keyTag , algorithm , digestType , digest ) ) ;
}
break ;
2022-10-30 19:13:48 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . SSHFP :
{
DnsSSHFPAlgorithm sshfpAlgorithm = request . GetQueryOrFormEnum < DnsSSHFPAlgorithm > ( "sshfpAlgorithm" ) ;
DnsSSHFPFingerprintType sshfpFingerprintType = request . GetQueryOrFormEnum < DnsSSHFPFingerprintType > ( "sshfpFingerprintType" ) ;
byte [ ] sshfpFingerprint = request . GetQueryOrForm ( "sshfpFingerprint" , Convert . FromHexString ) ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
newRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , ttl , new DnsSSHFPRecordData ( sshfpAlgorithm , sshfpFingerprintType , sshfpFingerprint ) ) ;
}
break ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . TLSA :
2023-05-20 18:40:44 +05:30
{
2025-02-15 12:51:16 +05:30
DnsTLSACertificateUsage tlsaCertificateUsage = Enum . Parse < DnsTLSACertificateUsage > ( request . GetQueryOrForm ( "tlsaCertificateUsage" ) . Replace ( '-' , '_' ) , true ) ;
DnsTLSASelector tlsaSelector = request . GetQueryOrFormEnum < DnsTLSASelector > ( "tlsaSelector" ) ;
DnsTLSAMatchingType tlsaMatchingType = Enum . Parse < DnsTLSAMatchingType > ( request . GetQueryOrForm ( "tlsaMatchingType" ) . Replace ( '-' , '_' ) , true ) ;
string tlsaCertificateAssociationData = request . GetQueryOrForm ( "tlsaCertificateAssociationData" ) ;
newRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , ttl , new DnsTLSARecordData ( tlsaCertificateUsage , tlsaSelector , tlsaMatchingType , tlsaCertificateAssociationData ) ) ;
2023-05-20 18:40:44 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
case DnsResourceRecordType . SVCB :
case DnsResourceRecordType . HTTPS :
2023-05-20 18:40:44 +05:30
{
2025-02-15 12:51:16 +05:30
ushort svcPriority = request . GetQueryOrForm ( "svcPriority" , ushort . Parse ) ;
string targetName = request . GetQueryOrForm ( "svcTargetName" ) . TrimEnd ( '.' ) ;
string strSvcParams = request . GetQueryOrForm ( "svcParams" ) ;
bool autoIpv4Hint = request . GetQueryOrForm ( "autoIpv4Hint" , bool . Parse , false ) ;
bool autoIpv6Hint = request . GetQueryOrForm ( "autoIpv6Hint" , bool . Parse , false ) ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
Dictionary < DnsSvcParamKey , DnsSvcParamValue > svcParams ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
if ( strSvcParams . Equals ( "false" , StringComparison . OrdinalIgnoreCase ) )
{
svcParams = new Dictionary < DnsSvcParamKey , DnsSvcParamValue > ( 0 ) ;
2023-05-20 18:40:44 +05:30
}
2025-02-15 12:51:16 +05:30
else
{
string [ ] strSvcParamsParts = strSvcParams . Split ( '|' ) ;
svcParams = new Dictionary < DnsSvcParamKey , DnsSvcParamValue > ( strSvcParamsParts . Length / 2 ) ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
for ( int i = 0 ; i < strSvcParamsParts . Length ; i + = 2 )
{
DnsSvcParamKey svcParamKey = Enum . Parse < DnsSvcParamKey > ( strSvcParamsParts [ i ] . Replace ( '-' , '_' ) , true ) ;
DnsSvcParamValue svcParamValue = DnsSvcParamValue . Parse ( svcParamKey , strSvcParamsParts [ i + 1 ] ) ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
svcParams . Add ( svcParamKey , svcParamValue ) ;
}
}
2024-06-01 19:25:07 +05:30
2025-02-15 12:51:16 +05:30
newRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , ttl , new DnsSVCBRecordData ( svcPriority , targetName , svcParams ) ) ;
2024-06-01 19:25:07 +05:30
2025-02-15 12:51:16 +05:30
if ( autoIpv4Hint )
newRecord . GetAuthSVCBRecordInfo ( ) . AutoIpv4Hint = true ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
if ( autoIpv6Hint )
newRecord . GetAuthSVCBRecordInfo ( ) . AutoIpv6Hint = true ;
2023-07-02 15:47:55 +05:30
2025-02-15 12:51:16 +05:30
if ( autoIpv4Hint | | autoIpv6Hint )
ResolveSvcbAutoHints ( zoneInfo . Name , newRecord , autoIpv4Hint , autoIpv6Hint , svcParams ) ;
}
break ;
2023-07-02 15:47:55 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . URI :
{
ushort priority = request . GetQueryOrForm ( "uriPriority" , ushort . Parse ) ;
ushort weight = request . GetQueryOrForm ( "uriWeight" , ushort . Parse ) ;
Uri uri = request . GetQueryOrForm ( "uri" , delegate ( string value ) { return new Uri ( value ) ; } ) ;
2021-11-06 13:30:48 +05:30
2025-02-15 12:51:16 +05:30
newRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , ttl , new DnsURIRecordData ( priority , weight , uri ) ) ;
}
break ;
2021-11-06 13:30:48 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . CAA :
{
byte flags = request . GetQueryOrForm ( "flags" , byte . Parse ) ;
string tag = request . GetQueryOrForm ( "tag" ) ;
string value = request . GetQueryOrForm ( "value" ) ;
2021-11-06 13:30:48 +05:30
2025-02-15 12:51:16 +05:30
newRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , ttl , new DnsCAARecordData ( flags , tag , value ) ) ;
}
break ;
2021-11-06 13:30:48 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . ANAME :
{
string aname = request . GetQueryOrFormAlt ( "aname" , "value" ) . TrimEnd ( '.' ) ;
2022-01-23 18:22:17 +05:30
2025-02-15 12:51:16 +05:30
newRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , ttl , new DnsANAMERecordData ( aname ) ) ;
}
break ;
2022-01-23 18:22:17 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . FWD :
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
DnsTransportProtocol protocol = request . GetQueryOrFormEnum ( "protocol" , DnsTransportProtocol . Udp ) ;
string forwarder = request . GetQueryOrFormAlt ( "forwarder" , "value" ) ;
bool dnssecValidation = request . GetQueryOrForm ( "dnssecValidation" , bool . Parse , false ) ;
DnsForwarderRecordProxyType proxyType = DnsForwarderRecordProxyType . DefaultProxy ;
string proxyAddress = null ;
ushort proxyPort = 0 ;
string proxyUsername = null ;
string proxyPassword = null ;
if ( ! forwarder . Equals ( "this-server" ) )
2022-04-30 16:19:02 +05:30
{
2025-02-15 12:51:16 +05:30
proxyType = request . GetQueryOrFormEnum ( "proxyType" , DnsForwarderRecordProxyType . DefaultProxy ) ;
switch ( proxyType )
{
case DnsForwarderRecordProxyType . Http :
case DnsForwarderRecordProxyType . Socks5 :
proxyAddress = request . GetQueryOrForm ( "proxyAddress" ) ;
proxyPort = request . GetQueryOrForm ( "proxyPort" , ushort . Parse ) ;
proxyUsername = request . QueryOrForm ( "proxyUsername" ) ;
proxyPassword = request . QueryOrForm ( "proxyPassword" ) ;
break ;
}
2022-04-30 16:19:02 +05:30
}
2022-01-23 18:22:17 +05:30
2025-02-15 12:51:16 +05:30
byte priority = request . GetQueryOrForm ( "forwarderPriority" , byte . Parse , byte . MinValue ) ;
2022-01-23 18:22:17 +05:30
2025-02-15 12:51:16 +05:30
if ( protocol = = DnsTransportProtocol . Quic )
DnsWebService . ValidateQuicSupport ( ) ;
2022-01-23 18:22:17 +05:30
2025-02-15 12:51:16 +05:30
newRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , 0 , new DnsForwarderRecordData ( protocol , forwarder , dnssecValidation , proxyType , proxyAddress , proxyPort , proxyUsername , proxyPassword , priority ) ) ;
2022-04-30 16:19:02 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
2022-01-23 18:22:17 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . APP :
{
if ( ! overwrite )
{
IReadOnlyList < DnsResourceRecord > existingRecords = _dnsWebService . _dnsServer . AuthZoneManager . GetRecords ( zoneInfo . Name , domain , type ) ;
if ( existingRecords . Count > 0 )
throw new DnsWebServiceException ( "Record already exists. Use overwrite option if you wish to overwrite existing record." ) ;
}
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
string appName = request . GetQueryOrFormAlt ( "appName" , "value" ) ;
string classPath = request . GetQueryOrForm ( "classPath" ) ;
string recordData = request . GetQueryOrForm ( "recordData" , "" ) ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
newRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , ttl , new DnsApplicationRecordData ( appName , classPath , recordData ) ) ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
overwrite = true ; //force SetRecord
}
break ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
default :
{
string strRData = request . GetQueryOrForm ( "rdata" ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
byte [ ] rdata ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( strRData . Contains ( ':' ) )
rdata = strRData . ParseColonHexString ( ) ;
else
rdata = Convert . FromHexString ( strRData ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
newRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , ttl , DnsResourceRecord . ReadRecordDataFrom ( type , rdata ) ) ;
}
break ;
}
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
//update record info
GenericRecordInfo recordInfo = newRecord . GetAuthGenericRecordInfo ( ) ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
recordInfo . LastModified = DateTime . UtcNow ;
recordInfo . ExpiryTtl = expiryTtl ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
if ( ! string . IsNullOrEmpty ( comments ) )
recordInfo . Comments = comments ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
//add record
if ( overwrite )
2025-04-19 16:03:13 +05:30
{
2025-02-15 12:51:16 +05:30
_dnsWebService . _dnsServer . AuthZoneManager . SetRecord ( zoneInfo . Name , newRecord ) ;
2025-04-19 16:03:13 +05:30
}
2025-02-15 12:51:16 +05:30
else
2025-04-19 16:03:13 +05:30
{
if ( ! _dnsWebService . _dnsServer . AuthZoneManager . AddRecord ( zoneInfo . Name , newRecord ) )
throw new DnsWebServiceException ( "Cannot add record: record already exists." ) ;
}
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
//additional processing
if ( ( type = = DnsResourceRecordType . A ) | | ( type = = DnsResourceRecordType . AAAA ) )
{
bool updateSvcbHints = request . GetQueryOrForm ( "updateSvcbHints" , bool . Parse , false ) ;
if ( updateSvcbHints )
UpdateSvcbAutoHints ( zoneInfo . Name , domain , type = = DnsResourceRecordType . A , type = = DnsResourceRecordType . AAAA ) ;
}
2023-01-01 18:39:46 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _log . Write ( context . GetRemoteEndPoint ( _dnsWebService . _webServiceRealIpHeader ) , "[" + session . User . Username + "] New record was added to " + zoneInfo . TypeName + " zone '" + zoneInfo . DisplayName + "' successfully {record: " + newRecord . ToString ( ) + "}" ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
//save zone
_dnsWebService . _dnsServer . AuthZoneManager . SaveZoneFile ( zoneInfo . Name ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
Utf8JsonWriter jsonWriter = context . GetCurrentJsonWriter ( ) ;
2023-02-05 16:35:08 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WritePropertyName ( "zone" ) ;
WriteZoneInfoAsJson ( zoneInfo , jsonWriter ) ;
2023-02-05 16:35:08 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WritePropertyName ( "addedRecord" ) ;
WriteRecordAsJson ( newRecord , jsonWriter , true , null ) ;
}
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
public void GetRecords ( HttpContext context )
2023-04-23 16:34:17 +05:30
{
2025-02-15 12:51:16 +05:30
HttpRequest request = context . Request ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
string domain = request . GetQueryOrForm ( "domain" ) . TrimEnd ( '.' ) ;
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . IsDomainNameUnicode ( domain ) )
domain = DnsClient . ConvertDomainNameToAscii ( domain ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
string zoneName = request . QueryOrForm ( "zone" ) ;
if ( zoneName is not null )
{
zoneName = zoneName . TrimEnd ( '.' ) ;
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . IsDomainNameUnicode ( zoneName ) )
zoneName = DnsClient . ConvertDomainNameToAscii ( zoneName ) ;
}
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
AuthZoneInfo zoneInfo = _dnsWebService . _dnsServer . AuthZoneManager . FindAuthZoneInfo ( string . IsNullOrEmpty ( zoneName ) ? domain : zoneName ) ;
if ( zoneInfo is null )
throw new DnsWebServiceException ( "No such zone was found: " + domain ) ;
2023-02-05 16:35:08 +05:30
2025-02-15 12:51:16 +05:30
UserSession session = context . GetCurrentSession ( ) ;
2023-02-05 16:35:08 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , zoneInfo . Name , session . User , PermissionFlag . View ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2023-02-05 16:35:08 +05:30
2025-02-15 12:51:16 +05:30
bool listZone = request . GetQueryOrForm ( "listZone" , bool . Parse , false ) ;
2023-01-01 18:39:46 +05:30
2025-02-15 12:51:16 +05:30
List < DnsResourceRecord > records = new List < DnsResourceRecord > ( ) ;
2022-04-23 18:03:17 +05:30
2025-02-15 12:51:16 +05:30
if ( listZone )
_dnsWebService . _dnsServer . AuthZoneManager . ListAllZoneRecords ( zoneInfo . Name , records ) ;
else
_dnsWebService . _dnsServer . AuthZoneManager . ListAllRecords ( zoneInfo . Name , domain , records ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
Utf8JsonWriter jsonWriter = context . GetCurrentJsonWriter ( ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WritePropertyName ( "zone" ) ;
WriteZoneInfoAsJson ( zoneInfo , jsonWriter ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
WriteRecordsAsJson ( records , jsonWriter , true , zoneInfo ) ;
}
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
public void DeleteRecord ( HttpContext context )
2023-04-23 16:34:17 +05:30
{
2025-02-15 12:51:16 +05:30
HttpRequest request = context . Request ;
2022-03-12 15:53:15 +05:30
2025-02-15 12:51:16 +05:30
string domain = request . GetQueryOrForm ( "domain" ) . TrimEnd ( '.' ) ;
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . IsDomainNameUnicode ( domain ) )
domain = DnsClient . ConvertDomainNameToAscii ( domain ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
string zoneName = request . QueryOrForm ( "zone" ) ;
if ( zoneName is not null )
{
zoneName = zoneName . TrimEnd ( '.' ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . IsDomainNameUnicode ( zoneName ) )
zoneName = DnsClient . ConvertDomainNameToAscii ( zoneName ) ;
}
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
AuthZoneInfo zoneInfo = _dnsWebService . _dnsServer . AuthZoneManager . FindAuthZoneInfo ( string . IsNullOrEmpty ( zoneName ) ? domain : zoneName ) ;
if ( zoneInfo is null )
throw new DnsWebServiceException ( "No such zone was found: " + domain ) ;
2022-01-23 18:22:17 +05:30
2025-02-15 12:51:16 +05:30
if ( zoneInfo . Internal )
throw new DnsWebServiceException ( "Access was denied to manage internal DNS Server zone." ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
UserSession session = context . GetCurrentSession ( ) ;
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , zoneInfo . Name , session . User , PermissionFlag . Delete ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
DnsResourceRecordType type = request . GetQueryOrFormEnum < DnsResourceRecordType > ( "type" ) ;
switch ( type )
{
case DnsResourceRecordType . A :
case DnsResourceRecordType . AAAA :
2021-09-18 19:02:40 +05:30
{
2025-02-15 12:51:16 +05:30
IPAddress ipAddress = IPAddress . Parse ( request . GetQueryOrFormAlt ( "ipAddress" , "value" ) ) ;
if ( type = = DnsResourceRecordType . A )
2025-03-29 18:58:25 +05:30
{
if ( ! _dnsWebService . _dnsServer . AuthZoneManager . DeleteRecord ( zoneInfo . Name , domain , type , new DnsARecordData ( ipAddress ) ) )
2025-03-31 19:36:23 +05:30
throw new DnsWebServiceException ( "Cannot delete record: no such record exists." ) ;
2025-03-29 18:58:25 +05:30
}
2025-02-15 12:51:16 +05:30
else
2025-03-29 18:58:25 +05:30
{
if ( ! _dnsWebService . _dnsServer . AuthZoneManager . DeleteRecord ( zoneInfo . Name , domain , type , new DnsAAAARecordData ( ipAddress ) ) )
2025-03-31 19:36:23 +05:30
throw new DnsWebServiceException ( "Cannot delete record: no such record exists." ) ;
2025-03-29 18:58:25 +05:30
}
2025-02-15 12:51:16 +05:30
string ptrDomain = Zone . GetReverseZone ( ipAddress , type = = DnsResourceRecordType . A ? 32 : 128 ) ;
AuthZoneInfo reverseZoneInfo = _dnsWebService . _dnsServer . AuthZoneManager . FindAuthZoneInfo ( ptrDomain ) ;
if ( ( reverseZoneInfo is not null ) & & ! reverseZoneInfo . Internal & & ( ( reverseZoneInfo . Type = = AuthZoneType . Primary ) | | ( reverseZoneInfo . Type = = AuthZoneType . Forwarder ) ) )
2021-09-18 19:02:40 +05:30
{
2025-02-15 12:51:16 +05:30
IReadOnlyList < DnsResourceRecord > ptrRecords = _dnsWebService . _dnsServer . AuthZoneManager . GetRecords ( reverseZoneInfo . Name , ptrDomain , DnsResourceRecordType . PTR ) ;
if ( ptrRecords . Count > 0 )
2021-09-18 19:02:40 +05:30
{
2025-02-15 12:51:16 +05:30
foreach ( DnsResourceRecord ptrRecord in ptrRecords )
2021-09-18 19:02:40 +05:30
{
2025-02-15 12:51:16 +05:30
if ( ( ptrRecord . RDATA as DnsPTRRecordData ) . Domain . Equals ( domain , StringComparison . OrdinalIgnoreCase ) )
{
//delete PTR record and save reverse zone
_dnsWebService . _dnsServer . AuthZoneManager . DeleteRecord ( reverseZoneInfo . Name , ptrDomain , DnsResourceRecordType . PTR , ptrRecord . RDATA ) ;
_dnsWebService . _dnsServer . AuthZoneManager . SaveZoneFile ( reverseZoneInfo . Name ) ;
break ;
}
2021-09-18 19:02:40 +05:30
}
}
}
2025-02-15 12:51:16 +05:30
bool updateSvcbHints = request . GetQueryOrForm ( "updateSvcbHints" , bool . Parse , false ) ;
if ( updateSvcbHints )
UpdateSvcbAutoHints ( zoneInfo . Name , domain , type = = DnsResourceRecordType . A , type = = DnsResourceRecordType . AAAA ) ;
2021-09-18 19:02:40 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
2024-06-01 19:25:07 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . NS :
{
string nameServer = request . GetQueryOrFormAlt ( "nameServer" , "value" ) . TrimEnd ( '.' ) ;
2021-09-18 19:02:40 +05:30
2025-03-29 18:58:25 +05:30
if ( ! _dnsWebService . _dnsServer . AuthZoneManager . DeleteRecord ( zoneInfo . Name , domain , type , new DnsNSRecordData ( nameServer , false ) ) )
2025-03-31 19:36:23 +05:30
throw new DnsWebServiceException ( "Cannot delete record: no such record exists." ) ;
2025-02-15 12:51:16 +05:30
}
break ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . CNAME :
2025-03-29 18:58:25 +05:30
if ( ! _dnsWebService . _dnsServer . AuthZoneManager . DeleteRecords ( zoneInfo . Name , domain , type ) )
2025-03-31 19:36:23 +05:30
throw new DnsWebServiceException ( "Cannot delete record: no such record exists." ) ;
2025-03-29 18:58:25 +05:30
2025-02-15 12:51:16 +05:30
break ;
case DnsResourceRecordType . PTR :
{
string ptrName = request . GetQueryOrFormAlt ( "ptrName" , "value" ) . TrimEnd ( '.' ) ;
2021-09-18 19:02:40 +05:30
2025-03-29 18:58:25 +05:30
if ( ! _dnsWebService . _dnsServer . AuthZoneManager . DeleteRecord ( zoneInfo . Name , domain , type , new DnsPTRRecordData ( ptrName ) ) )
2025-03-31 19:36:23 +05:30
throw new DnsWebServiceException ( "Cannot delete record: no such record exists." ) ;
2025-02-15 12:51:16 +05:30
}
break ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . MX :
{
ushort preference = request . GetQueryOrForm ( "preference" , ushort . Parse ) ;
string exchange = request . GetQueryOrFormAlt ( "exchange" , "value" ) . TrimEnd ( '.' ) ;
2022-03-06 16:56:54 +05:30
2025-03-29 18:58:25 +05:30
if ( ! _dnsWebService . _dnsServer . AuthZoneManager . DeleteRecord ( zoneInfo . Name , domain , type , new DnsMXRecordData ( preference , exchange ) ) )
2025-03-31 19:36:23 +05:30
throw new DnsWebServiceException ( "Cannot delete record: no such record exists." ) ;
2025-02-15 12:51:16 +05:30
}
break ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . TXT :
{
string text = request . GetQueryOrFormAlt ( "text" , "value" ) ;
bool splitText = request . GetQueryOrForm ( "splitText" , bool . Parse , false ) ;
2022-03-06 16:56:54 +05:30
2025-03-29 18:58:25 +05:30
if ( ! _dnsWebService . _dnsServer . AuthZoneManager . DeleteRecord ( zoneInfo . Name , domain , type , splitText ? new DnsTXTRecordData ( DecodeCharacterStrings ( text ) ) : new DnsTXTRecordData ( text ) ) )
2025-03-31 19:36:23 +05:30
throw new DnsWebServiceException ( "Cannot delete record: no such record exists." ) ;
2025-02-15 12:51:16 +05:30
}
break ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . RP :
{
string mailbox = request . GetQueryOrForm ( "mailbox" , "" ) . TrimEnd ( '.' ) ;
string txtDomain = request . GetQueryOrForm ( "txtDomain" , "" ) . TrimEnd ( '.' ) ;
2022-03-06 16:56:54 +05:30
2025-03-29 18:58:25 +05:30
if ( ! _dnsWebService . _dnsServer . AuthZoneManager . DeleteRecord ( zoneInfo . Name , domain , type , new DnsRPRecordData ( mailbox , txtDomain ) ) )
2025-03-31 19:36:23 +05:30
throw new DnsWebServiceException ( "Cannot delete record: no such record exists." ) ;
2025-02-15 12:51:16 +05:30
}
break ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . SRV :
{
ushort priority = request . GetQueryOrForm ( "priority" , ushort . Parse ) ;
ushort weight = request . GetQueryOrForm ( "weight" , ushort . Parse ) ;
ushort port = request . GetQueryOrForm ( "port" , ushort . Parse ) ;
string target = request . GetQueryOrFormAlt ( "target" , "value" ) . TrimEnd ( '.' ) ;
2024-09-15 15:14:12 +05:30
2025-03-29 18:58:25 +05:30
if ( ! _dnsWebService . _dnsServer . AuthZoneManager . DeleteRecord ( zoneInfo . Name , domain , type , new DnsSRVRecordData ( priority , weight , port , target ) ) )
2025-03-31 19:36:23 +05:30
throw new DnsWebServiceException ( "Cannot delete record: no such record exists." ) ;
2025-02-15 12:51:16 +05:30
}
break ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . NAPTR :
{
ushort order = request . GetQueryOrForm ( "naptrOrder" , ushort . Parse ) ;
ushort preference = request . GetQueryOrForm ( "naptrPreference" , ushort . Parse ) ;
string flags = request . GetQueryOrForm ( "naptrFlags" , "" ) ;
string services = request . GetQueryOrForm ( "naptrServices" , "" ) ;
string regexp = request . GetQueryOrForm ( "naptrRegexp" , "" ) ;
string replacement = request . GetQueryOrForm ( "naptrReplacement" , "" ) . TrimEnd ( '.' ) ;
2025-03-29 18:58:25 +05:30
if ( ! _dnsWebService . _dnsServer . AuthZoneManager . DeleteRecord ( zoneInfo . Name , domain , type , new DnsNAPTRRecordData ( order , preference , flags , services , regexp , replacement ) ) )
2025-03-31 19:36:23 +05:30
throw new DnsWebServiceException ( "Cannot delete record: no such record exists." ) ;
2025-02-15 12:51:16 +05:30
}
break ;
2022-05-28 12:25:54 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . DNAME :
2025-03-29 18:58:25 +05:30
if ( ! _dnsWebService . _dnsServer . AuthZoneManager . DeleteRecords ( zoneInfo . Name , domain , type ) )
2025-03-31 19:36:23 +05:30
throw new DnsWebServiceException ( "Cannot delete record: no such record exists." ) ;
2025-03-29 18:58:25 +05:30
2025-02-15 12:51:16 +05:30
break ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . DS :
{
ushort keyTag = request . GetQueryOrForm ( "keyTag" , ushort . Parse ) ;
DnssecAlgorithm algorithm = Enum . Parse < DnssecAlgorithm > ( request . GetQueryOrForm ( "algorithm" ) . Replace ( '-' , '_' ) , true ) ;
DnssecDigestType digestType = Enum . Parse < DnssecDigestType > ( request . GetQueryOrForm ( "digestType" ) . Replace ( '-' , '_' ) , true ) ;
byte [ ] digest = Convert . FromHexString ( request . GetQueryOrFormAlt ( "digest" , "value" ) ) ;
2024-05-19 16:40:40 +05:30
2025-03-29 18:58:25 +05:30
if ( ! _dnsWebService . _dnsServer . AuthZoneManager . DeleteRecord ( zoneInfo . Name , domain , type , new DnsDSRecordData ( keyTag , algorithm , digestType , digest ) ) )
2025-03-31 19:36:23 +05:30
throw new DnsWebServiceException ( "Cannot delete record: no such record exists." ) ;
2025-02-15 12:51:16 +05:30
}
break ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . SSHFP :
{
DnsSSHFPAlgorithm sshfpAlgorithm = request . GetQueryOrFormEnum < DnsSSHFPAlgorithm > ( "sshfpAlgorithm" ) ;
DnsSSHFPFingerprintType sshfpFingerprintType = request . GetQueryOrFormEnum < DnsSSHFPFingerprintType > ( "sshfpFingerprintType" ) ;
byte [ ] sshfpFingerprint = request . GetQueryOrForm ( "sshfpFingerprint" , Convert . FromHexString ) ;
2022-03-06 16:56:54 +05:30
2025-03-29 18:58:25 +05:30
if ( ! _dnsWebService . _dnsServer . AuthZoneManager . DeleteRecord ( zoneInfo . Name , domain , type , new DnsSSHFPRecordData ( sshfpAlgorithm , sshfpFingerprintType , sshfpFingerprint ) ) )
2025-03-31 19:36:23 +05:30
throw new DnsWebServiceException ( "Cannot delete record: no such record exists." ) ;
2025-02-15 12:51:16 +05:30
}
break ;
2022-02-27 18:23:41 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . TLSA :
{
DnsTLSACertificateUsage tlsaCertificateUsage = Enum . Parse < DnsTLSACertificateUsage > ( request . GetQueryOrForm ( "tlsaCertificateUsage" ) . Replace ( '-' , '_' ) , true ) ;
DnsTLSASelector tlsaSelector = request . GetQueryOrFormEnum < DnsTLSASelector > ( "tlsaSelector" ) ;
DnsTLSAMatchingType tlsaMatchingType = Enum . Parse < DnsTLSAMatchingType > ( request . GetQueryOrForm ( "tlsaMatchingType" ) . Replace ( '-' , '_' ) , true ) ;
string tlsaCertificateAssociationData = request . GetQueryOrForm ( "tlsaCertificateAssociationData" ) ;
2022-11-12 15:12:44 +05:30
2025-03-29 18:58:25 +05:30
if ( ! _dnsWebService . _dnsServer . AuthZoneManager . DeleteRecord ( zoneInfo . Name , domain , type , new DnsTLSARecordData ( tlsaCertificateUsage , tlsaSelector , tlsaMatchingType , tlsaCertificateAssociationData ) ) )
2025-03-31 19:36:23 +05:30
throw new DnsWebServiceException ( "Cannot delete record: no such record exists." ) ;
2025-02-15 12:51:16 +05:30
}
break ;
2022-11-12 15:12:44 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . SVCB :
case DnsResourceRecordType . HTTPS :
{
ushort svcPriority = request . GetQueryOrForm ( "svcPriority" , ushort . Parse ) ;
string targetName = request . GetQueryOrForm ( "svcTargetName" ) . TrimEnd ( '.' ) ;
string strSvcParams = request . GetQueryOrForm ( "svcParams" ) ;
2022-11-12 15:12:44 +05:30
2025-02-15 12:51:16 +05:30
Dictionary < DnsSvcParamKey , DnsSvcParamValue > svcParams ;
2022-11-12 15:12:44 +05:30
2025-02-15 12:51:16 +05:30
if ( strSvcParams . Equals ( "false" , StringComparison . OrdinalIgnoreCase ) )
{
svcParams = new Dictionary < DnsSvcParamKey , DnsSvcParamValue > ( 0 ) ;
}
else
{
string [ ] strSvcParamsParts = strSvcParams . Split ( '|' ) ;
svcParams = new Dictionary < DnsSvcParamKey , DnsSvcParamValue > ( strSvcParamsParts . Length / 2 ) ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
for ( int i = 0 ; i < strSvcParamsParts . Length ; i + = 2 )
{
DnsSvcParamKey svcParamKey = Enum . Parse < DnsSvcParamKey > ( strSvcParamsParts [ i ] . Replace ( '-' , '_' ) , true ) ;
DnsSvcParamValue svcParamValue = DnsSvcParamValue . Parse ( svcParamKey , strSvcParamsParts [ i + 1 ] ) ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
svcParams . Add ( svcParamKey , svcParamValue ) ;
}
}
2025-03-29 18:58:25 +05:30
if ( ! _dnsWebService . _dnsServer . AuthZoneManager . DeleteRecord ( zoneInfo . Name , domain , type , new DnsSVCBRecordData ( svcPriority , targetName , svcParams ) ) )
2025-03-31 19:36:23 +05:30
throw new DnsWebServiceException ( "Cannot delete record: no such record exists." ) ;
2023-05-20 18:40:44 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . URI :
{
ushort priority = request . GetQueryOrForm ( "uriPriority" , ushort . Parse ) ;
ushort weight = request . GetQueryOrForm ( "uriWeight" , ushort . Parse ) ;
Uri uri = request . GetQueryOrForm ( "uri" , delegate ( string value ) { return new Uri ( value ) ; } ) ;
2023-05-20 18:40:44 +05:30
2025-03-29 18:58:25 +05:30
if ( ! _dnsWebService . _dnsServer . AuthZoneManager . DeleteRecord ( zoneInfo . Name , domain , type , new DnsURIRecordData ( priority , weight , uri ) ) )
2025-03-31 19:36:23 +05:30
throw new DnsWebServiceException ( "Cannot delete record: no such record exists." ) ;
2023-05-20 18:40:44 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . CAA :
{
byte flags = request . GetQueryOrForm ( "flags" , byte . Parse ) ;
string tag = request . GetQueryOrForm ( "tag" ) ;
string value = request . GetQueryOrForm ( "value" ) ;
2023-07-02 15:47:55 +05:30
2025-03-29 18:58:25 +05:30
if ( ! _dnsWebService . _dnsServer . AuthZoneManager . DeleteRecord ( zoneInfo . Name , domain , type , new DnsCAARecordData ( flags , tag , value ) ) )
2025-03-31 19:36:23 +05:30
throw new DnsWebServiceException ( "Cannot delete record: no such record exists." ) ;
2025-02-15 12:51:16 +05:30
}
break ;
2023-07-02 15:47:55 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . ANAME :
{
string aname = request . GetQueryOrFormAlt ( "aname" , "value" ) . TrimEnd ( '.' ) ;
2021-09-18 19:02:40 +05:30
2025-03-29 18:58:25 +05:30
if ( ! _dnsWebService . _dnsServer . AuthZoneManager . DeleteRecord ( zoneInfo . Name , domain , type , new DnsANAMERecordData ( aname ) ) )
2025-03-31 19:36:23 +05:30
throw new DnsWebServiceException ( "Cannot delete record: no such record exists." ) ;
2025-02-15 12:51:16 +05:30
}
break ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . FWD :
{
DnsTransportProtocol protocol = request . GetQueryOrFormEnum ( "protocol" , DnsTransportProtocol . Udp ) ;
string forwarder = request . GetQueryOrFormAlt ( "forwarder" , "value" ) ;
2022-03-06 16:56:54 +05:30
2025-03-29 18:58:25 +05:30
if ( ! _dnsWebService . _dnsServer . AuthZoneManager . DeleteRecord ( zoneInfo . Name , domain , type , DnsForwarderRecordData . CreatePartialRecordData ( protocol , forwarder ) ) )
2025-03-31 19:36:23 +05:30
throw new DnsWebServiceException ( "Cannot delete record: no such record exists." ) ;
2025-02-15 12:51:16 +05:30
}
break ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . APP :
2025-03-29 18:58:25 +05:30
if ( ! _dnsWebService . _dnsServer . AuthZoneManager . DeleteRecords ( zoneInfo . Name , domain , type ) )
2025-03-31 19:36:23 +05:30
throw new DnsWebServiceException ( "Cannot delete record: no such record exists." ) ;
2025-03-29 18:58:25 +05:30
2025-02-15 12:51:16 +05:30
break ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
default :
{
string strRData = request . GetQueryOrForm ( "rdata" , string . Empty ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
byte [ ] rdata ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
if ( strRData . Contains ( ':' ) )
rdata = strRData . ParseColonHexString ( ) ;
else
rdata = Convert . FromHexString ( strRData ) ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _dnsServer . AuthZoneManager . DeleteRecord ( zoneInfo . Name , domain , type , new DnsUnknownRecordData ( rdata ) ) )
2025-03-31 19:36:23 +05:30
throw new DnsWebServiceException ( "Cannot delete record: no such record exists." ) ;
2025-02-15 12:51:16 +05:30
}
break ;
}
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _log . Write ( context . GetRemoteEndPoint ( _dnsWebService . _webServiceRealIpHeader ) , "[" + session . User . Username + "] Record was deleted from " + zoneInfo . TypeName + " zone '" + zoneInfo . DisplayName + "' successfully {domain: " + domain + "; type: " + type + ";}" ) ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _dnsServer . AuthZoneManager . SaveZoneFile ( zoneInfo . Name ) ;
2021-09-18 19:02:40 +05:30
}
2025-02-15 12:51:16 +05:30
public void UpdateRecord ( HttpContext context )
{
HttpRequest request = context . Request ;
string domain = request . GetQueryOrForm ( "domain" ) . TrimEnd ( '.' ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . IsDomainNameUnicode ( domain ) )
domain = DnsClient . ConvertDomainNameToAscii ( domain ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
string zoneName = request . QueryOrForm ( "zone" ) ;
if ( zoneName is not null )
{
zoneName = zoneName . TrimEnd ( '.' ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( DnsClient . IsDomainNameUnicode ( zoneName ) )
zoneName = DnsClient . ConvertDomainNameToAscii ( zoneName ) ;
}
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
AuthZoneInfo zoneInfo = _dnsWebService . _dnsServer . AuthZoneManager . FindAuthZoneInfo ( string . IsNullOrEmpty ( zoneName ) ? domain : zoneName ) ;
if ( zoneInfo is null )
throw new DnsWebServiceException ( "No such zone was found: " + domain ) ;
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
if ( zoneInfo . Internal )
throw new DnsWebServiceException ( "Access was denied to manage internal DNS Server zone." ) ;
2022-03-12 15:53:15 +05:30
2025-02-15 12:51:16 +05:30
UserSession session = context . GetCurrentSession ( ) ;
2023-04-23 16:34:17 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , zoneInfo . Name , session . User , PermissionFlag . Modify ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
string newDomain = request . GetQueryOrForm ( "newDomain" , domain ) . TrimEnd ( '.' ) ;
2025-03-29 18:58:25 +05:30
uint ttl = request . GetQueryOrForm ( "ttl" , ZoneFile . ParseTtl , _defaultRecordTtl ) ;
2025-02-15 12:51:16 +05:30
bool disable = request . GetQueryOrForm ( "disable" , bool . Parse , false ) ;
string comments = request . QueryOrForm ( "comments" ) ;
2025-03-31 19:36:23 +05:30
uint expiryTtl = request . GetQueryOrForm ( "expiryTtl" , ZoneFile . ParseTtl , 0 u ) ;
2025-02-15 12:51:16 +05:30
DnsResourceRecordType type = request . GetQueryOrFormEnum < DnsResourceRecordType > ( "type" ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
DnsResourceRecord oldRecord = null ;
DnsResourceRecord newRecord ;
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
switch ( type )
{
case DnsResourceRecordType . A :
case DnsResourceRecordType . AAAA :
{
IPAddress ipAddress = IPAddress . Parse ( request . GetQueryOrFormAlt ( "ipAddress" , "value" ) ) ;
IPAddress newIpAddress = IPAddress . Parse ( request . GetQueryOrFormAlt ( "newIpAddress" , "newValue" , ipAddress . ToString ( ) ) ) ;
2022-01-23 18:22:17 +05:30
2025-02-15 12:51:16 +05:30
bool ptr = request . GetQueryOrForm ( "ptr" , bool . Parse , false ) ;
if ( ptr )
{
string newPtrDomain = Zone . GetReverseZone ( newIpAddress , type = = DnsResourceRecordType . A ? 32 : 128 ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
AuthZoneInfo newReverseZoneInfo = _dnsWebService . _dnsServer . AuthZoneManager . FindAuthZoneInfo ( newPtrDomain ) ;
if ( newReverseZoneInfo is null )
{
bool createPtrZone = request . GetQueryOrForm ( "createPtrZone" , bool . Parse , false ) ;
if ( ! createPtrZone )
throw new DnsWebServiceException ( "No reverse zone available to add PTR record." ) ;
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
string ptrZone = Zone . GetReverseZone ( newIpAddress , type = = DnsResourceRecordType . A ? 24 : 64 ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
newReverseZoneInfo = _dnsWebService . _dnsServer . AuthZoneManager . CreatePrimaryZone ( ptrZone ) ;
if ( newReverseZoneInfo is null )
throw new DnsWebServiceException ( "Failed to create reverse zone to add PTR record: " + ptrZone ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
//set permissions
_dnsWebService . _authManager . SetPermission ( PermissionSection . Zones , newReverseZoneInfo . Name , session . User , PermissionFlag . ViewModifyDelete ) ;
_dnsWebService . _authManager . SetPermission ( PermissionSection . Zones , newReverseZoneInfo . Name , _dnsWebService . _authManager . GetGroup ( Group . ADMINISTRATORS ) , PermissionFlag . ViewModifyDelete ) ;
_dnsWebService . _authManager . SetPermission ( PermissionSection . Zones , newReverseZoneInfo . Name , _dnsWebService . _authManager . GetGroup ( Group . DNS_ADMINISTRATORS ) , PermissionFlag . ViewModifyDelete ) ;
_dnsWebService . _authManager . SaveConfigFile ( ) ;
}
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( newReverseZoneInfo . Internal )
throw new DnsWebServiceException ( "Reverse zone '" + newReverseZoneInfo . DisplayName + "' is an internal zone." ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( ( newReverseZoneInfo . Type ! = AuthZoneType . Primary ) & & ( newReverseZoneInfo . Type ! = AuthZoneType . Forwarder ) )
throw new DnsWebServiceException ( "Reverse zone '" + newReverseZoneInfo . DisplayName + "' is not a primary or forwarder zone." ) ;
2022-09-18 18:00:21 +05:30
2025-02-15 12:51:16 +05:30
string oldPtrDomain = Zone . GetReverseZone ( ipAddress , type = = DnsResourceRecordType . A ? 32 : 128 ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
AuthZoneInfo oldReverseZoneInfo = _dnsWebService . _dnsServer . AuthZoneManager . FindAuthZoneInfo ( oldPtrDomain ) ;
if ( ( oldReverseZoneInfo is not null ) & & ! oldReverseZoneInfo . Internal & & ( ( oldReverseZoneInfo . Type = = AuthZoneType . Primary ) | | ( oldReverseZoneInfo . Type = = AuthZoneType . Forwarder ) ) )
{
//delete old PTR record if any and save old reverse zone
_dnsWebService . _dnsServer . AuthZoneManager . DeleteRecords ( oldReverseZoneInfo . Name , oldPtrDomain , DnsResourceRecordType . PTR ) ;
_dnsWebService . _dnsServer . AuthZoneManager . SaveZoneFile ( oldReverseZoneInfo . Name ) ;
}
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
//add new PTR record and save reverse zone
DnsResourceRecord ptrRecord = new DnsResourceRecord ( newPtrDomain , DnsResourceRecordType . PTR , DnsClass . IN , ttl , new DnsPTRRecordData ( domain ) ) ;
ptrRecord . GetAuthGenericRecordInfo ( ) . LastModified = DateTime . UtcNow ;
ptrRecord . GetAuthGenericRecordInfo ( ) . ExpiryTtl = expiryTtl ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _dnsServer . AuthZoneManager . SetRecord ( newReverseZoneInfo . Name , ptrRecord ) ;
_dnsWebService . _dnsServer . AuthZoneManager . SaveZoneFile ( newReverseZoneInfo . Name ) ;
}
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( type = = DnsResourceRecordType . A )
2021-09-18 19:02:40 +05:30
{
2025-02-15 12:51:16 +05:30
oldRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , 0 , new DnsARecordData ( ipAddress ) ) ;
newRecord = new DnsResourceRecord ( newDomain , type , DnsClass . IN , ttl , new DnsARecordData ( newIpAddress ) ) ;
}
else
{
oldRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , 0 , new DnsAAAARecordData ( ipAddress ) ) ;
newRecord = new DnsResourceRecord ( newDomain , type , DnsClass . IN , ttl , new DnsAAAARecordData ( newIpAddress ) ) ;
2021-09-18 19:02:40 +05:30
}
}
2025-02-15 12:51:16 +05:30
break ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . NS :
2021-09-18 19:02:40 +05:30
{
2025-02-15 12:51:16 +05:30
string nameServer = request . GetQueryOrFormAlt ( "nameServer" , "value" ) . TrimEnd ( '.' ) ;
string newNameServer = request . GetQueryOrFormAlt ( "newNameServer" , "newValue" , nameServer ) . TrimEnd ( '.' ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
oldRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , 0 , new DnsNSRecordData ( nameServer ) ) ;
newRecord = new DnsResourceRecord ( newDomain , type , DnsClass . IN , ttl , new DnsNSRecordData ( newNameServer ) ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( request . TryGetQueryOrForm ( "glue" , out string glueAddresses ) )
{
if ( zoneInfo . Name . Equals ( newDomain , StringComparison . OrdinalIgnoreCase ) & & ( newNameServer . Equals ( newDomain , StringComparison . OrdinalIgnoreCase ) | | newNameServer . EndsWith ( "." + newDomain , StringComparison . OrdinalIgnoreCase ) ) )
throw new DnsWebServiceException ( "The zone's own NS records cannot have glue addresses. Please add separate A/AAAA records in the zone instead." ) ;
2024-11-23 13:14:04 +05:30
2025-02-15 12:51:16 +05:30
newRecord . SetGlueRecords ( glueAddresses ) ;
}
2024-11-23 13:14:04 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . CNAME :
{
string cname = request . GetQueryOrFormAlt ( "cname" , "value" ) . TrimEnd ( '.' ) ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
if ( cname . Equals ( newDomain , StringComparison . OrdinalIgnoreCase ) )
throw new DnsWebServiceException ( "CNAME domain name cannot be same as that of the record name." ) ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
oldRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , 0 , new DnsCNAMERecordData ( cname ) ) ;
newRecord = new DnsResourceRecord ( newDomain , type , DnsClass . IN , ttl , new DnsCNAMERecordData ( cname ) ) ;
}
break ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . SOA :
{
string primaryNameServer = request . GetQueryOrForm ( "primaryNameServer" ) . TrimEnd ( '.' ) ;
string responsiblePerson = request . GetQueryOrForm ( "responsiblePerson" ) . TrimEnd ( '.' ) ;
uint serial = request . GetQueryOrForm ( "serial" , uint . Parse ) ;
2025-03-31 19:36:23 +05:30
uint refresh = request . GetQueryOrForm ( "refresh" , ZoneFile . ParseTtl ) ;
uint retry = request . GetQueryOrForm ( "retry" , ZoneFile . ParseTtl ) ;
uint expire = request . GetQueryOrForm ( "expire" , ZoneFile . ParseTtl ) ;
uint minimum = request . GetQueryOrForm ( "minimum" , ZoneFile . ParseTtl ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
newRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , ttl , new DnsSOARecordData ( primaryNameServer , responsiblePerson , serial , refresh , retry , expire , minimum ) ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
switch ( zoneInfo . Type )
{
case AuthZoneType . Primary :
case AuthZoneType . Forwarder :
case AuthZoneType . Catalog :
{
if ( request . TryGetQueryOrForm ( "useSerialDateScheme" , bool . Parse , out bool useSerialDateScheme ) )
newRecord . GetAuthSOARecordInfo ( ) . UseSoaSerialDateScheme = useSerialDateScheme ;
}
break ;
}
2021-09-18 19:02:40 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . PTR :
{
string ptrName = request . GetQueryOrFormAlt ( "ptrName" , "value" ) . TrimEnd ( '.' ) ;
string newPtrName = request . GetQueryOrFormAlt ( "newPtrName" , "newValue" , ptrName ) . TrimEnd ( '.' ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
oldRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , 0 , new DnsPTRRecordData ( ptrName ) ) ;
newRecord = new DnsResourceRecord ( newDomain , type , DnsClass . IN , ttl , new DnsPTRRecordData ( newPtrName ) ) ;
}
break ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . MX :
{
ushort preference = request . GetQueryOrForm ( "preference" , ushort . Parse ) ;
ushort newPreference = request . GetQueryOrForm ( "newPreference" , ushort . Parse , preference ) ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
string exchange = request . GetQueryOrFormAlt ( "exchange" , "value" ) . TrimEnd ( '.' ) ;
string newExchange = request . GetQueryOrFormAlt ( "newExchange" , "newValue" , exchange ) . TrimEnd ( '.' ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
oldRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , 0 , new DnsMXRecordData ( preference , exchange ) ) ;
newRecord = new DnsResourceRecord ( newDomain , type , DnsClass . IN , ttl , new DnsMXRecordData ( newPreference , newExchange ) ) ;
}
break ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . TXT :
{
string text = request . GetQueryOrFormAlt ( "text" , "value" ) ;
string newText = request . GetQueryOrFormAlt ( "newText" , "newValue" , text ) ;
2024-05-19 16:40:40 +05:30
2025-02-15 12:51:16 +05:30
bool splitText = request . GetQueryOrForm ( "splitText" , bool . Parse , false ) ;
bool newSplitText = request . GetQueryOrForm ( "newSplitText" , bool . Parse , splitText ) ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
oldRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , 0 , splitText ? new DnsTXTRecordData ( DecodeCharacterStrings ( text ) ) : new DnsTXTRecordData ( text ) ) ;
newRecord = new DnsResourceRecord ( newDomain , type , DnsClass . IN , ttl , newSplitText ? new DnsTXTRecordData ( DecodeCharacterStrings ( newText ) ) : new DnsTXTRecordData ( newText ) ) ;
}
break ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . RP :
{
string mailbox = request . GetQueryOrForm ( "mailbox" , "" ) . TrimEnd ( '.' ) ;
string newMailbox = request . GetQueryOrForm ( "newMailbox" , mailbox ) . TrimEnd ( '.' ) ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
string txtDomain = request . GetQueryOrForm ( "txtDomain" , "" ) . TrimEnd ( '.' ) ;
string newTxtDomain = request . GetQueryOrForm ( "newTxtDomain" , txtDomain ) . TrimEnd ( '.' ) ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
oldRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , 0 , new DnsRPRecordData ( mailbox , txtDomain ) ) ;
newRecord = new DnsResourceRecord ( newDomain , type , DnsClass . IN , ttl , new DnsRPRecordData ( newMailbox , newTxtDomain ) ) ;
}
break ;
2022-05-28 12:25:54 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . SRV :
{
ushort priority = request . GetQueryOrForm ( "priority" , ushort . Parse ) ;
ushort newPriority = request . GetQueryOrForm ( "newPriority" , ushort . Parse , priority ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
ushort weight = request . GetQueryOrForm ( "weight" , ushort . Parse ) ;
ushort newWeight = request . GetQueryOrForm ( "newWeight" , ushort . Parse , weight ) ;
2022-05-28 12:25:54 +05:30
2025-02-15 12:51:16 +05:30
ushort port = request . GetQueryOrForm ( "port" , ushort . Parse ) ;
ushort newPort = request . GetQueryOrForm ( "newPort" , ushort . Parse , port ) ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
string target = request . GetQueryOrFormAlt ( "target" , "value" ) . TrimEnd ( '.' ) ;
string newTarget = request . GetQueryOrFormAlt ( "newTarget" , "newValue" , target ) . TrimEnd ( '.' ) ;
2024-05-19 16:40:40 +05:30
2025-02-15 12:51:16 +05:30
oldRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , 0 , new DnsSRVRecordData ( priority , weight , port , target ) ) ;
newRecord = new DnsResourceRecord ( newDomain , type , DnsClass . IN , ttl , new DnsSRVRecordData ( newPriority , newWeight , newPort , newTarget ) ) ;
}
break ;
2024-05-19 16:40:40 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . NAPTR :
{
ushort order = request . GetQueryOrForm ( "naptrOrder" , ushort . Parse ) ;
ushort newOrder = request . GetQueryOrForm ( "naptrNewOrder" , ushort . Parse , order ) ;
2024-05-19 16:40:40 +05:30
2025-02-15 12:51:16 +05:30
ushort preference = request . GetQueryOrForm ( "naptrPreference" , ushort . Parse ) ;
ushort newPreference = request . GetQueryOrForm ( "naptrNewPreference" , ushort . Parse , preference ) ;
2024-05-19 16:40:40 +05:30
2025-02-15 12:51:16 +05:30
string flags = request . GetQueryOrForm ( "naptrFlags" , "" ) ;
string newFlags = request . GetQueryOrForm ( "naptrNewFlags" , flags ) ;
2024-05-19 16:40:40 +05:30
2025-02-15 12:51:16 +05:30
string services = request . GetQueryOrForm ( "naptrServices" , "" ) ;
string newServices = request . GetQueryOrForm ( "naptrNewServices" , services ) ;
2024-05-19 16:40:40 +05:30
2025-02-15 12:51:16 +05:30
string regexp = request . GetQueryOrForm ( "naptrRegexp" , "" ) ;
string newRegexp = request . GetQueryOrForm ( "naptrNewRegexp" , regexp ) ;
2024-05-19 16:40:40 +05:30
2025-02-15 12:51:16 +05:30
string replacement = request . GetQueryOrForm ( "naptrReplacement" , "" ) . TrimEnd ( '.' ) ;
string newReplacement = request . GetQueryOrForm ( "naptrNewReplacement" , replacement ) . TrimEnd ( '.' ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
oldRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , 0 , new DnsNAPTRRecordData ( order , preference , flags , services , regexp , replacement ) ) ;
newRecord = new DnsResourceRecord ( newDomain , type , DnsClass . IN , ttl , new DnsNAPTRRecordData ( newOrder , newPreference , newFlags , newServices , newRegexp , newReplacement ) ) ;
}
break ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . DNAME :
{
string dname = request . GetQueryOrFormAlt ( "dname" , "value" ) . TrimEnd ( '.' ) ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
if ( dname . EndsWith ( "." + newDomain , StringComparison . OrdinalIgnoreCase ) )
throw new DnsWebServiceException ( "DNAME domain name cannot be a sub domain of the record name." ) ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
if ( dname . Equals ( newDomain , StringComparison . OrdinalIgnoreCase ) )
throw new DnsWebServiceException ( "DNAME domain name cannot be same as that of the record name." ) ;
2022-02-27 18:23:41 +05:30
2025-02-15 12:51:16 +05:30
oldRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , 0 , new DnsDNAMERecordData ( dname ) ) ;
newRecord = new DnsResourceRecord ( newDomain , type , DnsClass . IN , ttl , new DnsDNAMERecordData ( dname ) ) ;
}
break ;
2022-02-27 18:23:41 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . DS :
{
ushort keyTag = request . GetQueryOrForm ( "keyTag" , ushort . Parse ) ;
ushort newKeyTag = request . GetQueryOrForm ( "newKeyTag" , ushort . Parse , keyTag ) ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
DnssecAlgorithm algorithm = Enum . Parse < DnssecAlgorithm > ( request . GetQueryOrForm ( "algorithm" ) . Replace ( '-' , '_' ) , true ) ;
DnssecAlgorithm newAlgorithm = Enum . Parse < DnssecAlgorithm > ( request . GetQueryOrForm ( "newAlgorithm" , algorithm . ToString ( ) ) . Replace ( '-' , '_' ) , true ) ;
2022-02-27 18:23:41 +05:30
2025-02-15 12:51:16 +05:30
DnssecDigestType digestType = Enum . Parse < DnssecDigestType > ( request . GetQueryOrForm ( "digestType" ) . Replace ( '-' , '_' ) , true ) ;
DnssecDigestType newDigestType = Enum . Parse < DnssecDigestType > ( request . GetQueryOrForm ( "newDigestType" , digestType . ToString ( ) ) . Replace ( '-' , '_' ) , true ) ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
byte [ ] digest = request . GetQueryOrFormAlt ( "digest" , "value" , Convert . FromHexString ) ;
byte [ ] newDigest = request . GetQueryOrFormAlt ( "newDigest" , "newValue" , Convert . FromHexString , digest ) ;
2022-11-12 15:12:44 +05:30
2025-02-15 12:51:16 +05:30
oldRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , 0 , new DnsDSRecordData ( keyTag , algorithm , digestType , digest ) ) ;
newRecord = new DnsResourceRecord ( newDomain , type , DnsClass . IN , ttl , new DnsDSRecordData ( newKeyTag , newAlgorithm , newDigestType , newDigest ) ) ;
}
break ;
2022-11-12 15:12:44 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . SSHFP :
{
DnsSSHFPAlgorithm sshfpAlgorithm = request . GetQueryOrFormEnum < DnsSSHFPAlgorithm > ( "sshfpAlgorithm" ) ;
DnsSSHFPAlgorithm newSshfpAlgorithm = request . GetQueryOrFormEnum ( "newSshfpAlgorithm" , sshfpAlgorithm ) ;
2022-11-12 15:12:44 +05:30
2025-02-15 12:51:16 +05:30
DnsSSHFPFingerprintType sshfpFingerprintType = request . GetQueryOrFormEnum < DnsSSHFPFingerprintType > ( "sshfpFingerprintType" ) ;
DnsSSHFPFingerprintType newSshfpFingerprintType = request . GetQueryOrFormEnum ( "newSshfpFingerprintType" , sshfpFingerprintType ) ;
2022-11-12 15:12:44 +05:30
2025-02-15 12:51:16 +05:30
byte [ ] sshfpFingerprint = request . GetQueryOrForm ( "sshfpFingerprint" , Convert . FromHexString ) ;
byte [ ] newSshfpFingerprint = request . GetQueryOrForm ( "newSshfpFingerprint" , Convert . FromHexString , sshfpFingerprint ) ;
2022-11-12 15:12:44 +05:30
2025-02-15 12:51:16 +05:30
oldRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , 0 , new DnsSSHFPRecordData ( sshfpAlgorithm , sshfpFingerprintType , sshfpFingerprint ) ) ;
newRecord = new DnsResourceRecord ( newDomain , type , DnsClass . IN , ttl , new DnsSSHFPRecordData ( newSshfpAlgorithm , newSshfpFingerprintType , newSshfpFingerprint ) ) ;
}
break ;
2022-11-12 15:12:44 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . TLSA :
{
DnsTLSACertificateUsage tlsaCertificateUsage = Enum . Parse < DnsTLSACertificateUsage > ( request . GetQueryOrForm ( "tlsaCertificateUsage" ) . Replace ( '-' , '_' ) , true ) ;
DnsTLSACertificateUsage newTlsaCertificateUsage = Enum . Parse < DnsTLSACertificateUsage > ( request . GetQueryOrForm ( "newTlsaCertificateUsage" , tlsaCertificateUsage . ToString ( ) ) . Replace ( '-' , '_' ) , true ) ;
2022-11-12 15:12:44 +05:30
2025-02-15 12:51:16 +05:30
DnsTLSASelector tlsaSelector = request . GetQueryOrFormEnum < DnsTLSASelector > ( "tlsaSelector" ) ;
DnsTLSASelector newTlsaSelector = request . GetQueryOrFormEnum ( "newTlsaSelector" , tlsaSelector ) ;
2022-11-12 15:12:44 +05:30
2025-02-15 12:51:16 +05:30
DnsTLSAMatchingType tlsaMatchingType = Enum . Parse < DnsTLSAMatchingType > ( request . GetQueryOrForm ( "tlsaMatchingType" ) . Replace ( '-' , '_' ) , true ) ;
DnsTLSAMatchingType newTlsaMatchingType = Enum . Parse < DnsTLSAMatchingType > ( request . GetQueryOrForm ( "newTlsaMatchingType" , tlsaMatchingType . ToString ( ) ) . Replace ( '-' , '_' ) , true ) ;
2022-11-12 15:12:44 +05:30
2025-02-15 12:51:16 +05:30
string tlsaCertificateAssociationData = request . GetQueryOrForm ( "tlsaCertificateAssociationData" ) ;
string newTlsaCertificateAssociationData = request . GetQueryOrForm ( "newTlsaCertificateAssociationData" , tlsaCertificateAssociationData ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
oldRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , 0 , new DnsTLSARecordData ( tlsaCertificateUsage , tlsaSelector , tlsaMatchingType , tlsaCertificateAssociationData ) ) ;
newRecord = new DnsResourceRecord ( newDomain , type , DnsClass . IN , ttl , new DnsTLSARecordData ( newTlsaCertificateUsage , newTlsaSelector , newTlsaMatchingType , newTlsaCertificateAssociationData ) ) ;
}
break ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . SVCB :
case DnsResourceRecordType . HTTPS :
{
ushort svcPriority = request . GetQueryOrForm ( "svcPriority" , ushort . Parse ) ;
ushort newSvcPriority = request . GetQueryOrForm ( "newSvcPriority" , ushort . Parse , svcPriority ) ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
string targetName = request . GetQueryOrForm ( "svcTargetName" ) . TrimEnd ( '.' ) ;
string newTargetName = request . GetQueryOrForm ( "newSvcTargetName" , targetName ) . TrimEnd ( '.' ) ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
string strSvcParams = request . GetQueryOrForm ( "svcParams" ) ;
string strNewSvcParams = request . GetQueryOrForm ( "newSvcParams" , strSvcParams ) ;
2024-06-01 19:25:07 +05:30
2025-02-15 12:51:16 +05:30
bool autoIpv4Hint = request . GetQueryOrForm ( "autoIpv4Hint" , bool . Parse , false ) ;
bool autoIpv6Hint = request . GetQueryOrForm ( "autoIpv6Hint" , bool . Parse , false ) ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
Dictionary < DnsSvcParamKey , DnsSvcParamValue > svcParams ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
if ( strSvcParams . Equals ( "false" , StringComparison . OrdinalIgnoreCase ) )
2023-05-20 18:40:44 +05:30
{
2025-02-15 12:51:16 +05:30
svcParams = new Dictionary < DnsSvcParamKey , DnsSvcParamValue > ( 0 ) ;
2023-05-20 18:40:44 +05:30
}
2025-02-15 12:51:16 +05:30
else
{
string [ ] strSvcParamsParts = strSvcParams . Split ( '|' ) ;
svcParams = new Dictionary < DnsSvcParamKey , DnsSvcParamValue > ( strSvcParamsParts . Length / 2 ) ;
for ( int i = 0 ; i < strSvcParamsParts . Length ; i + = 2 )
{
DnsSvcParamKey svcParamKey = Enum . Parse < DnsSvcParamKey > ( strSvcParamsParts [ i ] . Replace ( '-' , '_' ) , true ) ;
DnsSvcParamValue svcParamValue = DnsSvcParamValue . Parse ( svcParamKey , strSvcParamsParts [ i + 1 ] ) ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
svcParams . Add ( svcParamKey , svcParamValue ) ;
}
}
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
Dictionary < DnsSvcParamKey , DnsSvcParamValue > newSvcParams ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
if ( strNewSvcParams . Equals ( "false" , StringComparison . OrdinalIgnoreCase ) )
{
newSvcParams = new Dictionary < DnsSvcParamKey , DnsSvcParamValue > ( 0 ) ;
}
else
2023-05-20 18:40:44 +05:30
{
2025-02-15 12:51:16 +05:30
string [ ] strSvcParamsParts = strNewSvcParams . Split ( '|' ) ;
newSvcParams = new Dictionary < DnsSvcParamKey , DnsSvcParamValue > ( strSvcParamsParts . Length / 2 ) ;
for ( int i = 0 ; i < strSvcParamsParts . Length ; i + = 2 )
{
DnsSvcParamKey svcParamKey = Enum . Parse < DnsSvcParamKey > ( strSvcParamsParts [ i ] . Replace ( '-' , '_' ) , true ) ;
DnsSvcParamValue svcParamValue = DnsSvcParamValue . Parse ( svcParamKey , strSvcParamsParts [ i + 1 ] ) ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
newSvcParams . Add ( svcParamKey , svcParamValue ) ;
}
2023-05-20 18:40:44 +05:30
}
2025-02-15 12:51:16 +05:30
oldRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , 0 , new DnsSVCBRecordData ( svcPriority , targetName , svcParams ) ) ;
newRecord = new DnsResourceRecord ( newDomain , type , DnsClass . IN , ttl , new DnsSVCBRecordData ( newSvcPriority , newTargetName , newSvcParams ) ) ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
if ( autoIpv4Hint )
newRecord . GetAuthSVCBRecordInfo ( ) . AutoIpv4Hint = true ;
2024-06-01 19:25:07 +05:30
2025-02-15 12:51:16 +05:30
if ( autoIpv6Hint )
newRecord . GetAuthSVCBRecordInfo ( ) . AutoIpv6Hint = true ;
2024-06-01 19:25:07 +05:30
2025-02-15 12:51:16 +05:30
if ( autoIpv4Hint | | autoIpv6Hint )
ResolveSvcbAutoHints ( zoneInfo . Name , newRecord , autoIpv4Hint , autoIpv6Hint , newSvcParams ) ;
}
break ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . URI :
{
ushort priority = request . GetQueryOrForm ( "uriPriority" , ushort . Parse ) ;
ushort newPriority = request . GetQueryOrForm ( "newUriPriority" , ushort . Parse , priority ) ;
2023-07-02 15:47:55 +05:30
2025-02-15 12:51:16 +05:30
ushort weight = request . GetQueryOrForm ( "uriWeight" , ushort . Parse ) ;
ushort newWeight = request . GetQueryOrForm ( "newUriWeight" , ushort . Parse , weight ) ;
2023-07-02 15:47:55 +05:30
2025-02-15 12:51:16 +05:30
Uri uri = request . GetQueryOrForm ( "uri" , delegate ( string value ) { return new Uri ( value ) ; } ) ;
Uri newUri = request . GetQueryOrForm ( "newUri" , delegate ( string value ) { return new Uri ( value ) ; } , uri ) ;
2023-07-02 15:47:55 +05:30
2025-02-15 12:51:16 +05:30
oldRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , 0 , new DnsURIRecordData ( priority , weight , uri ) ) ;
newRecord = new DnsResourceRecord ( newDomain , type , DnsClass . IN , ttl , new DnsURIRecordData ( newPriority , newWeight , newUri ) ) ;
}
break ;
2023-07-02 15:47:55 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . CAA :
{
byte flags = request . GetQueryOrForm ( "flags" , byte . Parse ) ;
byte newFlags = request . GetQueryOrForm ( "newFlags" , byte . Parse , flags ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
string tag = request . GetQueryOrForm ( "tag" ) ;
string newTag = request . GetQueryOrForm ( "newTag" , tag ) ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
string value = request . GetQueryOrForm ( "value" ) ;
string newValue = request . GetQueryOrForm ( "newValue" , value ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
oldRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , 0 , new DnsCAARecordData ( flags , tag , value ) ) ;
newRecord = new DnsResourceRecord ( newDomain , type , DnsClass . IN , ttl , new DnsCAARecordData ( newFlags , newTag , newValue ) ) ;
}
break ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . ANAME :
{
string aname = request . GetQueryOrFormAlt ( "aname" , "value" ) . TrimEnd ( '.' ) ;
string newAName = request . GetQueryOrFormAlt ( "newAName" , "newValue" , aname ) . TrimEnd ( '.' ) ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
oldRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , 0 , new DnsANAMERecordData ( aname ) ) ;
newRecord = new DnsResourceRecord ( newDomain , type , DnsClass . IN , ttl , new DnsANAMERecordData ( newAName ) ) ;
}
break ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . FWD :
{
DnsTransportProtocol protocol = request . GetQueryOrFormEnum ( "protocol" , DnsTransportProtocol . Udp ) ;
DnsTransportProtocol newProtocol = request . GetQueryOrFormEnum ( "newProtocol" , protocol ) ;
2022-01-23 18:22:17 +05:30
2025-02-15 12:51:16 +05:30
string forwarder = request . GetQueryOrFormAlt ( "forwarder" , "value" ) ;
string newForwarder = request . GetQueryOrFormAlt ( "newForwarder" , "newValue" , forwarder ) ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
bool dnssecValidation = request . GetQueryOrForm ( "dnssecValidation" , bool . Parse , false ) ;
2022-03-12 15:53:15 +05:30
2025-02-15 12:51:16 +05:30
DnsForwarderRecordProxyType proxyType = DnsForwarderRecordProxyType . DefaultProxy ;
string proxyAddress = null ;
ushort proxyPort = 0 ;
string proxyUsername = null ;
string proxyPassword = null ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( ! newForwarder . Equals ( "this-server" ) )
2022-03-06 16:56:54 +05:30
{
2025-02-15 12:51:16 +05:30
proxyType = request . GetQueryOrFormEnum ( "proxyType" , DnsForwarderRecordProxyType . DefaultProxy ) ;
switch ( proxyType )
{
case DnsForwarderRecordProxyType . Http :
case DnsForwarderRecordProxyType . Socks5 :
proxyAddress = request . GetQueryOrForm ( "proxyAddress" ) ;
proxyPort = request . GetQueryOrForm ( "proxyPort" , ushort . Parse ) ;
proxyUsername = request . QueryOrForm ( "proxyUsername" ) ;
proxyPassword = request . QueryOrForm ( "proxyPassword" ) ;
break ;
}
2022-03-06 16:56:54 +05:30
}
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
byte priority = request . GetQueryOrForm ( "forwarderPriority" , byte . Parse , byte . MinValue ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( newProtocol = = DnsTransportProtocol . Quic )
DnsWebService . ValidateQuicSupport ( ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
oldRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , 0 , DnsForwarderRecordData . CreatePartialRecordData ( protocol , forwarder ) ) ;
newRecord = new DnsResourceRecord ( newDomain , type , DnsClass . IN , 0 , new DnsForwarderRecordData ( newProtocol , newForwarder , dnssecValidation , proxyType , proxyAddress , proxyPort , proxyUsername , proxyPassword , priority ) ) ;
}
break ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
case DnsResourceRecordType . APP :
{
string appName = request . GetQueryOrFormAlt ( "appName" , "value" ) ;
string classPath = request . GetQueryOrForm ( "classPath" ) ;
string recordData = request . GetQueryOrForm ( "recordData" , "" ) ;
2022-03-06 16:56:54 +05:30
2025-02-15 12:51:16 +05:30
oldRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , 0 , new DnsApplicationRecordData ( appName , classPath , recordData ) ) ;
newRecord = new DnsResourceRecord ( newDomain , type , DnsClass . IN , ttl , new DnsApplicationRecordData ( appName , classPath , recordData ) ) ;
}
break ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
default :
{
string strRData = request . GetQueryOrForm ( "rdata" ) ;
string strNewRData = request . GetQueryOrForm ( "newRData" , strRData ) ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
byte [ ] rdata ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
if ( strRData . Contains ( ':' ) )
rdata = strRData . ParseColonHexString ( ) ;
else
rdata = Convert . FromHexString ( strRData ) ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
byte [ ] newRData ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
if ( strNewRData . Contains ( ':' ) )
newRData = strNewRData . ParseColonHexString ( ) ;
else
newRData = Convert . FromHexString ( strNewRData ) ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
oldRecord = new DnsResourceRecord ( domain , type , DnsClass . IN , 0 , new DnsUnknownRecordData ( rdata ) ) ;
newRecord = new DnsResourceRecord ( newDomain , type , DnsClass . IN , ttl , new DnsUnknownRecordData ( newRData ) ) ;
}
break ;
}
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
//update record info
GenericRecordInfo recordInfo = newRecord . GetAuthGenericRecordInfo ( ) ;
2023-05-20 18:40:44 +05:30
2025-02-15 12:51:16 +05:30
recordInfo . LastModified = DateTime . UtcNow ;
recordInfo . ExpiryTtl = expiryTtl ;
recordInfo . Disabled = disable ;
recordInfo . Comments = comments ;
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
//update record
if ( type = = DnsResourceRecordType . SOA )
2024-09-15 15:14:12 +05:30
{
2025-02-15 12:51:16 +05:30
//special SOA case
switch ( zoneInfo . Type )
{
case AuthZoneType . Primary :
case AuthZoneType . Forwarder :
case AuthZoneType . Catalog :
_dnsWebService . _dnsServer . AuthZoneManager . SetRecord ( zoneInfo . Name , newRecord ) ;
break ;
}
//get updated record to return json
newRecord = zoneInfo . ApexZone . GetRecords ( DnsResourceRecordType . SOA ) [ 0 ] ;
}
else
{
_dnsWebService . _dnsServer . AuthZoneManager . UpdateRecord ( zoneInfo . Name , oldRecord , newRecord ) ;
2024-09-15 15:14:12 +05:30
}
2025-02-15 12:51:16 +05:30
//additional processing
if ( ( type = = DnsResourceRecordType . A ) | | ( type = = DnsResourceRecordType . AAAA ) )
{
bool updateSvcbHints = request . GetQueryOrForm ( "updateSvcbHints" , bool . Parse , false ) ;
if ( updateSvcbHints )
UpdateSvcbAutoHints ( zoneInfo . Name , newDomain , type = = DnsResourceRecordType . A , type = = DnsResourceRecordType . AAAA ) ;
}
2024-09-15 15:14:12 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _log . Write ( context . GetRemoteEndPoint ( _dnsWebService . _webServiceRealIpHeader ) , "[" + session . User . Username + "] Record was updated for " + zoneInfo . TypeName + " zone '" + zoneInfo . DisplayName + "' successfully {" + ( oldRecord is null ? "" : "oldRecord: " + oldRecord . ToString ( ) + "; " ) + "newRecord: " + newRecord . ToString ( ) + "}" ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
//save zone
_dnsWebService . _dnsServer . AuthZoneManager . SaveZoneFile ( zoneInfo . Name ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
Utf8JsonWriter jsonWriter = context . GetCurrentJsonWriter ( ) ;
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WritePropertyName ( "zone" ) ;
WriteZoneInfoAsJson ( zoneInfo , jsonWriter ) ;
2023-01-01 18:39:46 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WritePropertyName ( "updatedRecord" ) ;
WriteRecordAsJson ( newRecord , jsonWriter , true , zoneInfo ) ;
}
2022-04-30 16:19:02 +05:30
2025-02-15 12:51:16 +05:30
#endregion
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
#region properties
2021-09-25 13:45:03 +05:30
2025-02-15 12:51:16 +05:30
public uint DefaultRecordTtl
{
get { return _defaultRecordTtl ; }
set { _defaultRecordTtl = value ; }
}
2021-09-25 13:45:03 +05:30
2025-02-15 12:51:16 +05:30
#endregion
2021-09-25 13:45:03 +05:30
}
2021-09-18 19:02:40 +05:30
}
}