mirror of
https://github.com/fergalmoran/DnsServer.git
synced 2026-03-23 22:10:34 +00:00
merged multi-user into develop
This commit is contained in:
4126
APIDOCS.md
4126
APIDOCS.md
File diff suppressed because it is too large
Load Diff
@@ -147,6 +147,7 @@ namespace AdvancedBlocking
|
||||
|
||||
SocketsHttpHandler handler = new SocketsHttpHandler();
|
||||
handler.Proxy = _dnsServer.Proxy;
|
||||
handler.UseProxy = _dnsServer.Proxy is not null;
|
||||
handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
|
||||
|
||||
using (HttpClient http = new HttpClient(handler))
|
||||
|
||||
@@ -150,7 +150,7 @@ namespace Failover
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<DnsDatagram> ProcessRequestAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol, bool isRecursionAllowed, string zoneName, uint appRecordTtl, string appRecordData)
|
||||
public Task<DnsDatagram> ProcessRequestAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol, bool isRecursionAllowed, string zoneName, string appRecordName, uint appRecordTtl, string appRecordData)
|
||||
{
|
||||
DnsQuestionRecord question = request.Question[0];
|
||||
switch (question.Type)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Technitium DNS Server
|
||||
Copyright (C) 2021 Shreyas Zare (shreyas@technitium.com)
|
||||
Copyright (C) 2022 Shreyas Zare (shreyas@technitium.com)
|
||||
|
||||
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
|
||||
@@ -115,7 +115,7 @@ namespace Failover
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<DnsDatagram> ProcessRequestAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol, bool isRecursionAllowed, string zoneName, uint appRecordTtl, string appRecordData)
|
||||
public Task<DnsDatagram> ProcessRequestAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol, bool isRecursionAllowed, string zoneName, string appRecordName, uint appRecordTtl, string appRecordData)
|
||||
{
|
||||
DnsQuestionRecord question = request.Question[0];
|
||||
|
||||
|
||||
@@ -127,6 +127,7 @@ namespace Failover
|
||||
httpHandler.ConnectTimeout = TimeSpan.FromMilliseconds(_timeout);
|
||||
httpHandler.PooledConnectionIdleTimeout = TimeSpan.FromMilliseconds(Math.Max(10000, _timeout));
|
||||
httpHandler.Proxy = proxy;
|
||||
httpHandler.UseProxy = proxy is not null;
|
||||
httpHandler.AllowAutoRedirect = true;
|
||||
httpHandler.MaxAutomaticRedirections = 10;
|
||||
|
||||
@@ -141,6 +142,7 @@ namespace Failover
|
||||
httpHandler.ConnectTimeout = TimeSpan.FromMilliseconds(_timeout);
|
||||
httpHandler.PooledConnectionIdleTimeout = TimeSpan.FromMilliseconds(Math.Max(10000, _timeout));
|
||||
httpHandler.Proxy = proxy;
|
||||
httpHandler.UseProxy = proxy is not null;
|
||||
httpHandler.AllowAutoRedirect = true;
|
||||
httpHandler.MaxAutomaticRedirections = 10;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Technitium DNS Server
|
||||
Copyright (C) 2021 Shreyas Zare (shreyas@technitium.com)
|
||||
Copyright (C) 2022 Shreyas Zare (shreyas@technitium.com)
|
||||
|
||||
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
|
||||
@@ -102,6 +102,7 @@ namespace Failover
|
||||
{
|
||||
SocketsHttpHandler httpHandler = new SocketsHttpHandler();
|
||||
httpHandler.Proxy = proxy;
|
||||
httpHandler.UseProxy = proxy is not null;
|
||||
httpHandler.AllowAutoRedirect = true;
|
||||
httpHandler.MaxAutomaticRedirections = 10;
|
||||
|
||||
@@ -114,6 +115,7 @@ namespace Failover
|
||||
{
|
||||
SocketsHttpHandler httpHandler = new SocketsHttpHandler();
|
||||
httpHandler.Proxy = proxy;
|
||||
httpHandler.UseProxy = proxy is not null;
|
||||
httpHandler.AllowAutoRedirect = true;
|
||||
httpHandler.MaxAutomaticRedirections = 10;
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace GeoContinent
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<DnsDatagram> ProcessRequestAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol, bool isRecursionAllowed, string zoneName, uint appRecordTtl, string appRecordData)
|
||||
public Task<DnsDatagram> ProcessRequestAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol, bool isRecursionAllowed, string zoneName, string appRecordName, uint appRecordTtl, string appRecordData)
|
||||
{
|
||||
DnsQuestionRecord question = request.Question[0];
|
||||
switch (question.Type)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Technitium DNS Server
|
||||
Copyright (C) 2021 Shreyas Zare (shreyas@technitium.com)
|
||||
Copyright (C) 2022 Shreyas Zare (shreyas@technitium.com)
|
||||
|
||||
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
|
||||
@@ -71,7 +71,7 @@ namespace GeoContinent
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<DnsDatagram> ProcessRequestAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol, bool isRecursionAllowed, string zoneName, uint appRecordTtl, string appRecordData)
|
||||
public Task<DnsDatagram> ProcessRequestAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol, bool isRecursionAllowed, string zoneName, string appRecordName, uint appRecordTtl, string appRecordData)
|
||||
{
|
||||
dynamic jsonAppRecordData = JsonConvert.DeserializeObject(appRecordData);
|
||||
dynamic jsonContinent;
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace GeoCountry
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<DnsDatagram> ProcessRequestAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol, bool isRecursionAllowed, string zoneName, uint appRecordTtl, string appRecordData)
|
||||
public Task<DnsDatagram> ProcessRequestAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol, bool isRecursionAllowed, string zoneName, string appRecordName, uint appRecordTtl, string appRecordData)
|
||||
{
|
||||
DnsQuestionRecord question = request.Question[0];
|
||||
switch (question.Type)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Technitium DNS Server
|
||||
Copyright (C) 2021 Shreyas Zare (shreyas@technitium.com)
|
||||
Copyright (C) 2022 Shreyas Zare (shreyas@technitium.com)
|
||||
|
||||
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
|
||||
@@ -71,7 +71,7 @@ namespace GeoCountry
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<DnsDatagram> ProcessRequestAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol, bool isRecursionAllowed, string zoneName, uint appRecordTtl, string appRecordData)
|
||||
public Task<DnsDatagram> ProcessRequestAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol, bool isRecursionAllowed, string zoneName, string appRecordName, uint appRecordTtl, string appRecordData)
|
||||
{
|
||||
dynamic jsonAppRecordData = JsonConvert.DeserializeObject(appRecordData);
|
||||
dynamic jsonCountry;
|
||||
|
||||
@@ -89,7 +89,7 @@ namespace GeoDistance
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<DnsDatagram> ProcessRequestAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol, bool isRecursionAllowed, string zoneName, uint appRecordTtl, string appRecordData)
|
||||
public Task<DnsDatagram> ProcessRequestAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol, bool isRecursionAllowed, string zoneName, string appRecordName, uint appRecordTtl, string appRecordData)
|
||||
{
|
||||
DnsQuestionRecord question = request.Question[0];
|
||||
switch (question.Type)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Technitium DNS Server
|
||||
Copyright (C) 2021 Shreyas Zare (shreyas@technitium.com)
|
||||
Copyright (C) 2022 Shreyas Zare (shreyas@technitium.com)
|
||||
|
||||
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
|
||||
@@ -87,7 +87,7 @@ namespace GeoDistance
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<DnsDatagram> ProcessRequestAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol, bool isRecursionAllowed, string zoneName, uint appRecordTtl, string appRecordData)
|
||||
public Task<DnsDatagram> ProcessRequestAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol, bool isRecursionAllowed, string zoneName, string appRecordName, uint appRecordTtl, string appRecordData)
|
||||
{
|
||||
Location location = null;
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ namespace SplitHorizon
|
||||
}
|
||||
}
|
||||
|
||||
public Task<DnsDatagram> ProcessRequestAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol, bool isRecursionAllowed, string zoneName, uint appRecordTtl, string appRecordData)
|
||||
public Task<DnsDatagram> ProcessRequestAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol, bool isRecursionAllowed, string zoneName, string appRecordName, uint appRecordTtl, string appRecordData)
|
||||
{
|
||||
DnsQuestionRecord question = request.Question[0];
|
||||
switch (question.Type)
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace SplitHorizon
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<DnsDatagram> ProcessRequestAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol, bool isRecursionAllowed, string zoneName, uint appRecordTtl, string appRecordData)
|
||||
public Task<DnsDatagram> ProcessRequestAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol, bool isRecursionAllowed, string zoneName, string appRecordName, uint appRecordTtl, string appRecordData)
|
||||
{
|
||||
dynamic jsonAppRecordData = JsonConvert.DeserializeObject(appRecordData);
|
||||
dynamic jsonCname = null;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Technitium DNS Server
|
||||
Copyright (C) 2021 Shreyas Zare (shreyas@technitium.com)
|
||||
Copyright (C) 2022 Shreyas Zare (shreyas@technitium.com)
|
||||
|
||||
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
|
||||
@@ -45,7 +45,7 @@ namespace WhatIsMyDns
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<DnsDatagram> ProcessRequestAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol, bool isRecursionAllowed, string zoneName, uint appRecordTtl, string appRecordData)
|
||||
public Task<DnsDatagram> ProcessRequestAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol, bool isRecursionAllowed, string zoneName, string appRecordName, uint appRecordTtl, string appRecordData)
|
||||
{
|
||||
DnsResourceRecord answer;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Technitium DNS Server
|
||||
Copyright (C) 2021 Shreyas Zare (shreyas@technitium.com)
|
||||
Copyright (C) 2022 Shreyas Zare (shreyas@technitium.com)
|
||||
|
||||
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
|
||||
@@ -51,7 +51,7 @@ namespace DnsServerApp
|
||||
break;
|
||||
}
|
||||
|
||||
service = new DnsWebService(configFolder, updateCheckUri, new Uri("https://go.technitium.com/?id=40"));
|
||||
service = new DnsWebService(configFolder, updateCheckUri, new Uri("https://go.technitium.com/?id=44"));
|
||||
service.Start();
|
||||
|
||||
Console.CancelKeyPress += delegate (object sender, ConsoleCancelEventArgs e)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Technitium DNS Server
|
||||
Copyright (C) 2021 Shreyas Zare (shreyas@technitium.com)
|
||||
Copyright (C) 2022 Shreyas Zare (shreyas@technitium.com)
|
||||
|
||||
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
|
||||
@@ -36,10 +36,11 @@ namespace DnsServerCore.ApplicationCommon
|
||||
/// <param name="protocol">The protocol using which the request was received.</param>
|
||||
/// <param name="isRecursionAllowed">Tells if the DNS server is configured to allow recursion for the client making this request.</param>
|
||||
/// <param name="zoneName">The name of the application zone that the APP record belongs to.</param>
|
||||
/// <param name="appRecordName">The domain name of the APP record.</param>
|
||||
/// <param name="appRecordTtl">The TTL value set in the APP record.</param>
|
||||
/// <param name="appRecordData">The record data in the APP record as required for processing the request.</param>
|
||||
/// <returns>The DNS response for the DNS request or <c>null</c> to send no answer response with an SOA authority.</returns>
|
||||
Task<DnsDatagram> ProcessRequestAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol, bool isRecursionAllowed, string zoneName, uint appRecordTtl, string appRecordData);
|
||||
Task<DnsDatagram> ProcessRequestAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol, bool isRecursionAllowed, string zoneName, string appRecordName, uint appRecordTtl, string appRecordData);
|
||||
|
||||
/// <summary>
|
||||
/// A template of the record data format that is required by this app. This template is populated in the UI to allow the user to edit in the expected values. The format could be JSON or any other custom text based format which the app is programmed to parse. This property is optional and can return <c>null</c> if no APP record data is required by the app.
|
||||
|
||||
837
DnsServerCore/Auth/AuthManager.cs
Normal file
837
DnsServerCore/Auth/AuthManager.cs
Normal file
@@ -0,0 +1,837 @@
|
||||
/*
|
||||
Technitium DNS Server
|
||||
Copyright (C) 2022 Shreyas Zare (shreyas@technitium.com)
|
||||
|
||||
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/>.
|
||||
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DnsServerCore.Auth
|
||||
{
|
||||
sealed class AuthManager : IDisposable
|
||||
{
|
||||
#region variables
|
||||
|
||||
readonly ConcurrentDictionary<string, Group> _groups = new ConcurrentDictionary<string, Group>(1, 4);
|
||||
readonly ConcurrentDictionary<string, User> _users = new ConcurrentDictionary<string, User>(1, 4);
|
||||
|
||||
readonly ConcurrentDictionary<PermissionSection, Permission> _permissions = new ConcurrentDictionary<PermissionSection, Permission>(1, 11);
|
||||
|
||||
readonly ConcurrentDictionary<string, UserSession> _sessions = new ConcurrentDictionary<string, UserSession>(1, 10);
|
||||
|
||||
readonly ConcurrentDictionary<IPAddress, int> _failedLoginAttempts = new ConcurrentDictionary<IPAddress, int>(1, 10);
|
||||
const int MAX_LOGIN_ATTEMPTS = 5;
|
||||
|
||||
readonly ConcurrentDictionary<IPAddress, DateTime> _blockedAddresses = new ConcurrentDictionary<IPAddress, DateTime>(1, 10);
|
||||
const int BLOCK_ADDRESS_INTERVAL = 5 * 60 * 1000;
|
||||
|
||||
readonly string _configFolder;
|
||||
readonly LogManager _log;
|
||||
|
||||
readonly object _lockObj = new object();
|
||||
bool _pendingSave;
|
||||
readonly Timer _saveTimer;
|
||||
const int SAVE_TIMER_INITIAL_INTERVAL = 10000;
|
||||
|
||||
#endregion
|
||||
|
||||
#region constructor
|
||||
|
||||
public AuthManager(string configFolder, LogManager log)
|
||||
{
|
||||
_configFolder = configFolder;
|
||||
_log = log;
|
||||
|
||||
_saveTimer = new Timer(SaveTimerCallback, null, Timeout.Infinite, Timeout.Infinite);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDisposable
|
||||
|
||||
bool _disposed;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed)
|
||||
return;
|
||||
|
||||
if (_saveTimer is not null)
|
||||
_saveTimer.Dispose();
|
||||
|
||||
lock (_lockObj)
|
||||
{
|
||||
SaveConfigFileInternal();
|
||||
}
|
||||
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region private
|
||||
|
||||
private void SaveTimerCallback(object state)
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (_lockObj)
|
||||
{
|
||||
_pendingSave = false;
|
||||
SaveConfigFileInternal();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_log.Write(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateDefaultConfig()
|
||||
{
|
||||
Group adminGroup = CreateGroup(Group.ADMINISTRATORS, "Super administrators");
|
||||
Group dnsAdminGroup = CreateGroup(Group.DNS_ADMINISTRATORS, "DNS service administrators");
|
||||
Group dhcpAdminGroup = CreateGroup(Group.DHCP_ADMINISTRATORS, "DHCP service administrators");
|
||||
Group everyoneGroup = CreateGroup(Group.EVERYONE, "All users");
|
||||
|
||||
SetPermission(PermissionSection.Dashboard, adminGroup, PermissionFlag.ViewModifyDelete);
|
||||
SetPermission(PermissionSection.Zones, adminGroup, PermissionFlag.ViewModifyDelete);
|
||||
SetPermission(PermissionSection.Cache, adminGroup, PermissionFlag.ViewModifyDelete);
|
||||
SetPermission(PermissionSection.Allowed, adminGroup, PermissionFlag.ViewModifyDelete);
|
||||
SetPermission(PermissionSection.Blocked, adminGroup, PermissionFlag.ViewModifyDelete);
|
||||
SetPermission(PermissionSection.Apps, adminGroup, PermissionFlag.ViewModifyDelete);
|
||||
SetPermission(PermissionSection.DnsClient, adminGroup, PermissionFlag.ViewModifyDelete);
|
||||
SetPermission(PermissionSection.Settings, adminGroup, PermissionFlag.ViewModifyDelete);
|
||||
SetPermission(PermissionSection.DhcpServer, adminGroup, PermissionFlag.ViewModifyDelete);
|
||||
SetPermission(PermissionSection.Administration, adminGroup, PermissionFlag.ViewModifyDelete);
|
||||
SetPermission(PermissionSection.Logs, adminGroup, PermissionFlag.ViewModifyDelete);
|
||||
|
||||
SetPermission(PermissionSection.Zones, dnsAdminGroup, PermissionFlag.ViewModifyDelete);
|
||||
SetPermission(PermissionSection.Cache, dnsAdminGroup, PermissionFlag.ViewModifyDelete);
|
||||
SetPermission(PermissionSection.Allowed, dnsAdminGroup, PermissionFlag.ViewModifyDelete);
|
||||
SetPermission(PermissionSection.Blocked, dnsAdminGroup, PermissionFlag.ViewModifyDelete);
|
||||
SetPermission(PermissionSection.Apps, dnsAdminGroup, PermissionFlag.ViewModifyDelete);
|
||||
SetPermission(PermissionSection.DnsClient, dnsAdminGroup, PermissionFlag.ViewModifyDelete);
|
||||
SetPermission(PermissionSection.Settings, dnsAdminGroup, PermissionFlag.ViewModifyDelete);
|
||||
SetPermission(PermissionSection.Logs, dnsAdminGroup, PermissionFlag.View);
|
||||
|
||||
SetPermission(PermissionSection.Zones, dhcpAdminGroup, PermissionFlag.View);
|
||||
SetPermission(PermissionSection.DnsClient, dhcpAdminGroup, PermissionFlag.View);
|
||||
SetPermission(PermissionSection.DhcpServer, dhcpAdminGroup, PermissionFlag.ViewModifyDelete);
|
||||
SetPermission(PermissionSection.Logs, dhcpAdminGroup, PermissionFlag.View);
|
||||
|
||||
SetPermission(PermissionSection.Dashboard, everyoneGroup, PermissionFlag.View);
|
||||
SetPermission(PermissionSection.Zones, everyoneGroup, PermissionFlag.View);
|
||||
SetPermission(PermissionSection.Cache, everyoneGroup, PermissionFlag.View);
|
||||
SetPermission(PermissionSection.Allowed, everyoneGroup, PermissionFlag.View);
|
||||
SetPermission(PermissionSection.Blocked, everyoneGroup, PermissionFlag.View);
|
||||
SetPermission(PermissionSection.Apps, everyoneGroup, PermissionFlag.View);
|
||||
SetPermission(PermissionSection.DnsClient, everyoneGroup, PermissionFlag.View);
|
||||
SetPermission(PermissionSection.DhcpServer, everyoneGroup, PermissionFlag.View);
|
||||
SetPermission(PermissionSection.Logs, everyoneGroup, PermissionFlag.View);
|
||||
|
||||
string adminPassword = Environment.GetEnvironmentVariable("DNS_SERVER_ADMIN_PASSWORD");
|
||||
string adminPasswordFile = Environment.GetEnvironmentVariable("DNS_SERVER_ADMIN_PASSWORD_FILE");
|
||||
|
||||
User adminUser;
|
||||
|
||||
if (!string.IsNullOrEmpty(adminPassword))
|
||||
{
|
||||
adminUser = CreateUser("Administrator", "admin", adminPassword);
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(adminPasswordFile))
|
||||
{
|
||||
try
|
||||
{
|
||||
using (StreamReader sR = new StreamReader(adminPasswordFile, true))
|
||||
{
|
||||
string password = sR.ReadLine();
|
||||
adminUser = CreateUser("Administrator", "admin", password);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_log.Write(ex);
|
||||
|
||||
adminUser = CreateUser("Administrator", "admin", "admin");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
adminUser = CreateUser("Administrator", "admin", "admin");
|
||||
}
|
||||
|
||||
adminUser.AddToGroup(adminGroup);
|
||||
}
|
||||
|
||||
private void LoadConfigFileInternal(UserSession implantSession)
|
||||
{
|
||||
string configFile = Path.Combine(_configFolder, "auth.config");
|
||||
|
||||
try
|
||||
{
|
||||
bool passwordResetOption = false;
|
||||
|
||||
if (!File.Exists(configFile))
|
||||
{
|
||||
string passwordResetConfigFile = Path.Combine(_configFolder, "resetadmin.config");
|
||||
|
||||
if (File.Exists(passwordResetConfigFile))
|
||||
{
|
||||
passwordResetOption = true;
|
||||
configFile = passwordResetConfigFile;
|
||||
}
|
||||
}
|
||||
|
||||
using (FileStream fS = new FileStream(configFile, FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
ReadConfigFrom(new BinaryReader(fS));
|
||||
}
|
||||
|
||||
if (implantSession is not null)
|
||||
{
|
||||
UserSession newSession;
|
||||
|
||||
using (MemoryStream mS = new MemoryStream())
|
||||
{
|
||||
implantSession.WriteTo(new BinaryWriter(mS));
|
||||
|
||||
mS.Position = 0;
|
||||
newSession = new UserSession(new BinaryReader(mS), this);
|
||||
}
|
||||
|
||||
_sessions.TryAdd(newSession.Token, newSession);
|
||||
}
|
||||
|
||||
_log.Write("DNS Server auth config file was loaded: " + configFile);
|
||||
|
||||
if (passwordResetOption)
|
||||
{
|
||||
User adminUser = GetUser("admin");
|
||||
if (adminUser is null)
|
||||
{
|
||||
adminUser = CreateUser("Administrator", "admin", "admin");
|
||||
}
|
||||
else
|
||||
{
|
||||
adminUser.ChangePassword("admin");
|
||||
adminUser.Disabled = false;
|
||||
}
|
||||
|
||||
adminUser.AddToGroup(GetGroup(Group.ADMINISTRATORS));
|
||||
|
||||
_log.Write("DNS Server reset password for user: admin");
|
||||
SaveConfigFileInternal();
|
||||
|
||||
try
|
||||
{
|
||||
File.Delete(configFile);
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
_log.Write("DNS Server auth config file was not found: " + configFile);
|
||||
_log.Write("DNS Server is restoring default auth config file.");
|
||||
|
||||
CreateDefaultConfig();
|
||||
|
||||
SaveConfigFileInternal();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_log.Write("DNS Server encountered an error while loading auth config file: " + configFile + "\r\n" + ex.ToString());
|
||||
_log.Write("Note: You may try deleting the auth config file to fix this issue. However, you will lose auth settings but, rest of the DNS settings and zone data wont be affected.");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveConfigFileInternal()
|
||||
{
|
||||
string configFile = Path.Combine(_configFolder, "auth.config");
|
||||
|
||||
using (MemoryStream mS = new MemoryStream())
|
||||
{
|
||||
//serialize config
|
||||
WriteConfigTo(new BinaryWriter(mS));
|
||||
|
||||
//write config
|
||||
mS.Position = 0;
|
||||
|
||||
using (FileStream fS = new FileStream(configFile, FileMode.Create, FileAccess.Write))
|
||||
{
|
||||
mS.CopyTo(fS);
|
||||
}
|
||||
}
|
||||
|
||||
_log.Write("DNS Server auth config file was saved: " + configFile);
|
||||
}
|
||||
|
||||
private void ReadConfigFrom(BinaryReader bR)
|
||||
{
|
||||
if (Encoding.ASCII.GetString(bR.ReadBytes(2)) != "AS") //format
|
||||
throw new InvalidDataException("DNS Server auth config file format is invalid.");
|
||||
|
||||
int version = bR.ReadByte();
|
||||
switch (version)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
int count = bR.ReadByte();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
Group group = new Group(bR);
|
||||
_groups.TryAdd(group.Name.ToLower(), group);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
int count = bR.ReadByte();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
User user = new User(bR, this);
|
||||
_users.TryAdd(user.Username, user);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
int count = bR.ReadInt32();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
Permission permission = new Permission(bR, this);
|
||||
_permissions.TryAdd(permission.Section, permission);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
int count = bR.ReadInt32();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
UserSession session = new UserSession(bR, this);
|
||||
if (!session.HasExpired())
|
||||
_sessions.TryAdd(session.Token, session);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new InvalidDataException("DNS Server auth config version not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteConfigTo(BinaryWriter bW)
|
||||
{
|
||||
bW.Write(Encoding.ASCII.GetBytes("AS")); //format
|
||||
bW.Write((byte)1); //version
|
||||
|
||||
bW.Write(Convert.ToByte(_groups.Count));
|
||||
|
||||
foreach (KeyValuePair<string, Group> group in _groups)
|
||||
group.Value.WriteTo(bW);
|
||||
|
||||
bW.Write(Convert.ToByte(_users.Count));
|
||||
|
||||
foreach (KeyValuePair<string, User> user in _users)
|
||||
user.Value.WriteTo(bW);
|
||||
|
||||
bW.Write(_permissions.Count);
|
||||
|
||||
foreach (KeyValuePair<PermissionSection, Permission> permission in _permissions)
|
||||
permission.Value.WriteTo(bW);
|
||||
|
||||
List<UserSession> activeSessions = new List<UserSession>(_sessions.Count);
|
||||
|
||||
foreach (KeyValuePair<string, UserSession> session in _sessions)
|
||||
{
|
||||
if (session.Value.HasExpired())
|
||||
_sessions.TryRemove(session.Key, out _);
|
||||
else
|
||||
activeSessions.Add(session.Value);
|
||||
}
|
||||
|
||||
bW.Write(activeSessions.Count);
|
||||
|
||||
foreach (UserSession session in activeSessions)
|
||||
session.WriteTo(bW);
|
||||
}
|
||||
|
||||
private void FailedLoginAttempt(IPAddress address)
|
||||
{
|
||||
_failedLoginAttempts.AddOrUpdate(address, 1, delegate (IPAddress key, int attempts)
|
||||
{
|
||||
return attempts + 1;
|
||||
});
|
||||
}
|
||||
|
||||
private bool LoginAttemptsExceedLimit(IPAddress address, int limit)
|
||||
{
|
||||
if (!_failedLoginAttempts.TryGetValue(address, out int attempts))
|
||||
return false;
|
||||
|
||||
return attempts >= limit;
|
||||
}
|
||||
|
||||
private void ResetFailedLoginAttempt(IPAddress address)
|
||||
{
|
||||
_failedLoginAttempts.TryRemove(address, out _);
|
||||
}
|
||||
|
||||
private void BlockAddress(IPAddress address, int interval)
|
||||
{
|
||||
_blockedAddresses.TryAdd(address, DateTime.UtcNow.AddMilliseconds(interval));
|
||||
}
|
||||
|
||||
private bool IsAddressBlocked(IPAddress address)
|
||||
{
|
||||
if (!_blockedAddresses.TryGetValue(address, out DateTime expiry))
|
||||
return false;
|
||||
|
||||
if (expiry > DateTime.UtcNow)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
UnblockAddress(address);
|
||||
ResetFailedLoginAttempt(address);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void UnblockAddress(IPAddress address)
|
||||
{
|
||||
_blockedAddresses.TryRemove(address, out _);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region public
|
||||
|
||||
public User GetUser(string username)
|
||||
{
|
||||
if (_users.TryGetValue(username.ToLower(), out User user))
|
||||
return user;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public User CreateUser(string displayName, string username, string password, int iterations = User.DEFAULT_ITERATIONS)
|
||||
{
|
||||
username = username.ToLower();
|
||||
|
||||
User user = new User(displayName, username, password, iterations);
|
||||
|
||||
if (_users.TryAdd(username, user))
|
||||
{
|
||||
user.AddToGroup(GetGroup(Group.EVERYONE));
|
||||
return user;
|
||||
}
|
||||
|
||||
throw new DnsWebServiceException("User already exists: " + username);
|
||||
}
|
||||
|
||||
public void ChangeUsername(User user, string newUsername)
|
||||
{
|
||||
if (user.Username.Equals(newUsername, StringComparison.OrdinalIgnoreCase))
|
||||
return;
|
||||
|
||||
string oldUsername = user.Username;
|
||||
user.Username = newUsername;
|
||||
|
||||
if (!_users.TryAdd(user.Username, user))
|
||||
{
|
||||
user.Username = oldUsername; //revert
|
||||
throw new DnsWebServiceException("User already exists: " + newUsername);
|
||||
}
|
||||
|
||||
_users.TryRemove(oldUsername, out _);
|
||||
}
|
||||
|
||||
public bool DeleteUser(string username)
|
||||
{
|
||||
if (_users.TryRemove(username.ToLower(), out User deletedUser))
|
||||
{
|
||||
//delete all sessions
|
||||
foreach (UserSession session in GetSessions(deletedUser))
|
||||
DeleteSession(session.Token);
|
||||
|
||||
//delete all permissions
|
||||
foreach (KeyValuePair<PermissionSection, Permission> permission in _permissions)
|
||||
{
|
||||
permission.Value.RemovePermission(deletedUser);
|
||||
permission.Value.RemoveAllSubItemPermissions(deletedUser);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public Group GetGroup(string name)
|
||||
{
|
||||
if (_groups.TryGetValue(name.ToLower(), out Group group))
|
||||
return group;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<User> GetGroupMembers(Group group)
|
||||
{
|
||||
List<User> members = new List<User>();
|
||||
|
||||
foreach (KeyValuePair<string, User> user in _users)
|
||||
{
|
||||
if (user.Value.IsMemberOfGroup(group))
|
||||
members.Add(user.Value);
|
||||
}
|
||||
|
||||
return members;
|
||||
}
|
||||
|
||||
public void SyncGroupMembers(Group group, IReadOnlyDictionary<string, User> users)
|
||||
{
|
||||
//remove
|
||||
foreach (KeyValuePair<string, User> user in _users)
|
||||
{
|
||||
if (!users.ContainsKey(user.Key))
|
||||
user.Value.RemoveFromGroup(group);
|
||||
}
|
||||
|
||||
//set
|
||||
foreach (KeyValuePair<string, User> user in users)
|
||||
user.Value.AddToGroup(group);
|
||||
}
|
||||
|
||||
public Group CreateGroup(string name, string description)
|
||||
{
|
||||
Group group = new Group(name, description);
|
||||
|
||||
if (_groups.TryAdd(name.ToLower(), group))
|
||||
return group;
|
||||
|
||||
throw new DnsWebServiceException("Group already exists: " + name);
|
||||
}
|
||||
|
||||
public void RenameGroup(Group group, string newGroupName)
|
||||
{
|
||||
if (group.Name.Equals(newGroupName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
group.Name = newGroupName;
|
||||
return;
|
||||
}
|
||||
|
||||
string oldGroupName = group.Name;
|
||||
group.Name = newGroupName;
|
||||
|
||||
if (!_groups.TryAdd(group.Name.ToLower(), group))
|
||||
{
|
||||
group.Name = oldGroupName; //revert
|
||||
throw new DnsWebServiceException("Group already exists: " + newGroupName);
|
||||
}
|
||||
|
||||
_groups.TryRemove(oldGroupName.ToLower(), out _);
|
||||
|
||||
//update users
|
||||
foreach (KeyValuePair<string, User> user in _users)
|
||||
user.Value.RenameGroup(oldGroupName);
|
||||
}
|
||||
|
||||
public bool DeleteGroup(string name)
|
||||
{
|
||||
name = name.ToLower();
|
||||
|
||||
switch (name)
|
||||
{
|
||||
case "everyone":
|
||||
case "administrators":
|
||||
case "dns administrators":
|
||||
case "dhcp administrators":
|
||||
throw new InvalidOperationException("Access was denied.");
|
||||
|
||||
default:
|
||||
if (_groups.TryRemove(name, out Group deletedGroup))
|
||||
{
|
||||
//remove all users from deleted group
|
||||
foreach (KeyValuePair<string, User> user in _users)
|
||||
user.Value.RemoveFromGroup(deletedGroup);
|
||||
|
||||
//delete all permissions
|
||||
foreach (KeyValuePair<PermissionSection, Permission> permission in _permissions)
|
||||
{
|
||||
permission.Value.RemovePermission(deletedGroup);
|
||||
permission.Value.RemoveAllSubItemPermissions(deletedGroup);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public UserSession GetSession(string token)
|
||||
{
|
||||
if (_sessions.TryGetValue(token, out UserSession session))
|
||||
return session;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<UserSession> GetSessions(User user)
|
||||
{
|
||||
List<UserSession> userSessions = new List<UserSession>();
|
||||
|
||||
foreach (KeyValuePair<string, UserSession> session in _sessions)
|
||||
{
|
||||
if (session.Value.User.Equals(user) && !session.Value.HasExpired())
|
||||
userSessions.Add(session.Value);
|
||||
}
|
||||
|
||||
return userSessions;
|
||||
}
|
||||
|
||||
public async Task<UserSession> CreateSessionAsync(UserSessionType type, string tokenName, string username, string password, IPAddress remoteAddress, string userAgent)
|
||||
{
|
||||
if (IsAddressBlocked(remoteAddress))
|
||||
throw new DnsWebServiceException("Max limit of " + MAX_LOGIN_ATTEMPTS + " attempts exceeded. Access blocked for " + (BLOCK_ADDRESS_INTERVAL / 1000) + " seconds.");
|
||||
|
||||
User user = GetUser(username);
|
||||
|
||||
if ((user is null) || !user.PasswordHash.Equals(user.GetPasswordHashFor(password), StringComparison.Ordinal))
|
||||
{
|
||||
if (password != "admin")
|
||||
{
|
||||
FailedLoginAttempt(remoteAddress);
|
||||
|
||||
if (LoginAttemptsExceedLimit(remoteAddress, MAX_LOGIN_ATTEMPTS))
|
||||
BlockAddress(remoteAddress, BLOCK_ADDRESS_INTERVAL);
|
||||
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
|
||||
throw new DnsWebServiceException("Invalid username or password for user: " + username);
|
||||
}
|
||||
|
||||
ResetFailedLoginAttempt(remoteAddress);
|
||||
|
||||
if (user.Disabled)
|
||||
throw new DnsWebServiceException("User account is disabled. Please contact your administrator.");
|
||||
|
||||
UserSession session = new UserSession(type, tokenName, user, remoteAddress, userAgent);
|
||||
|
||||
if (!_sessions.TryAdd(session.Token, session))
|
||||
throw new DnsWebServiceException("Error while creating session. Please try again.");
|
||||
|
||||
user.LoggedInFrom(remoteAddress);
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
public UserSession CreateApiToken(string tokenName, string username, IPAddress remoteAddress, string userAgent)
|
||||
{
|
||||
if (IsAddressBlocked(remoteAddress))
|
||||
throw new DnsWebServiceException("Max limit of " + MAX_LOGIN_ATTEMPTS + " attempts exceeded. Access blocked for " + (BLOCK_ADDRESS_INTERVAL / 1000) + " seconds.");
|
||||
|
||||
User user = GetUser(username);
|
||||
if (user is null)
|
||||
throw new DnsWebServiceException("No such user exists: " + username);
|
||||
|
||||
if (user.Disabled)
|
||||
throw new DnsWebServiceException("Account is suspended.");
|
||||
|
||||
UserSession session = new UserSession(UserSessionType.ApiToken, tokenName, user, remoteAddress, userAgent);
|
||||
|
||||
if (!_sessions.TryAdd(session.Token, session))
|
||||
throw new DnsWebServiceException("Error while creating session. Please try again.");
|
||||
|
||||
user.LoggedInFrom(remoteAddress);
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
public UserSession DeleteSession(string token)
|
||||
{
|
||||
if (_sessions.TryRemove(token, out UserSession session))
|
||||
return session;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Permission GetPermission(PermissionSection section)
|
||||
{
|
||||
if (_permissions.TryGetValue(section, out Permission permission))
|
||||
return permission;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Permission GetPermission(PermissionSection section, string subItemName)
|
||||
{
|
||||
if (_permissions.TryGetValue(section, out Permission permission))
|
||||
return permission.GetSubItemPermission(subItemName);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void SetPermission(PermissionSection section, User user, PermissionFlag flags)
|
||||
{
|
||||
Permission permission = _permissions.GetOrAdd(section, delegate (PermissionSection key)
|
||||
{
|
||||
return new Permission(key);
|
||||
});
|
||||
|
||||
permission.SetPermission(user, flags);
|
||||
}
|
||||
|
||||
public void SetPermission(PermissionSection section, string subItemName, User user, PermissionFlag flags)
|
||||
{
|
||||
Permission permission = _permissions.GetOrAdd(section, delegate (PermissionSection key)
|
||||
{
|
||||
return new Permission(key);
|
||||
});
|
||||
|
||||
permission.SetSubItemPermission(subItemName, user, flags);
|
||||
}
|
||||
|
||||
public void SetPermission(PermissionSection section, Group group, PermissionFlag flags)
|
||||
{
|
||||
Permission permission = _permissions.GetOrAdd(section, delegate (PermissionSection key)
|
||||
{
|
||||
return new Permission(key);
|
||||
});
|
||||
|
||||
permission.SetPermission(group, flags);
|
||||
}
|
||||
|
||||
public void SetPermission(PermissionSection section, string subItemName, Group group, PermissionFlag flags)
|
||||
{
|
||||
Permission permission = _permissions.GetOrAdd(section, delegate (PermissionSection key)
|
||||
{
|
||||
return new Permission(key);
|
||||
});
|
||||
|
||||
permission.SetSubItemPermission(subItemName, group, flags);
|
||||
}
|
||||
|
||||
public bool RemovePermission(PermissionSection section, User user)
|
||||
{
|
||||
return _permissions.TryGetValue(section, out Permission permission) && permission.RemovePermission(user);
|
||||
}
|
||||
|
||||
public bool RemovePermission(PermissionSection section, string subItemName, User user)
|
||||
{
|
||||
return _permissions.TryGetValue(section, out Permission permission) && permission.RemoveSubItemPermission(subItemName, user);
|
||||
}
|
||||
|
||||
public bool RemovePermission(PermissionSection section, Group group)
|
||||
{
|
||||
return _permissions.TryGetValue(section, out Permission permission) && permission.RemovePermission(group);
|
||||
}
|
||||
|
||||
public bool RemovePermission(PermissionSection section, string subItemName, Group group)
|
||||
{
|
||||
return _permissions.TryGetValue(section, out Permission permission) && permission.RemoveSubItemPermission(subItemName, group);
|
||||
}
|
||||
|
||||
public bool RemoveAllPermissions(PermissionSection section, string subItemName)
|
||||
{
|
||||
return _permissions.TryGetValue(section, out Permission permission) && permission.RemoveAllSubItemPermissions(subItemName);
|
||||
}
|
||||
|
||||
public bool IsPermitted(PermissionSection section, User user, PermissionFlag flag)
|
||||
{
|
||||
return _permissions.TryGetValue(section, out Permission permission) && permission.IsPermitted(user, flag);
|
||||
}
|
||||
|
||||
public bool IsPermitted(PermissionSection section, string subItemName, User user, PermissionFlag flag)
|
||||
{
|
||||
return _permissions.TryGetValue(section, out Permission permission) && permission.IsSubItemPermitted(subItemName, user, flag);
|
||||
}
|
||||
|
||||
public void LoadOldConfig(string password, bool isPasswordHash)
|
||||
{
|
||||
User user = GetUser("admin");
|
||||
if (user is null)
|
||||
user = CreateUser("Administrator", "admin", "admin");
|
||||
|
||||
user.AddToGroup(GetGroup(Group.ADMINISTRATORS));
|
||||
|
||||
if (isPasswordHash)
|
||||
user.LoadOldSchemeCredentials(password);
|
||||
else
|
||||
user.ChangePassword(password);
|
||||
|
||||
lock (_lockObj)
|
||||
{
|
||||
SaveConfigFileInternal();
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadConfigFile(UserSession implantSession = null)
|
||||
{
|
||||
lock (_lockObj)
|
||||
{
|
||||
_groups.Clear();
|
||||
_users.Clear();
|
||||
_permissions.Clear();
|
||||
_sessions.Clear();
|
||||
|
||||
LoadConfigFileInternal(implantSession);
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveConfigFile()
|
||||
{
|
||||
lock (_lockObj)
|
||||
{
|
||||
if (_pendingSave)
|
||||
return;
|
||||
|
||||
_pendingSave = true;
|
||||
_saveTimer.Change(SAVE_TIMER_INITIAL_INTERVAL, Timeout.Infinite);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region properties
|
||||
|
||||
public ICollection<Group> Groups
|
||||
{ get { return _groups.Values; } }
|
||||
|
||||
public ICollection<User> Users
|
||||
{ get { return _users.Values; } }
|
||||
|
||||
public ICollection<Permission> Permissions
|
||||
{ get { return _permissions.Values; } }
|
||||
|
||||
public ICollection<UserSession> Sessions
|
||||
{ get { return _sessions.Values; } }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
140
DnsServerCore/Auth/Group.cs
Normal file
140
DnsServerCore/Auth/Group.cs
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
Technitium DNS Server
|
||||
Copyright (C) 2022 Shreyas Zare (shreyas@technitium.com)
|
||||
|
||||
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/>.
|
||||
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using TechnitiumLibrary.IO;
|
||||
|
||||
namespace DnsServerCore.Auth
|
||||
{
|
||||
class Group : IComparable<Group>
|
||||
{
|
||||
#region variables
|
||||
|
||||
public const string ADMINISTRATORS = "Administrators";
|
||||
public const string EVERYONE = "Everyone";
|
||||
public const string DNS_ADMINISTRATORS = "DNS Administrators";
|
||||
public const string DHCP_ADMINISTRATORS = "DHCP Administrators";
|
||||
|
||||
string _name;
|
||||
string _description;
|
||||
|
||||
#endregion
|
||||
|
||||
#region constructor
|
||||
|
||||
public Group(string name, string description)
|
||||
{
|
||||
Name = name;
|
||||
Description = description;
|
||||
}
|
||||
|
||||
public Group(BinaryReader bR)
|
||||
{
|
||||
switch (bR.ReadByte())
|
||||
{
|
||||
case 1:
|
||||
_name = bR.ReadShortString();
|
||||
_description = bR.ReadShortString();
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new InvalidDataException("Invalid data or version not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region public
|
||||
|
||||
public void WriteTo(BinaryWriter bW)
|
||||
{
|
||||
bW.Write((byte)1);
|
||||
bW.WriteShortString(_name);
|
||||
bW.WriteShortString(_description);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj is not Group other)
|
||||
return false;
|
||||
|
||||
return _name.Equals(other._name, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return base.GetHashCode();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
public int CompareTo(Group other)
|
||||
{
|
||||
return _name.CompareTo(other._name);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region properties
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return _name; }
|
||||
set
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
throw new ArgumentException("Group name cannot be null or empty.", nameof(Name));
|
||||
|
||||
if (value.Length > 255)
|
||||
throw new ArgumentException("Group name length cannot exceed 255 characters.", nameof(Name));
|
||||
|
||||
switch (_name?.ToLower())
|
||||
{
|
||||
case "everyone":
|
||||
case "administrators":
|
||||
case "dns administrators":
|
||||
case "dhcp administrators":
|
||||
throw new InvalidOperationException("Access was denied.");
|
||||
|
||||
default:
|
||||
_name = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string Description
|
||||
{
|
||||
get { return _description; }
|
||||
set
|
||||
{
|
||||
if (value.Length > 255)
|
||||
throw new ArgumentException("Group description length cannot exceed 255 characters.", nameof(Description));
|
||||
|
||||
_description = value;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
339
DnsServerCore/Auth/Permission.cs
Normal file
339
DnsServerCore/Auth/Permission.cs
Normal file
@@ -0,0 +1,339 @@
|
||||
/*
|
||||
Technitium DNS Server
|
||||
Copyright (C) 2022 Shreyas Zare (shreyas@technitium.com)
|
||||
|
||||
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/>.
|
||||
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using TechnitiumLibrary.IO;
|
||||
|
||||
namespace DnsServerCore.Auth
|
||||
{
|
||||
enum PermissionSection : byte
|
||||
{
|
||||
Unknown = 0,
|
||||
Dashboard = 1,
|
||||
Zones = 2,
|
||||
Cache = 3,
|
||||
Allowed = 4,
|
||||
Blocked = 5,
|
||||
Apps = 6,
|
||||
DnsClient = 7,
|
||||
Settings = 8,
|
||||
DhcpServer = 9,
|
||||
Administration = 10,
|
||||
Logs = 11
|
||||
}
|
||||
|
||||
[Flags]
|
||||
enum PermissionFlag : byte
|
||||
{
|
||||
None = 0,
|
||||
View = 1,
|
||||
Modify = 2,
|
||||
Delete = 4,
|
||||
ViewModify = 3,
|
||||
ViewModifyDelete = 7
|
||||
}
|
||||
|
||||
class Permission : IComparable<Permission>
|
||||
{
|
||||
#region variables
|
||||
|
||||
readonly PermissionSection _section;
|
||||
readonly string _subItemName;
|
||||
|
||||
readonly ConcurrentDictionary<User, PermissionFlag> _userPermissions;
|
||||
readonly ConcurrentDictionary<Group, PermissionFlag> _groupPermissions;
|
||||
|
||||
readonly ConcurrentDictionary<string, Permission> _subItemPermissions;
|
||||
|
||||
#endregion
|
||||
|
||||
#region constructor
|
||||
|
||||
public Permission(PermissionSection section, string subItemName = null)
|
||||
{
|
||||
_section = section;
|
||||
_subItemName = subItemName;
|
||||
|
||||
_userPermissions = new ConcurrentDictionary<User, PermissionFlag>(1, 1);
|
||||
_groupPermissions = new ConcurrentDictionary<Group, PermissionFlag>(1, 1);
|
||||
|
||||
_subItemPermissions = new ConcurrentDictionary<string, Permission>(1, 1);
|
||||
}
|
||||
|
||||
public Permission(BinaryReader bR, AuthManager authManager)
|
||||
{
|
||||
switch (bR.ReadByte())
|
||||
{
|
||||
case 1:
|
||||
_section = (PermissionSection)bR.ReadByte();
|
||||
|
||||
{
|
||||
int count = bR.ReadByte();
|
||||
_userPermissions = new ConcurrentDictionary<User, PermissionFlag>(1, count);
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
User user = authManager.GetUser(bR.ReadShortString());
|
||||
PermissionFlag flag = (PermissionFlag)bR.ReadByte();
|
||||
|
||||
if (user is not null)
|
||||
_userPermissions.TryAdd(user, flag);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
int count = bR.ReadByte();
|
||||
_groupPermissions = new ConcurrentDictionary<Group, PermissionFlag>(1, count);
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
Group group = authManager.GetGroup(bR.ReadShortString());
|
||||
PermissionFlag flag = (PermissionFlag)bR.ReadByte();
|
||||
|
||||
if (group is not null)
|
||||
_groupPermissions.TryAdd(group, flag);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
int count = bR.ReadByte();
|
||||
_subItemPermissions = new ConcurrentDictionary<string, Permission>(1, count);
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
string subItemName = bR.ReadShortString();
|
||||
Permission subItemPermission = new Permission(bR, authManager);
|
||||
|
||||
_subItemPermissions.TryAdd(subItemName.ToLower(), subItemPermission);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new InvalidDataException("Invalid data or version not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region public
|
||||
|
||||
public void SetPermission(User user, PermissionFlag flags)
|
||||
{
|
||||
_userPermissions[user] = flags;
|
||||
}
|
||||
|
||||
public void SyncPermissions(IReadOnlyDictionary<User, PermissionFlag> userPermissions)
|
||||
{
|
||||
//remove non-existent permissions
|
||||
foreach (KeyValuePair<User, PermissionFlag> userPermission in _userPermissions)
|
||||
{
|
||||
if (!userPermissions.ContainsKey(userPermission.Key))
|
||||
_userPermissions.TryRemove(userPermission.Key, out _);
|
||||
}
|
||||
|
||||
//set new permissions
|
||||
foreach (KeyValuePair<User, PermissionFlag> userPermission in userPermissions)
|
||||
_userPermissions[userPermission.Key] = userPermission.Value;
|
||||
}
|
||||
|
||||
public void SetSubItemPermission(string subItemName, User user, PermissionFlag flags)
|
||||
{
|
||||
Permission subItemPermission = _subItemPermissions.GetOrAdd(subItemName.ToLower(), delegate (string key)
|
||||
{
|
||||
return new Permission(_section, key);
|
||||
});
|
||||
|
||||
subItemPermission.SetPermission(user, flags);
|
||||
}
|
||||
|
||||
public void SetPermission(Group group, PermissionFlag flags)
|
||||
{
|
||||
_groupPermissions[group] = flags;
|
||||
}
|
||||
|
||||
public void SyncPermissions(IReadOnlyDictionary<Group, PermissionFlag> groupPermissions)
|
||||
{
|
||||
//remove non-existent permissions
|
||||
foreach (KeyValuePair<Group, PermissionFlag> groupPermission in _groupPermissions)
|
||||
{
|
||||
if (!groupPermissions.ContainsKey(groupPermission.Key))
|
||||
_groupPermissions.TryRemove(groupPermission.Key, out _);
|
||||
}
|
||||
|
||||
//set new permissions
|
||||
foreach (KeyValuePair<Group, PermissionFlag> groupPermission in groupPermissions)
|
||||
_groupPermissions[groupPermission.Key] = groupPermission.Value;
|
||||
}
|
||||
|
||||
public void SetSubItemPermission(string subItemName, Group group, PermissionFlag flags)
|
||||
{
|
||||
Permission subItemPermission = _subItemPermissions.GetOrAdd(subItemName.ToLower(), delegate (string key)
|
||||
{
|
||||
return new Permission(_section, key);
|
||||
});
|
||||
|
||||
subItemPermission.SetPermission(group, flags);
|
||||
}
|
||||
|
||||
public bool RemovePermission(User user)
|
||||
{
|
||||
return _userPermissions.TryRemove(user, out _);
|
||||
}
|
||||
|
||||
public bool RemoveSubItemPermission(string subItemName, User user)
|
||||
{
|
||||
return _subItemPermissions.TryGetValue(subItemName.ToLower(), out Permission subItemPermission) && subItemPermission.RemovePermission(user);
|
||||
}
|
||||
|
||||
public bool RemovePermission(Group group)
|
||||
{
|
||||
return _groupPermissions.TryRemove(group, out _);
|
||||
}
|
||||
|
||||
public bool RemoveSubItemPermission(string subItemName, Group group)
|
||||
{
|
||||
return _subItemPermissions.TryGetValue(subItemName.ToLower(), out Permission subItemPermission) && subItemPermission.RemovePermission(group);
|
||||
}
|
||||
|
||||
public bool RemoveAllSubItemPermissions(User user)
|
||||
{
|
||||
bool removed = false;
|
||||
|
||||
foreach (KeyValuePair<string, Permission> subItemPermission in _subItemPermissions)
|
||||
{
|
||||
if (subItemPermission.Value.RemovePermission(user))
|
||||
removed = true;
|
||||
}
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
public bool RemoveAllSubItemPermissions(Group group)
|
||||
{
|
||||
bool removed = false;
|
||||
|
||||
foreach (KeyValuePair<string, Permission> subItemPermission in _subItemPermissions)
|
||||
{
|
||||
if (subItemPermission.Value.RemovePermission(group))
|
||||
removed = true;
|
||||
}
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
public bool RemoveAllSubItemPermissions(string subItemName)
|
||||
{
|
||||
return _subItemPermissions.TryRemove(subItemName, out _);
|
||||
}
|
||||
|
||||
public Permission GetSubItemPermission(string subItemName)
|
||||
{
|
||||
if (_subItemPermissions.TryGetValue(subItemName.ToLower(), out Permission subItemPermission))
|
||||
return subItemPermission;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool IsPermitted(User user, PermissionFlag flag)
|
||||
{
|
||||
if (_userPermissions.TryGetValue(user, out PermissionFlag userPermissions) && userPermissions.HasFlag(flag))
|
||||
return true;
|
||||
|
||||
foreach (Group group in user.MemberOfGroups)
|
||||
{
|
||||
if (_groupPermissions.TryGetValue(group, out PermissionFlag groupPermissions) && groupPermissions.HasFlag(flag))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsSubItemPermitted(string subItemName, User user, PermissionFlag flag)
|
||||
{
|
||||
return _subItemPermissions.TryGetValue(subItemName.ToLower(), out Permission subItemPermission) && subItemPermission.IsPermitted(user, flag);
|
||||
}
|
||||
|
||||
public void WriteTo(BinaryWriter bW)
|
||||
{
|
||||
bW.Write((byte)1);
|
||||
bW.Write((byte)_section);
|
||||
|
||||
{
|
||||
bW.Write(Convert.ToByte(_userPermissions.Count));
|
||||
|
||||
foreach (KeyValuePair<User, PermissionFlag> userPermission in _userPermissions)
|
||||
{
|
||||
bW.WriteShortString(userPermission.Key.Username);
|
||||
bW.Write((byte)userPermission.Value);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
bW.Write(Convert.ToByte(_groupPermissions.Count));
|
||||
|
||||
foreach (KeyValuePair<Group, PermissionFlag> groupPermission in _groupPermissions)
|
||||
{
|
||||
bW.WriteShortString(groupPermission.Key.Name);
|
||||
bW.Write((byte)groupPermission.Value);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
bW.Write(Convert.ToByte(_subItemPermissions.Count));
|
||||
|
||||
foreach (KeyValuePair<string, Permission> subItemPermission in _subItemPermissions)
|
||||
{
|
||||
bW.WriteShortString(subItemPermission.Key);
|
||||
subItemPermission.Value.WriteTo(bW);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int CompareTo(Permission other)
|
||||
{
|
||||
return _section.CompareTo(other._section);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region properties
|
||||
|
||||
public PermissionSection Section
|
||||
{ get { return _section; } }
|
||||
|
||||
public string SubItemName
|
||||
{ get { return _subItemName; } }
|
||||
|
||||
public IReadOnlyDictionary<User, PermissionFlag> UserPermissions
|
||||
{ get { return _userPermissions; } }
|
||||
|
||||
public IReadOnlyDictionary<Group, PermissionFlag> GroupPermissions
|
||||
{ get { return _groupPermissions; } }
|
||||
|
||||
public IReadOnlyDictionary<string, Permission> SubItemPermissions
|
||||
{ get { return _subItemPermissions; } }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
357
DnsServerCore/Auth/User.cs
Normal file
357
DnsServerCore/Auth/User.cs
Normal file
@@ -0,0 +1,357 @@
|
||||
/*
|
||||
Technitium DNS Server
|
||||
Copyright (C) 2022 Shreyas Zare (shreyas@technitium.com)
|
||||
|
||||
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/>.
|
||||
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using TechnitiumLibrary.IO;
|
||||
using TechnitiumLibrary.Net;
|
||||
|
||||
namespace DnsServerCore.Auth
|
||||
{
|
||||
enum UserPasswordHashType : byte
|
||||
{
|
||||
Unknown = 0,
|
||||
OldScheme = 1,
|
||||
PBKDF2_SHA256 = 2
|
||||
}
|
||||
|
||||
class User : IComparable<User>
|
||||
{
|
||||
#region variables
|
||||
|
||||
static readonly RandomNumberGenerator _rng = RandomNumberGenerator.Create();
|
||||
|
||||
public const int DEFAULT_ITERATIONS = 1000000;
|
||||
|
||||
string _displayName;
|
||||
string _username;
|
||||
UserPasswordHashType _passwordHashType;
|
||||
int _iterations;
|
||||
byte[] _salt;
|
||||
string _passwordHash;
|
||||
bool _disabled;
|
||||
int _sessionTimeoutSeconds = 30 * 60; //default 30 mins
|
||||
|
||||
DateTime _previousSessionLoggedOn;
|
||||
IPAddress _previousSessionRemoteAddress;
|
||||
DateTime _recentSessionLoggedOn;
|
||||
IPAddress _recentSessionRemoteAddress;
|
||||
|
||||
readonly ConcurrentDictionary<string, Group> _memberOfGroups;
|
||||
|
||||
#endregion
|
||||
|
||||
#region constructor
|
||||
|
||||
public User(string displayName, string username, string password, int iterations = DEFAULT_ITERATIONS)
|
||||
{
|
||||
DisplayName = displayName;
|
||||
Username = username;
|
||||
|
||||
ChangePassword(password, iterations);
|
||||
|
||||
_previousSessionRemoteAddress = IPAddress.Any;
|
||||
_recentSessionRemoteAddress = IPAddress.Any;
|
||||
|
||||
_memberOfGroups = new ConcurrentDictionary<string, Group>(1, 2);
|
||||
}
|
||||
|
||||
public User(BinaryReader bR, AuthManager authManager)
|
||||
{
|
||||
switch (bR.ReadByte())
|
||||
{
|
||||
case 1:
|
||||
_displayName = bR.ReadShortString();
|
||||
_username = bR.ReadShortString();
|
||||
_passwordHashType = (UserPasswordHashType)bR.ReadByte();
|
||||
_iterations = bR.ReadInt32();
|
||||
_salt = bR.ReadBuffer();
|
||||
_passwordHash = bR.ReadShortString();
|
||||
_disabled = bR.ReadBoolean();
|
||||
_sessionTimeoutSeconds = bR.ReadInt32();
|
||||
|
||||
_previousSessionLoggedOn = bR.ReadDateTime();
|
||||
_previousSessionRemoteAddress = IPAddressExtension.ReadFrom(bR);
|
||||
_recentSessionLoggedOn = bR.ReadDateTime();
|
||||
_recentSessionRemoteAddress = IPAddressExtension.ReadFrom(bR);
|
||||
|
||||
{
|
||||
int count = bR.ReadByte();
|
||||
_memberOfGroups = new ConcurrentDictionary<string, Group>(1, count);
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
Group group = authManager.GetGroup(bR.ReadShortString());
|
||||
if (group is not null)
|
||||
_memberOfGroups.TryAdd(group.Name.ToLower(), group);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new InvalidDataException("Invalid data or version not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region internal
|
||||
|
||||
internal void RenameGroup(string oldName)
|
||||
{
|
||||
if (_memberOfGroups.TryRemove(oldName.ToLower(), out Group renamedGroup))
|
||||
_memberOfGroups.TryAdd(renamedGroup.Name.ToLower(), renamedGroup);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region public
|
||||
|
||||
public string GetPasswordHashFor(string password)
|
||||
{
|
||||
switch (_passwordHashType)
|
||||
{
|
||||
case UserPasswordHashType.OldScheme:
|
||||
using (HMAC hmac = new HMACSHA256(Encoding.UTF8.GetBytes(password)))
|
||||
{
|
||||
return Convert.ToHexString(hmac.ComputeHash(Encoding.UTF8.GetBytes(_username))).ToLower();
|
||||
}
|
||||
|
||||
case UserPasswordHashType.PBKDF2_SHA256:
|
||||
return Convert.ToHexString(Rfc2898DeriveBytes.Pbkdf2(Encoding.UTF8.GetBytes(password), _salt, _iterations, HashAlgorithmName.SHA256, 32)).ToLower();
|
||||
|
||||
default:
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
|
||||
public void ChangePassword(string newPassword, int iterations = DEFAULT_ITERATIONS)
|
||||
{
|
||||
_passwordHashType = UserPasswordHashType.PBKDF2_SHA256;
|
||||
_iterations = iterations;
|
||||
|
||||
_salt = new byte[32];
|
||||
_rng.GetBytes(_salt);
|
||||
|
||||
_passwordHash = GetPasswordHashFor(newPassword);
|
||||
}
|
||||
|
||||
public void LoadOldSchemeCredentials(string passwordHash)
|
||||
{
|
||||
_passwordHashType = UserPasswordHashType.OldScheme;
|
||||
_passwordHash = passwordHash;
|
||||
}
|
||||
|
||||
public void LoggedInFrom(IPAddress remoteAddress)
|
||||
{
|
||||
_previousSessionLoggedOn = _recentSessionLoggedOn;
|
||||
_previousSessionRemoteAddress = _recentSessionRemoteAddress;
|
||||
|
||||
_recentSessionLoggedOn = DateTime.UtcNow;
|
||||
_recentSessionRemoteAddress = remoteAddress;
|
||||
}
|
||||
|
||||
public void AddToGroup(Group group)
|
||||
{
|
||||
if (_memberOfGroups.Count == 255)
|
||||
throw new InvalidOperationException("Cannot add user to group: user can be member of max 255 groups.");
|
||||
|
||||
_memberOfGroups.TryAdd(group.Name.ToLower(), group);
|
||||
}
|
||||
|
||||
public bool RemoveFromGroup(Group group)
|
||||
{
|
||||
if (group.Name.Equals("everyone", StringComparison.OrdinalIgnoreCase))
|
||||
throw new InvalidOperationException("Access was denied.");
|
||||
|
||||
return _memberOfGroups.TryRemove(group.Name.ToLower(), out _);
|
||||
}
|
||||
|
||||
public void SyncGroups(IReadOnlyDictionary<string, Group> groups)
|
||||
{
|
||||
//remove non-existent groups
|
||||
foreach (KeyValuePair<string, Group> group in _memberOfGroups)
|
||||
{
|
||||
if (!groups.ContainsKey(group.Key))
|
||||
_memberOfGroups.TryRemove(group.Key, out _);
|
||||
}
|
||||
|
||||
//set new groups
|
||||
foreach (KeyValuePair<string, Group> group in groups)
|
||||
_memberOfGroups[group.Key] = group.Value;
|
||||
}
|
||||
|
||||
public bool IsMemberOfGroup(Group group)
|
||||
{
|
||||
return _memberOfGroups.ContainsKey(group.Name.ToLower());
|
||||
}
|
||||
|
||||
public void WriteTo(BinaryWriter bW)
|
||||
{
|
||||
bW.Write((byte)1);
|
||||
bW.WriteShortString(_displayName);
|
||||
bW.WriteShortString(_username);
|
||||
bW.Write((byte)_passwordHashType);
|
||||
bW.Write(_iterations);
|
||||
bW.WriteBuffer(_salt);
|
||||
bW.WriteShortString(_passwordHash);
|
||||
bW.Write(_disabled);
|
||||
bW.Write(_sessionTimeoutSeconds);
|
||||
|
||||
bW.Write(_previousSessionLoggedOn);
|
||||
IPAddressExtension.WriteTo(_previousSessionRemoteAddress, bW);
|
||||
bW.Write(_recentSessionLoggedOn);
|
||||
IPAddressExtension.WriteTo(_recentSessionRemoteAddress, bW);
|
||||
|
||||
bW.Write(Convert.ToByte(_memberOfGroups.Count));
|
||||
|
||||
foreach (KeyValuePair<string, Group> group in _memberOfGroups)
|
||||
bW.WriteShortString(group.Value.Name.ToLower());
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj is not User other)
|
||||
return false;
|
||||
|
||||
return _username.Equals(other._username, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return base.GetHashCode();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return _username;
|
||||
}
|
||||
|
||||
public int CompareTo(User other)
|
||||
{
|
||||
return _username.CompareTo(other._username);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region properties
|
||||
|
||||
public string DisplayName
|
||||
{
|
||||
get { return _displayName; }
|
||||
set
|
||||
{
|
||||
if (value.Length > 255)
|
||||
throw new ArgumentException("Display name length cannot exceed 255 characters.", nameof(DisplayName));
|
||||
|
||||
_displayName = value;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(_displayName))
|
||||
_displayName = _username;
|
||||
}
|
||||
}
|
||||
|
||||
public string Username
|
||||
{
|
||||
get { return _username; }
|
||||
set
|
||||
{
|
||||
if (_passwordHashType == UserPasswordHashType.OldScheme)
|
||||
throw new InvalidOperationException("Cannot change username when using old password hash scheme. Change password once and try again.");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
throw new ArgumentException("Username cannot be null or empty.", nameof(Username));
|
||||
|
||||
if (value.Length > 255)
|
||||
throw new ArgumentException("Username length cannot exceed 255 characters.", nameof(Username));
|
||||
|
||||
foreach (char c in value)
|
||||
{
|
||||
if ((c >= 97) && (c <= 122)) //[a-z]
|
||||
continue;
|
||||
|
||||
if ((c >= 65) && (c <= 90)) //[A-Z]
|
||||
continue;
|
||||
|
||||
if ((c >= 48) && (c <= 57)) //[0-9]
|
||||
continue;
|
||||
|
||||
if (c == '-')
|
||||
continue;
|
||||
|
||||
if (c == '_')
|
||||
continue;
|
||||
|
||||
if (c == '.')
|
||||
continue;
|
||||
|
||||
throw new ArgumentException("Username can contain only alpha numeric, '-', '_', or '.' characters.", nameof(Username));
|
||||
}
|
||||
|
||||
_username = value.ToLower();
|
||||
}
|
||||
}
|
||||
|
||||
public UserPasswordHashType PasswordHashType
|
||||
{ get { return _passwordHashType; } }
|
||||
|
||||
public string PasswordHash
|
||||
{ get { return _passwordHash; } }
|
||||
|
||||
public bool Disabled
|
||||
{
|
||||
get { return _disabled; }
|
||||
set { _disabled = value; }
|
||||
}
|
||||
|
||||
public int SessionTimeoutSeconds
|
||||
{
|
||||
get { return _sessionTimeoutSeconds; }
|
||||
set
|
||||
{
|
||||
if ((value < 0) || (value > 604800))
|
||||
throw new ArgumentOutOfRangeException(nameof(SessionTimeoutSeconds), "Session timeout value must be between 0-604800 seconds.");
|
||||
|
||||
_sessionTimeoutSeconds = value;
|
||||
}
|
||||
}
|
||||
|
||||
public DateTime PreviousSessionLoggedOn
|
||||
{ get { return _previousSessionLoggedOn; } }
|
||||
|
||||
public IPAddress PreviousSessionRemoteAddress
|
||||
{ get { return _previousSessionRemoteAddress; } }
|
||||
|
||||
public DateTime RecentSessionLoggedOn
|
||||
{ get { return _recentSessionLoggedOn; } }
|
||||
|
||||
public IPAddress RecentSessionRemoteAddress
|
||||
{ get { return _recentSessionRemoteAddress; } }
|
||||
|
||||
public ICollection<Group> MemberOfGroups
|
||||
{ get { return _memberOfGroups.Values; } }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
179
DnsServerCore/Auth/UserSession.cs
Normal file
179
DnsServerCore/Auth/UserSession.cs
Normal file
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
Technitium DNS Server
|
||||
Copyright (C) 2022 Shreyas Zare (shreyas@technitium.com)
|
||||
|
||||
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/>.
|
||||
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Security.Cryptography;
|
||||
using TechnitiumLibrary.IO;
|
||||
using TechnitiumLibrary.Net;
|
||||
|
||||
namespace DnsServerCore.Auth
|
||||
{
|
||||
enum UserSessionType : byte
|
||||
{
|
||||
Unknown = 0,
|
||||
Standard = 1,
|
||||
ApiToken = 2
|
||||
}
|
||||
|
||||
class UserSession : IComparable<UserSession>
|
||||
{
|
||||
#region variables
|
||||
|
||||
static readonly RandomNumberGenerator _rng = RandomNumberGenerator.Create();
|
||||
|
||||
readonly string _token;
|
||||
readonly UserSessionType _type;
|
||||
readonly string _tokenName;
|
||||
readonly User _user;
|
||||
DateTime _lastSeen;
|
||||
IPAddress _lastSeenRemoteAddress;
|
||||
string _lastSeenUserAgent;
|
||||
|
||||
#endregion
|
||||
|
||||
#region constructor
|
||||
|
||||
public UserSession(UserSessionType type, string tokenName, User user, IPAddress remoteAddress, string lastSeenUserAgent)
|
||||
{
|
||||
if ((tokenName is not null) && (tokenName.Length > 255))
|
||||
throw new ArgumentOutOfRangeException(nameof(tokenName), "Token name length cannot exceed 255 characters.");
|
||||
|
||||
byte[] tokenBytes = new byte[32];
|
||||
_rng.GetBytes(tokenBytes);
|
||||
_token = Convert.ToHexString(tokenBytes).ToLower();
|
||||
|
||||
_type = type;
|
||||
_tokenName = tokenName;
|
||||
_user = user;
|
||||
_lastSeen = DateTime.UtcNow;
|
||||
_lastSeenRemoteAddress = remoteAddress;
|
||||
_lastSeenUserAgent = lastSeenUserAgent;
|
||||
|
||||
if ((_lastSeenUserAgent is not null) && (_lastSeenUserAgent.Length > 255))
|
||||
_lastSeenUserAgent = _lastSeenUserAgent.Substring(0, 255);
|
||||
}
|
||||
|
||||
public UserSession(BinaryReader bR, AuthManager authManager)
|
||||
{
|
||||
switch (bR.ReadByte())
|
||||
{
|
||||
case 1:
|
||||
_token = bR.ReadShortString();
|
||||
_type = (UserSessionType)bR.ReadByte();
|
||||
|
||||
_tokenName = bR.ReadShortString();
|
||||
if (_tokenName.Length == 0)
|
||||
_tokenName = null;
|
||||
|
||||
_user = authManager.GetUser(bR.ReadShortString());
|
||||
_lastSeen = bR.ReadDateTime();
|
||||
_lastSeenRemoteAddress = IPAddressExtension.ReadFrom(bR);
|
||||
|
||||
_lastSeenUserAgent = bR.ReadShortString();
|
||||
if (_lastSeenUserAgent.Length == 0)
|
||||
_lastSeenUserAgent = null;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new InvalidDataException("Invalid data or version not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region public
|
||||
|
||||
public void UpdateLastSeen(IPAddress remoteAddress, string lastSeenUserAgent)
|
||||
{
|
||||
_lastSeen = DateTime.UtcNow;
|
||||
_lastSeenRemoteAddress = remoteAddress;
|
||||
_lastSeenUserAgent = lastSeenUserAgent;
|
||||
|
||||
if ((_lastSeenUserAgent is not null) && (_lastSeenUserAgent.Length > 255))
|
||||
_lastSeenUserAgent = _lastSeenUserAgent.Substring(0, 255);
|
||||
}
|
||||
|
||||
public bool HasExpired()
|
||||
{
|
||||
if (_type == UserSessionType.ApiToken)
|
||||
return false;
|
||||
|
||||
if (_user.SessionTimeoutSeconds == 0)
|
||||
return false;
|
||||
|
||||
return _lastSeen.AddSeconds(_user.SessionTimeoutSeconds) < DateTime.UtcNow;
|
||||
}
|
||||
|
||||
public void WriteTo(BinaryWriter bW)
|
||||
{
|
||||
bW.Write((byte)1);
|
||||
bW.WriteShortString(_token);
|
||||
bW.Write((byte)_type);
|
||||
|
||||
if (_tokenName is null)
|
||||
bW.Write((byte)0);
|
||||
else
|
||||
bW.WriteShortString(_tokenName);
|
||||
|
||||
bW.WriteShortString(_user.Username);
|
||||
bW.Write(_lastSeen);
|
||||
_lastSeenRemoteAddress.WriteTo(bW);
|
||||
|
||||
if (_lastSeenUserAgent is null)
|
||||
bW.Write((byte)0);
|
||||
else
|
||||
bW.WriteShortString(_lastSeenUserAgent);
|
||||
}
|
||||
|
||||
public int CompareTo(UserSession other)
|
||||
{
|
||||
return other._lastSeen.CompareTo(_lastSeen);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region properties
|
||||
|
||||
public string Token
|
||||
{ get { return _token; } }
|
||||
|
||||
public UserSessionType Type
|
||||
{ get { return _type; } }
|
||||
|
||||
public string TokenName
|
||||
{ get { return _tokenName; } }
|
||||
|
||||
public User User
|
||||
{ get { return _user; } }
|
||||
|
||||
public DateTime LastSeen
|
||||
{ get { return _lastSeen; } }
|
||||
|
||||
public IPAddress LastSeenRemoteAddress
|
||||
{ get { return _lastSeenRemoteAddress; } }
|
||||
|
||||
public string LastSeenUserAgent
|
||||
{ get { return _lastSeenUserAgent; } }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
using DnsServerCore.Auth;
|
||||
using DnsServerCore.Dhcp.Options;
|
||||
using DnsServerCore.Dns.ZoneManagers;
|
||||
using DnsServerCore.Dns.Zones;
|
||||
@@ -69,6 +70,7 @@ namespace DnsServerCore.Dhcp
|
||||
readonly ConcurrentDictionary<string, Scope> _scopes = new ConcurrentDictionary<string, Scope>();
|
||||
|
||||
AuthZoneManager _authZoneManager;
|
||||
AuthManager _authManager;
|
||||
|
||||
ConcurrentDictionary<string, object> _modifiedDnsAuthZones = new ConcurrentDictionary<string, object>();
|
||||
readonly Timer _saveModifiedDnsAuthZonesTimer;
|
||||
@@ -760,16 +762,42 @@ namespace DnsServerCore.Dhcp
|
||||
{
|
||||
//zone does not exists; create new primary zone
|
||||
zoneInfo = _authZoneManager.CreatePrimaryZone(scope.DomainName, _authZoneManager.ServerDomain, false);
|
||||
log?.Write("DHCP Server create DNS primary zone '" + scope.DomainName + "'.");
|
||||
if (zoneInfo is null)
|
||||
{
|
||||
log?.Write("DHCP Server failed to create DNS primary zone '" + scope.DomainName + "'.");
|
||||
return;
|
||||
}
|
||||
|
||||
//set permissions
|
||||
_authManager.SetPermission(PermissionSection.Zones, zoneInfo.Name, _authManager.GetGroup(Group.ADMINISTRATORS), PermissionFlag.ViewModifyDelete);
|
||||
_authManager.SetPermission(PermissionSection.Zones, zoneInfo.Name, _authManager.GetGroup(Group.DNS_ADMINISTRATORS), PermissionFlag.ViewModifyDelete);
|
||||
_authManager.SetPermission(PermissionSection.Zones, zoneInfo.Name, _authManager.GetGroup(Group.DHCP_ADMINISTRATORS), PermissionFlag.ViewModifyDelete);
|
||||
_authManager.SaveConfigFile();
|
||||
|
||||
log?.Write("DHCP Server create DNS primary zone '" + zoneInfo.Name + "'.");
|
||||
_authZoneManager.SaveZoneFile(zoneInfo.Name);
|
||||
}
|
||||
else if (zoneInfo.Type != AuthZoneType.Primary)
|
||||
else if ((zoneInfo.Type != AuthZoneType.Primary) && (zoneInfo.Type != AuthZoneType.Forwarder))
|
||||
{
|
||||
if (zoneInfo.Name.Equals(scope.DomainName, StringComparison.OrdinalIgnoreCase))
|
||||
throw new DhcpServerException("Cannot update DNS zone '" + zoneInfo.Name + "': not a primary zone.");
|
||||
throw new DhcpServerException("Cannot update DNS zone '" + zoneInfo.Name + "': not a primary or a forwarder zone.");
|
||||
|
||||
//create new primary zone
|
||||
zoneInfo = _authZoneManager.CreatePrimaryZone(scope.DomainName, _authZoneManager.ServerDomain, false);
|
||||
log?.Write("DHCP Server create DNS primary zone '" + scope.DomainName + "'.");
|
||||
if (zoneInfo is null)
|
||||
{
|
||||
log?.Write("DHCP Server failed to create DNS primary zone '" + scope.DomainName + "'.");
|
||||
return;
|
||||
}
|
||||
|
||||
//set permissions
|
||||
_authManager.SetPermission(PermissionSection.Zones, zoneInfo.Name, _authManager.GetGroup(Group.ADMINISTRATORS), PermissionFlag.ViewModifyDelete);
|
||||
_authManager.SetPermission(PermissionSection.Zones, zoneInfo.Name, _authManager.GetGroup(Group.DNS_ADMINISTRATORS), PermissionFlag.ViewModifyDelete);
|
||||
_authManager.SetPermission(PermissionSection.Zones, zoneInfo.Name, _authManager.GetGroup(Group.DHCP_ADMINISTRATORS), PermissionFlag.ViewModifyDelete);
|
||||
_authManager.SaveConfigFile();
|
||||
|
||||
log?.Write("DHCP Server create DNS primary zone '" + zoneInfo.Name + "'.");
|
||||
_authZoneManager.SaveZoneFile(zoneInfo.Name);
|
||||
}
|
||||
|
||||
zoneName = zoneInfo.Name;
|
||||
@@ -803,18 +831,44 @@ namespace DnsServerCore.Dhcp
|
||||
|
||||
//reverse zone does not exists; create new reverse primary zone
|
||||
reverseZoneInfo = _authZoneManager.CreatePrimaryZone(reverseZone, _authZoneManager.ServerDomain, false);
|
||||
log?.Write("DHCP Server create DNS primary zone '" + reverseZone + "'.");
|
||||
if (reverseZoneInfo is null)
|
||||
{
|
||||
log?.Write("DHCP Server failed to create DNS primary zone '" + reverseZone + "'.");
|
||||
return;
|
||||
}
|
||||
|
||||
//set permissions
|
||||
_authManager.SetPermission(PermissionSection.Zones, reverseZoneInfo.Name, _authManager.GetGroup(Group.ADMINISTRATORS), PermissionFlag.ViewModifyDelete);
|
||||
_authManager.SetPermission(PermissionSection.Zones, reverseZoneInfo.Name, _authManager.GetGroup(Group.DNS_ADMINISTRATORS), PermissionFlag.ViewModifyDelete);
|
||||
_authManager.SetPermission(PermissionSection.Zones, reverseZoneInfo.Name, _authManager.GetGroup(Group.DHCP_ADMINISTRATORS), PermissionFlag.ViewModifyDelete);
|
||||
_authManager.SaveConfigFile();
|
||||
|
||||
log?.Write("DHCP Server create DNS primary zone '" + reverseZoneInfo.Name + "'.");
|
||||
_authZoneManager.SaveZoneFile(reverseZoneInfo.Name);
|
||||
}
|
||||
else if (reverseZoneInfo.Type != AuthZoneType.Primary)
|
||||
else if ((reverseZoneInfo.Type != AuthZoneType.Primary) && (reverseZoneInfo.Type != AuthZoneType.Forwarder))
|
||||
{
|
||||
string reverseZone = Zone.GetReverseZone(address, scope.SubnetMask);
|
||||
|
||||
if (reverseZoneInfo.Name.Equals(reverseZone, StringComparison.OrdinalIgnoreCase))
|
||||
throw new DhcpServerException("Cannot update reverse DNS zone '" + reverseZoneInfo.Name + "': not a primary zone.");
|
||||
throw new DhcpServerException("Cannot update reverse DNS zone '" + reverseZoneInfo.Name + "': not a primary or a forwarder zone.");
|
||||
|
||||
//create new reverse primary zone
|
||||
reverseZoneInfo = _authZoneManager.CreatePrimaryZone(reverseZone, _authZoneManager.ServerDomain, false);
|
||||
log?.Write("DHCP Server create DNS primary zone '" + reverseZone + "'.");
|
||||
if (reverseZoneInfo is null)
|
||||
{
|
||||
log?.Write("DHCP Server failed to create DNS primary zone '" + reverseZone + "'.");
|
||||
return;
|
||||
}
|
||||
|
||||
//set permissions
|
||||
_authManager.SetPermission(PermissionSection.Zones, reverseZoneInfo.Name, _authManager.GetGroup(Group.ADMINISTRATORS), PermissionFlag.ViewModifyDelete);
|
||||
_authManager.SetPermission(PermissionSection.Zones, reverseZoneInfo.Name, _authManager.GetGroup(Group.DNS_ADMINISTRATORS), PermissionFlag.ViewModifyDelete);
|
||||
_authManager.SetPermission(PermissionSection.Zones, reverseZoneInfo.Name, _authManager.GetGroup(Group.DHCP_ADMINISTRATORS), PermissionFlag.ViewModifyDelete);
|
||||
_authManager.SaveConfigFile();
|
||||
|
||||
log?.Write("DHCP Server create DNS primary zone '" + reverseZoneInfo.Name + "'.");
|
||||
_authZoneManager.SaveZoneFile(reverseZoneInfo.Name);
|
||||
}
|
||||
|
||||
reverseZoneName = reverseZoneInfo.Name;
|
||||
@@ -825,7 +879,7 @@ namespace DnsServerCore.Dhcp
|
||||
{
|
||||
//remove from forward zone
|
||||
AuthZoneInfo zoneInfo = _authZoneManager.FindAuthZoneInfo(domain);
|
||||
if ((zoneInfo is not null) && (zoneInfo.Type == AuthZoneType.Primary))
|
||||
if ((zoneInfo is not null) && ((zoneInfo.Type == AuthZoneType.Primary) || (zoneInfo.Type == AuthZoneType.Forwarder)))
|
||||
{
|
||||
//primary zone exists
|
||||
zoneName = zoneInfo.Name;
|
||||
@@ -835,7 +889,7 @@ namespace DnsServerCore.Dhcp
|
||||
|
||||
//remove from reverse zone
|
||||
AuthZoneInfo reverseZoneInfo = _authZoneManager.FindAuthZoneInfo(reverseDomain);
|
||||
if ((reverseZoneInfo != null) && (reverseZoneInfo.Type == AuthZoneType.Primary))
|
||||
if ((reverseZoneInfo != null) && ((reverseZoneInfo.Type == AuthZoneType.Primary) || (reverseZoneInfo.Type == AuthZoneType.Forwarder)))
|
||||
{
|
||||
//primary reverse zone exists
|
||||
reverseZoneName = reverseZoneInfo.Name;
|
||||
@@ -1397,6 +1451,12 @@ namespace DnsServerCore.Dhcp
|
||||
set { _authZoneManager = value; }
|
||||
}
|
||||
|
||||
internal AuthManager AuthManager
|
||||
{
|
||||
get { return _authManager; }
|
||||
set { _authManager = value; }
|
||||
}
|
||||
|
||||
public LogManager LogManager
|
||||
{
|
||||
get { return _log; }
|
||||
|
||||
@@ -88,7 +88,7 @@ namespace DnsServerCore.Dhcp
|
||||
_hostName = null;
|
||||
|
||||
_hardwareAddress = bR.ReadBuffer();
|
||||
_address = IPAddressExtension.Parse(bR);
|
||||
_address = IPAddressExtension.ReadFrom(bR);
|
||||
|
||||
if (version >= 2)
|
||||
{
|
||||
|
||||
@@ -120,7 +120,7 @@ namespace DnsServerCore.Dhcp
|
||||
_name = bR.ReadShortString();
|
||||
_enabled = bR.ReadBoolean();
|
||||
|
||||
ChangeNetwork(IPAddressExtension.Parse(bR), IPAddressExtension.Parse(bR), IPAddressExtension.Parse(bR));
|
||||
ChangeNetwork(IPAddressExtension.ReadFrom(bR), IPAddressExtension.ReadFrom(bR), IPAddressExtension.ReadFrom(bR));
|
||||
|
||||
_leaseTimeDays = bR.ReadUInt16();
|
||||
_leaseTimeHours = bR.ReadByte();
|
||||
@@ -143,7 +143,7 @@ namespace DnsServerCore.Dhcp
|
||||
|
||||
if (version >= 2)
|
||||
{
|
||||
_serverAddress = IPAddressExtension.Parse(bR);
|
||||
_serverAddress = IPAddressExtension.ReadFrom(bR);
|
||||
if (_serverAddress.Equals(IPAddress.Any))
|
||||
_serverAddress = null;
|
||||
}
|
||||
@@ -159,7 +159,7 @@ namespace DnsServerCore.Dhcp
|
||||
_bootFileName = null;
|
||||
}
|
||||
|
||||
_routerAddress = IPAddressExtension.Parse(bR);
|
||||
_routerAddress = IPAddressExtension.ReadFrom(bR);
|
||||
if (_routerAddress.Equals(IPAddress.Any))
|
||||
_routerAddress = null;
|
||||
|
||||
@@ -177,7 +177,7 @@ namespace DnsServerCore.Dhcp
|
||||
IPAddress[] dnsServers = new IPAddress[count];
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
dnsServers[i] = IPAddressExtension.Parse(bR);
|
||||
dnsServers[i] = IPAddressExtension.ReadFrom(bR);
|
||||
|
||||
_dnsServers = dnsServers;
|
||||
}
|
||||
@@ -191,7 +191,7 @@ namespace DnsServerCore.Dhcp
|
||||
IPAddress[] winsServers = new IPAddress[count];
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
winsServers[i] = IPAddressExtension.Parse(bR);
|
||||
winsServers[i] = IPAddressExtension.ReadFrom(bR);
|
||||
|
||||
_winsServers = winsServers;
|
||||
}
|
||||
@@ -204,7 +204,7 @@ namespace DnsServerCore.Dhcp
|
||||
IPAddress[] ntpServers = new IPAddress[count];
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
ntpServers[i] = IPAddressExtension.Parse(bR);
|
||||
ntpServers[i] = IPAddressExtension.ReadFrom(bR);
|
||||
|
||||
_ntpServers = ntpServers;
|
||||
}
|
||||
@@ -249,7 +249,7 @@ namespace DnsServerCore.Dhcp
|
||||
Exclusion[] exclusions = new Exclusion[count];
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
exclusions[i] = new Exclusion(IPAddressExtension.Parse(bR), IPAddressExtension.Parse(bR));
|
||||
exclusions[i] = new Exclusion(IPAddressExtension.ReadFrom(bR), IPAddressExtension.ReadFrom(bR));
|
||||
|
||||
_exclusions = exclusions;
|
||||
}
|
||||
@@ -455,7 +455,7 @@ namespace DnsServerCore.Dhcp
|
||||
|
||||
clientDomainName = request.HostName.HostName + "." + _domainName;
|
||||
}
|
||||
else if (request.ClientFullyQualifiedDomainName.DomainName.Contains("."))
|
||||
else if (request.ClientFullyQualifiedDomainName.DomainName.Contains('.'))
|
||||
{
|
||||
//client domain is fqdn
|
||||
if (request.ClientFullyQualifiedDomainName.DomainName.EndsWith("." + _domainName, StringComparison.OrdinalIgnoreCase))
|
||||
@@ -1161,6 +1161,19 @@ namespace DnsServerCore.Dhcp
|
||||
}
|
||||
}
|
||||
|
||||
public bool AddReservedLease(Lease reservedLease)
|
||||
{
|
||||
return _reservedLeases.TryAdd(reservedLease.ClientIdentifier, reservedLease);
|
||||
}
|
||||
|
||||
public bool RemoveReservedLease(string hardwareAddress)
|
||||
{
|
||||
byte[] hardwareAddressBytes = Lease.ParseHardwareAddress(hardwareAddress);
|
||||
ClientIdentifierOption reservedLeaseClientIdentifier = new ClientIdentifierOption((byte)DhcpMessageHardwareAddressType.Ethernet, hardwareAddressBytes);
|
||||
|
||||
return _reservedLeases.TryRemove(reservedLeaseClientIdentifier, out _);
|
||||
}
|
||||
|
||||
public Lease RemoveLease(string hardwareAddress)
|
||||
{
|
||||
byte[] hardwareAddressBytes = Lease.ParseHardwareAddress(hardwareAddress);
|
||||
@@ -1182,12 +1195,12 @@ namespace DnsServerCore.Dhcp
|
||||
if (removedLease.Type == LeaseType.Reserved)
|
||||
{
|
||||
//remove reserved lease
|
||||
ClientIdentifierOption reservedLeasesClientIdentifier = new ClientIdentifierOption((byte)DhcpMessageHardwareAddressType.Ethernet, removedLease.HardwareAddress);
|
||||
if (_reservedLeases.TryGetValue(reservedLeasesClientIdentifier, out Lease existingReservedLease))
|
||||
ClientIdentifierOption reservedLeaseClientIdentifier = new ClientIdentifierOption((byte)DhcpMessageHardwareAddressType.Ethernet, removedLease.HardwareAddress);
|
||||
if (_reservedLeases.TryGetValue(reservedLeaseClientIdentifier, out Lease existingReservedLease))
|
||||
{
|
||||
//remove reserved lease only if the IP addresses match
|
||||
if (existingReservedLease.Address.Equals(removedLease.Address))
|
||||
_reservedLeases.TryRemove(reservedLeasesClientIdentifier, out _);
|
||||
_reservedLeases.TryRemove(reservedLeaseClientIdentifier, out _);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1464,7 +1464,7 @@ namespace DnsServerCore.Dns
|
||||
{
|
||||
AuthZoneInfo zoneInfo = _authZoneManager.FindAuthZoneInfo(appResourceRecord.Name);
|
||||
|
||||
DnsDatagram appResponse = await appRecordRequestHandler.ProcessRequestAsync(request, remoteEP, protocol, isRecursionAllowed, zoneInfo.Name, appResourceRecord.TtlValue, appRecord.Data);
|
||||
DnsDatagram appResponse = await appRecordRequestHandler.ProcessRequestAsync(request, remoteEP, protocol, isRecursionAllowed, zoneInfo.Name, appResourceRecord.Name, appResourceRecord.TtlValue, appRecord.Data);
|
||||
if (appResponse is null)
|
||||
{
|
||||
//return no error response with SOA
|
||||
@@ -1540,7 +1540,7 @@ namespace DnsServerCore.Dns
|
||||
int queryCount = 0;
|
||||
do
|
||||
{
|
||||
DnsDatagram newRequest = new DnsDatagram(0, false, DnsOpcode.StandardQuery, false, false, request.RecursionDesired, false, false, false, DnsResponseCode.NoError, new DnsQuestionRecord[] { new DnsQuestionRecord((lastRR.RDATA as DnsCNAMERecordData).Domain, request.Question[0].Type, request.Question[0].Class) }, null, null, null, _udpPayloadSize, _dnssecValidation ? EDnsHeaderFlags.DNSSEC_OK : EDnsHeaderFlags.None);
|
||||
DnsDatagram newRequest = new DnsDatagram(0, false, DnsOpcode.StandardQuery, false, false, request.RecursionDesired, false, false, false, DnsResponseCode.NoError, new DnsQuestionRecord[] { new DnsQuestionRecord((lastRR.RDATA as DnsCNAMERecordData).Domain, request.Question[0].Type, request.Question[0].Class) }, null, null, null, _udpPayloadSize, request.DnssecOk ? EDnsHeaderFlags.DNSSEC_OK : EDnsHeaderFlags.None);
|
||||
|
||||
//query authoritative zone first
|
||||
newResponse = _authZoneManager.Query(newRequest, isRecursionAllowed);
|
||||
|
||||
@@ -1368,7 +1368,7 @@ namespace DnsServerCore.Dns
|
||||
_clientIpAddresses = new ConcurrentDictionary<IPAddress, Counter>(1, count);
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
_clientIpAddresses.TryAdd(IPAddressExtension.Parse(bR), new Counter(bR.ReadInt32()));
|
||||
_clientIpAddresses.TryAdd(IPAddressExtension.ReadFrom(bR), new Counter(bR.ReadInt32()));
|
||||
|
||||
if (version < 6)
|
||||
_totalClients = count;
|
||||
@@ -1393,7 +1393,7 @@ namespace DnsServerCore.Dns
|
||||
_errorIpAddresses = new ConcurrentDictionary<IPAddress, Counter>(1, count);
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
_errorIpAddresses.TryAdd(IPAddressExtension.Parse(bR), new Counter(bR.ReadInt32()));
|
||||
_errorIpAddresses.TryAdd(IPAddressExtension.ReadFrom(bR), new Counter(bR.ReadInt32()));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1697,9 +1697,6 @@ namespace DnsServerCore.Dns.ZoneManagers
|
||||
if (apexZone is StubZone)
|
||||
return GetReferralResponse(request, false, apexZone, apexZone, isRecursionAllowed);
|
||||
|
||||
if (apexZone is ForwarderZone)
|
||||
return GetForwarderResponse(request, null, closest, apexZone, isRecursionAllowed);
|
||||
|
||||
DnsResponseCode rCode = DnsResponseCode.NoError;
|
||||
IReadOnlyList<DnsResourceRecord> answer = null;
|
||||
IReadOnlyList<DnsResourceRecord> authority = null;
|
||||
@@ -1733,6 +1730,9 @@ namespace DnsServerCore.Dns.ZoneManagers
|
||||
authority = apexZone.QueryRecords(DnsResourceRecordType.APP, false);
|
||||
if (authority.Count == 0)
|
||||
{
|
||||
if (apexZone is ForwarderZone)
|
||||
return GetForwarderResponse(request, null, closest, apexZone, isRecursionAllowed); //no DNAME or APP record available so process FWD response
|
||||
|
||||
if (!hasSubDomains)
|
||||
rCode = DnsResponseCode.NxDomain;
|
||||
|
||||
@@ -1767,12 +1767,20 @@ namespace DnsServerCore.Dns.ZoneManagers
|
||||
else
|
||||
{
|
||||
//zone found
|
||||
if ((question.Type == DnsResourceRecordType.DS) && (zone is ApexZone))
|
||||
if (question.Type == DnsResourceRecordType.DS)
|
||||
{
|
||||
if (delegation is null || !delegation.IsActive || (delegation.Name.Length > apexZone.Name.Length))
|
||||
return null; //no authoritative parent side delegation zone available to answer for DS
|
||||
if (zone is ApexZone)
|
||||
{
|
||||
if (delegation is null || !delegation.IsActive || (delegation.Name.Length > apexZone.Name.Length))
|
||||
return null; //no authoritative parent side delegation zone available to answer for DS
|
||||
|
||||
zone = delegation; //switch zone to parent side sub domain delegation zone for DS record
|
||||
zone = delegation; //switch zone to parent side sub domain delegation zone for DS record
|
||||
}
|
||||
}
|
||||
else if (zone.Equals(delegation))
|
||||
{
|
||||
//zone is delegation
|
||||
return GetReferralResponse(request, dnssecOk, delegation, apexZone, isRecursionAllowed);
|
||||
}
|
||||
|
||||
IReadOnlyList<DnsResourceRecord> authority = null;
|
||||
@@ -1806,9 +1814,6 @@ namespace DnsServerCore.Dns.ZoneManagers
|
||||
|
||||
if (apexZone is StubZone)
|
||||
return GetReferralResponse(request, false, apexZone, apexZone, isRecursionAllowed);
|
||||
|
||||
if (apexZone is ForwarderZone)
|
||||
return GetForwarderResponse(request, zone, closest, apexZone, isRecursionAllowed);
|
||||
}
|
||||
|
||||
authority = zone.QueryRecords(DnsResourceRecordType.APP, false);
|
||||
@@ -1822,6 +1827,9 @@ namespace DnsServerCore.Dns.ZoneManagers
|
||||
authority = apexZone.QueryRecords(DnsResourceRecordType.APP, false);
|
||||
if (authority.Count == 0)
|
||||
{
|
||||
if (apexZone is ForwarderZone)
|
||||
return GetForwarderResponse(request, zone, closest, apexZone, isRecursionAllowed); //no APP record available so process FWD response
|
||||
|
||||
authority = apexZone.QueryRecords(DnsResourceRecordType.SOA, dnssecOk);
|
||||
|
||||
if (dnssecOk)
|
||||
|
||||
@@ -321,6 +321,7 @@ namespace DnsServerCore.Dns.ZoneManagers
|
||||
|
||||
SocketsHttpHandler handler = new SocketsHttpHandler();
|
||||
handler.Proxy = _dnsServer.Proxy;
|
||||
handler.UseProxy = _dnsServer.Proxy is not null;
|
||||
handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
|
||||
|
||||
using (HttpClient http = new HttpClient(handler))
|
||||
|
||||
@@ -110,7 +110,7 @@ namespace DnsServerCore.Dns.Zones
|
||||
IPAddress[] nameServers = new IPAddress[count];
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
nameServers[i] = IPAddressExtension.Parse(bR);
|
||||
nameServers[i] = IPAddressExtension.ReadFrom(bR);
|
||||
|
||||
_zoneTransferNameServers = nameServers;
|
||||
}
|
||||
@@ -125,7 +125,7 @@ namespace DnsServerCore.Dns.Zones
|
||||
IPAddress[] nameServers = new IPAddress[count];
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
nameServers[i] = IPAddressExtension.Parse(bR);
|
||||
nameServers[i] = IPAddressExtension.ReadFrom(bR);
|
||||
|
||||
_notifyNameServers = nameServers;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,6 @@ namespace DnsServerCore.Dns.Zones
|
||||
{
|
||||
case DnsResourceRecordType.SOA:
|
||||
case DnsResourceRecordType.DS:
|
||||
case DnsResourceRecordType.APP:
|
||||
throw new DnsServerException("The record type is not supported by forwarder zones.");
|
||||
|
||||
default:
|
||||
@@ -54,7 +53,6 @@ namespace DnsServerCore.Dns.Zones
|
||||
switch (record.Type)
|
||||
{
|
||||
case DnsResourceRecordType.DS:
|
||||
case DnsResourceRecordType.APP:
|
||||
throw new DnsServerException("The record type is not supported by forwarder zones.");
|
||||
|
||||
default:
|
||||
|
||||
@@ -61,7 +61,6 @@ namespace DnsServerCore.Dns.Zones
|
||||
|
||||
case DnsResourceRecordType.SOA:
|
||||
case DnsResourceRecordType.DS:
|
||||
case DnsResourceRecordType.APP:
|
||||
throw new DnsServerException("The record type is not supported by forwarder zones.");
|
||||
|
||||
default:
|
||||
@@ -75,7 +74,6 @@ namespace DnsServerCore.Dns.Zones
|
||||
switch (record.Type)
|
||||
{
|
||||
case DnsResourceRecordType.DS:
|
||||
case DnsResourceRecordType.APP:
|
||||
throw new DnsServerException("The record type is not supported by forwarder zones.");
|
||||
|
||||
default:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
Technitium DNS Server
|
||||
Copyright (C) 2019 Shreyas Zare (shreyas@technitium.com)
|
||||
|
||||
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/>.
|
||||
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace DnsServerCore
|
||||
{
|
||||
class UserSession
|
||||
{
|
||||
#region variables
|
||||
|
||||
const int SESSION_TIMEOUT = 30 * 60 * 1000; //30 mins
|
||||
|
||||
readonly string _username;
|
||||
DateTime _lastSeen;
|
||||
|
||||
#endregion
|
||||
|
||||
#region constructor
|
||||
|
||||
public UserSession(string username)
|
||||
{
|
||||
_username = username;
|
||||
_lastSeen = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region public
|
||||
|
||||
public void UpdateLastSeen()
|
||||
{
|
||||
_lastSeen = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
public bool HasExpired()
|
||||
{
|
||||
return _lastSeen.AddMilliseconds(SESSION_TIMEOUT) < DateTime.UtcNow;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region properties
|
||||
|
||||
public string Username
|
||||
{ get { return _username; } }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -25,13 +25,14 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using TechnitiumLibrary;
|
||||
using TechnitiumLibrary.IO;
|
||||
|
||||
namespace DnsServerCore
|
||||
{
|
||||
class WebServiceAppsApi
|
||||
sealed class WebServiceAppsApi : IDisposable
|
||||
{
|
||||
#region variables
|
||||
|
||||
@@ -42,6 +43,10 @@ namespace DnsServerCore
|
||||
DateTime _storeAppsJsonDataUpdatedOn;
|
||||
const int STORE_APPS_JSON_DATA_CACHE_TIME_SECONDS = 300;
|
||||
|
||||
Timer _appUpdateTimer;
|
||||
const int APP_UPDATE_TIMER_INITIAL_INTERVAL = 10000;
|
||||
const int APP_UPDATE_TIMER_PERIODIC_INTERVAL = 86400000;
|
||||
|
||||
#endregion
|
||||
|
||||
#region constructor
|
||||
@@ -54,14 +59,113 @@ namespace DnsServerCore
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDisposable
|
||||
|
||||
bool _disposed;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed)
|
||||
return;
|
||||
|
||||
if (_appUpdateTimer is not null)
|
||||
_appUpdateTimer.Dispose();
|
||||
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region private
|
||||
|
||||
private void StartAutomaticUpdate()
|
||||
{
|
||||
if (_appUpdateTimer is null)
|
||||
{
|
||||
_appUpdateTimer = new Timer(async delegate (object state)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_dnsWebService.DnsServer.DnsApplicationManager.Applications.Count < 1)
|
||||
return;
|
||||
|
||||
string storeAppsJsonData = await GetStoreAppsJsonData().WithTimeout(5000);
|
||||
dynamic jsonStoreAppsArray = JsonConvert.DeserializeObject(storeAppsJsonData);
|
||||
|
||||
foreach (DnsApplication application in _dnsWebService.DnsServer.DnsApplicationManager.Applications.Values)
|
||||
{
|
||||
foreach (dynamic jsonStoreApp in jsonStoreAppsArray)
|
||||
{
|
||||
string name = jsonStoreApp.name.Value;
|
||||
if (name.Equals(application.Name))
|
||||
{
|
||||
string url = null;
|
||||
Version storeAppVersion = null;
|
||||
Version lastServerVersion = null;
|
||||
|
||||
foreach (dynamic jsonVersion in jsonStoreApp.versions)
|
||||
{
|
||||
string strServerVersion = jsonVersion.serverVersion.Value;
|
||||
Version requiredServerVersion = new Version(strServerVersion);
|
||||
|
||||
if (_dnsWebService.ServerVersion < requiredServerVersion)
|
||||
continue;
|
||||
|
||||
if ((lastServerVersion is not null) && (lastServerVersion > requiredServerVersion))
|
||||
continue;
|
||||
|
||||
string version = jsonVersion.version.Value;
|
||||
url = jsonVersion.url.Value;
|
||||
|
||||
storeAppVersion = new Version(version);
|
||||
lastServerVersion = requiredServerVersion;
|
||||
}
|
||||
|
||||
if ((storeAppVersion is not null) && (storeAppVersion > application.Version))
|
||||
{
|
||||
try
|
||||
{
|
||||
await DownloadAndUpdateAppAsync(application.Name, url);
|
||||
|
||||
_dnsWebService.Log.Write("DNS application '" + application.Name + "' was automatically updated successfully from: " + url);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_dnsWebService.Log.Write("Failed to automatically download and update DNS application '" + application.Name + "': " + ex.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_dnsWebService.Log.Write(ex);
|
||||
}
|
||||
});
|
||||
|
||||
_appUpdateTimer.Change(APP_UPDATE_TIMER_INITIAL_INTERVAL, APP_UPDATE_TIMER_PERIODIC_INTERVAL);
|
||||
}
|
||||
}
|
||||
|
||||
private void StopAutomaticUpdate()
|
||||
{
|
||||
if (_appUpdateTimer is not null)
|
||||
{
|
||||
_appUpdateTimer.Dispose();
|
||||
_appUpdateTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<string> GetStoreAppsJsonData()
|
||||
{
|
||||
if ((_storeAppsJsonData == null) || (DateTime.UtcNow > _storeAppsJsonDataUpdatedOn.AddSeconds(STORE_APPS_JSON_DATA_CACHE_TIME_SECONDS)))
|
||||
{
|
||||
SocketsHttpHandler handler = new SocketsHttpHandler();
|
||||
handler.Proxy = _dnsWebService.DnsServer.Proxy;
|
||||
handler.UseProxy = _dnsWebService.DnsServer.Proxy is not null;
|
||||
handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
|
||||
|
||||
using (HttpClient http = new HttpClient(handler))
|
||||
@@ -74,6 +178,45 @@ namespace DnsServerCore
|
||||
return _storeAppsJsonData;
|
||||
}
|
||||
|
||||
private async Task DownloadAndUpdateAppAsync(string applicationName, string url)
|
||||
{
|
||||
string tmpFile = Path.GetTempFileName();
|
||||
try
|
||||
{
|
||||
using (FileStream fS = new FileStream(tmpFile, FileMode.Create, FileAccess.ReadWrite))
|
||||
{
|
||||
//download to temp file
|
||||
SocketsHttpHandler handler = new SocketsHttpHandler();
|
||||
handler.Proxy = _dnsWebService.DnsServer.Proxy;
|
||||
handler.UseProxy = _dnsWebService.DnsServer.Proxy is not null;
|
||||
handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
|
||||
|
||||
using (HttpClient http = new HttpClient(handler))
|
||||
{
|
||||
using (Stream httpStream = await http.GetStreamAsync(url))
|
||||
{
|
||||
await httpStream.CopyToAsync(fS);
|
||||
}
|
||||
}
|
||||
|
||||
//update app
|
||||
fS.Position = 0;
|
||||
await _dnsWebService.DnsServer.DnsApplicationManager.UpdateApplicationAsync(applicationName, fS);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(tmpFile);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_dnsWebService.Log.Write(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region public
|
||||
@@ -81,7 +224,6 @@ namespace DnsServerCore
|
||||
public async Task ListInstalledAppsAsync(JsonTextWriter jsonWriter)
|
||||
{
|
||||
List<string> apps = new List<string>(_dnsWebService.DnsServer.DnsApplicationManager.Applications.Keys);
|
||||
|
||||
apps.Sort();
|
||||
|
||||
dynamic jsonStoreAppsArray = null;
|
||||
@@ -119,8 +261,31 @@ namespace DnsServerCore
|
||||
string name = jsonStoreApp.name.Value;
|
||||
if (name.Equals(application.Name))
|
||||
{
|
||||
string version = jsonStoreApp.version.Value;
|
||||
string url = jsonStoreApp.url.Value;
|
||||
string version = null;
|
||||
string url = null;
|
||||
Version storeAppVersion = null;
|
||||
Version lastServerVersion = null;
|
||||
|
||||
foreach (dynamic jsonVersion in jsonStoreApp.versions)
|
||||
{
|
||||
string strServerVersion = jsonVersion.serverVersion.Value;
|
||||
Version requiredServerVersion = new Version(strServerVersion);
|
||||
|
||||
if (_dnsWebService.ServerVersion < requiredServerVersion)
|
||||
continue;
|
||||
|
||||
if ((lastServerVersion is not null) && (lastServerVersion > requiredServerVersion))
|
||||
continue;
|
||||
|
||||
version = jsonVersion.version.Value;
|
||||
url = jsonVersion.url.Value;
|
||||
|
||||
storeAppVersion = new Version(version);
|
||||
lastServerVersion = requiredServerVersion;
|
||||
}
|
||||
|
||||
if (storeAppVersion is null)
|
||||
break; //no compatible update available
|
||||
|
||||
jsonWriter.WritePropertyName("updateVersion");
|
||||
jsonWriter.WriteValue(version);
|
||||
@@ -129,7 +294,7 @@ namespace DnsServerCore
|
||||
jsonWriter.WriteValue(url);
|
||||
|
||||
jsonWriter.WritePropertyName("updateAvailable");
|
||||
jsonWriter.WriteValue(new Version(version) > application.Version);
|
||||
jsonWriter.WriteValue(storeAppVersion > application.Version);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -196,22 +361,46 @@ namespace DnsServerCore
|
||||
foreach (dynamic jsonStoreApp in jsonStoreAppsArray)
|
||||
{
|
||||
string name = jsonStoreApp.name.Value;
|
||||
string version = jsonStoreApp.version.Value;
|
||||
string description = jsonStoreApp.description.Value;
|
||||
string url = jsonStoreApp.url.Value;
|
||||
string size = jsonStoreApp.size.Value;
|
||||
string version = null;
|
||||
string url = null;
|
||||
string size = null;
|
||||
Version storeAppVersion = null;
|
||||
Version lastServerVersion = null;
|
||||
|
||||
foreach (dynamic jsonVersion in jsonStoreApp.versions)
|
||||
{
|
||||
string strServerVersion = jsonVersion.serverVersion.Value;
|
||||
Version requiredServerVersion = new Version(strServerVersion);
|
||||
|
||||
if (_dnsWebService.ServerVersion < requiredServerVersion)
|
||||
continue;
|
||||
|
||||
if ((lastServerVersion is not null) && (lastServerVersion > requiredServerVersion))
|
||||
continue;
|
||||
|
||||
version = jsonVersion.version.Value;
|
||||
url = jsonVersion.url.Value;
|
||||
size = jsonVersion.size.Value;
|
||||
|
||||
storeAppVersion = new Version(version);
|
||||
lastServerVersion = requiredServerVersion;
|
||||
}
|
||||
|
||||
if (storeAppVersion is null)
|
||||
continue; //app is not compatible
|
||||
|
||||
jsonWriter.WriteStartObject();
|
||||
|
||||
jsonWriter.WritePropertyName("name");
|
||||
jsonWriter.WriteValue(name);
|
||||
|
||||
jsonWriter.WritePropertyName("version");
|
||||
jsonWriter.WriteValue(version);
|
||||
|
||||
jsonWriter.WritePropertyName("description");
|
||||
jsonWriter.WriteValue(description);
|
||||
|
||||
jsonWriter.WritePropertyName("version");
|
||||
jsonWriter.WriteValue(version);
|
||||
|
||||
jsonWriter.WritePropertyName("url");
|
||||
jsonWriter.WriteValue(url);
|
||||
|
||||
@@ -229,7 +418,7 @@ namespace DnsServerCore
|
||||
jsonWriter.WriteValue(DnsWebService.GetCleanVersion(installedApp.Version));
|
||||
|
||||
jsonWriter.WritePropertyName("updateAvailable");
|
||||
jsonWriter.WriteValue(new Version(version) > installedApp.Version);
|
||||
jsonWriter.WriteValue(storeAppVersion > installedApp.Version);
|
||||
}
|
||||
|
||||
jsonWriter.WriteEndObject();
|
||||
@@ -261,6 +450,7 @@ namespace DnsServerCore
|
||||
//download to temp file
|
||||
SocketsHttpHandler handler = new SocketsHttpHandler();
|
||||
handler.Proxy = _dnsWebService.DnsServer.Proxy;
|
||||
handler.UseProxy = _dnsWebService.DnsServer.Proxy is not null;
|
||||
handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
|
||||
|
||||
using (HttpClient http = new HttpClient(handler))
|
||||
@@ -275,7 +465,7 @@ namespace DnsServerCore
|
||||
fS.Position = 0;
|
||||
await _dnsWebService.DnsServer.DnsApplicationManager.InstallApplicationAsync(name, fS);
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] DNS application '" + name + "' was installed successfully from: " + url);
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).User.Username + "] DNS application '" + name + "' was installed successfully from: " + url);
|
||||
}
|
||||
}
|
||||
finally
|
||||
@@ -306,42 +496,9 @@ namespace DnsServerCore
|
||||
if (!url.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
|
||||
throw new DnsWebServiceException("Parameter 'url' value must start with 'https://'.");
|
||||
|
||||
string tmpFile = Path.GetTempFileName();
|
||||
try
|
||||
{
|
||||
using (FileStream fS = new FileStream(tmpFile, FileMode.Create, FileAccess.ReadWrite))
|
||||
{
|
||||
//download to temp file
|
||||
SocketsHttpHandler handler = new SocketsHttpHandler();
|
||||
handler.Proxy = _dnsWebService.DnsServer.Proxy;
|
||||
handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
|
||||
await DownloadAndUpdateAppAsync(name, url);
|
||||
|
||||
using (HttpClient http = new HttpClient(handler))
|
||||
{
|
||||
using (Stream httpStream = await http.GetStreamAsync(url))
|
||||
{
|
||||
await httpStream.CopyToAsync(fS);
|
||||
}
|
||||
}
|
||||
|
||||
//update app
|
||||
fS.Position = 0;
|
||||
await _dnsWebService.DnsServer.DnsApplicationManager.UpdateApplicationAsync(name, fS);
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] DNS application '" + name + "' was updated successfully from: " + url);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(tmpFile);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_dnsWebService.Log.Write(ex);
|
||||
}
|
||||
}
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).User.Username + "] DNS application '" + name + "' was updated successfully from: " + url);
|
||||
}
|
||||
|
||||
public async Task InstallAppAsync(HttpListenerRequest request)
|
||||
@@ -387,7 +544,7 @@ namespace DnsServerCore
|
||||
fS.Position = 0;
|
||||
await _dnsWebService.DnsServer.DnsApplicationManager.InstallApplicationAsync(name, fS);
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] DNS application '" + name + "' was installed successfully.");
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).User.Username + "] DNS application '" + name + "' was installed successfully.");
|
||||
}
|
||||
}
|
||||
finally
|
||||
@@ -446,7 +603,7 @@ namespace DnsServerCore
|
||||
fS.Position = 0;
|
||||
await _dnsWebService.DnsServer.DnsApplicationManager.UpdateApplicationAsync(name, fS);
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] DNS application '" + name + "' was updated successfully.");
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).User.Username + "] DNS application '" + name + "' was updated successfully.");
|
||||
}
|
||||
}
|
||||
finally
|
||||
@@ -471,7 +628,7 @@ namespace DnsServerCore
|
||||
name = name.Trim();
|
||||
|
||||
_dnsWebService.DnsServer.DnsApplicationManager.UninstallApplication(name);
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] DNS application '" + name + "' was uninstalled successfully.");
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).User.Username + "] DNS application '" + name + "' was uninstalled successfully.");
|
||||
}
|
||||
|
||||
public async Task GetAppConfigAsync(HttpListenerRequest request, JsonTextWriter jsonWriter)
|
||||
@@ -514,14 +671,14 @@ namespace DnsServerCore
|
||||
{
|
||||
if (formPart.StartsWith("config="))
|
||||
{
|
||||
string config = formPart.Substring(7);
|
||||
string config = Uri.UnescapeDataString(formPart.Substring(7));
|
||||
|
||||
if (config.Length == 0)
|
||||
config = null;
|
||||
|
||||
await application.SetConfigAsync(config);
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] DNS application '" + name + "' app config was saved successfully.");
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).User.Username + "] DNS application '" + name + "' app config was saved successfully.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -530,5 +687,21 @@ namespace DnsServerCore
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region properties
|
||||
|
||||
public bool EnableAutomaticUpdate
|
||||
{
|
||||
get { return _appUpdateTimer is not null; }
|
||||
set
|
||||
{
|
||||
if (value)
|
||||
StartAutomaticUpdate();
|
||||
else
|
||||
StopAutomaticUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
1086
DnsServerCore/WebServiceAuthApi.cs
Normal file
1086
DnsServerCore/WebServiceAuthApi.cs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -638,13 +638,13 @@ namespace DnsServerCore
|
||||
{
|
||||
_dnsWebService.DhcpServer.SaveScope(scopeName);
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] DHCP scope was updated successfully: " + scopeName);
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).User.Username + "] DHCP scope was updated successfully: " + scopeName);
|
||||
}
|
||||
else
|
||||
{
|
||||
await _dnsWebService.DhcpServer.AddScopeAsync(scope);
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] DHCP scope was added successfully: " + scopeName);
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).User.Username + "] DHCP scope was added successfully: " + scopeName);
|
||||
}
|
||||
|
||||
string newName = request.QueryString["newName"];
|
||||
@@ -652,10 +652,64 @@ namespace DnsServerCore
|
||||
{
|
||||
_dnsWebService.DhcpServer.RenameScope(scopeName, newName);
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] DHCP scope was renamed successfully: '" + scopeName + "' to '" + newName + "'");
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).User.Username + "] DHCP scope was renamed successfully: '" + scopeName + "' to '" + newName + "'");
|
||||
}
|
||||
}
|
||||
|
||||
public void AddReservedLease(HttpListenerRequest request)
|
||||
{
|
||||
string scopeName = request.QueryString["name"];
|
||||
if (string.IsNullOrEmpty(scopeName))
|
||||
throw new DnsWebServiceException("Parameter 'name' missing.");
|
||||
|
||||
Scope scope = _dnsWebService.DhcpServer.GetScope(scopeName);
|
||||
if (scope is null)
|
||||
throw new DnsWebServiceException("No such scope exists: " + scopeName);
|
||||
|
||||
string hostName = request.QueryString["hostName"];
|
||||
|
||||
string hardwareAddress = request.QueryString["hardwareAddress"];
|
||||
if (string.IsNullOrEmpty(hardwareAddress))
|
||||
throw new DnsWebServiceException("Parameter 'hardwareAddress' missing.");
|
||||
|
||||
string strIpAddress = request.QueryString["ipAddress"];
|
||||
if (string.IsNullOrEmpty(strIpAddress))
|
||||
throw new DnsWebServiceException("Parameter 'ipAddress' missing.");
|
||||
|
||||
string comments = request.QueryString["comments"];
|
||||
|
||||
Lease reservedLease = new Lease(LeaseType.Reserved, hostName, DhcpMessageHardwareAddressType.Ethernet, hardwareAddress, IPAddress.Parse(strIpAddress), comments);
|
||||
|
||||
if (!scope.AddReservedLease(reservedLease))
|
||||
throw new DnsWebServiceException("Failed to add reserved lease for scope: " + scopeName);
|
||||
|
||||
_dnsWebService.DhcpServer.SaveScope(scopeName);
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).User.Username + "] DHCP scope reserved lease was added successfully: " + scopeName);
|
||||
}
|
||||
|
||||
public void RemoveReservedLease(HttpListenerRequest request)
|
||||
{
|
||||
string scopeName = request.QueryString["name"];
|
||||
if (string.IsNullOrEmpty(scopeName))
|
||||
throw new DnsWebServiceException("Parameter 'name' missing.");
|
||||
|
||||
Scope scope = _dnsWebService.DhcpServer.GetScope(scopeName);
|
||||
if (scope is null)
|
||||
throw new DnsWebServiceException("No such scope exists: " + scopeName);
|
||||
|
||||
string hardwareAddress = request.QueryString["hardwareAddress"];
|
||||
if (string.IsNullOrEmpty(hardwareAddress))
|
||||
throw new DnsWebServiceException("Parameter 'hardwareAddress' missing.");
|
||||
|
||||
if (!scope.RemoveReservedLease(hardwareAddress))
|
||||
throw new DnsWebServiceException("Failed to remove reserved lease for scope: " + scopeName);
|
||||
|
||||
_dnsWebService.DhcpServer.SaveScope(scopeName);
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).User.Username + "] DHCP scope reserved lease was removed successfully: " + scopeName);
|
||||
}
|
||||
|
||||
public async Task EnableDhcpScopeAsync(HttpListenerRequest request)
|
||||
{
|
||||
string scopeName = request.QueryString["name"];
|
||||
@@ -665,7 +719,7 @@ namespace DnsServerCore
|
||||
if (!await _dnsWebService.DhcpServer.EnableScopeAsync(scopeName))
|
||||
throw new DnsWebServiceException("Failed to enable DHCP scope, please check logs for details: " + scopeName);
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] DHCP scope was enabled successfully: " + scopeName);
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).User.Username + "] DHCP scope was enabled successfully: " + scopeName);
|
||||
}
|
||||
|
||||
public void DisableDhcpScope(HttpListenerRequest request)
|
||||
@@ -677,7 +731,7 @@ namespace DnsServerCore
|
||||
if (!_dnsWebService.DhcpServer.DisableScope(scopeName))
|
||||
throw new DnsWebServiceException("Failed to disable DHCP scope, please check logs for details: " + scopeName);
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] DHCP scope was disabled successfully: " + scopeName);
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).User.Username + "] DHCP scope was disabled successfully: " + scopeName);
|
||||
}
|
||||
|
||||
public void DeleteDhcpScope(HttpListenerRequest request)
|
||||
@@ -688,7 +742,7 @@ namespace DnsServerCore
|
||||
|
||||
_dnsWebService.DhcpServer.DeleteScope(scopeName);
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] DHCP scope was deleted successfully: " + scopeName);
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).User.Username + "] DHCP scope was deleted successfully: " + scopeName);
|
||||
}
|
||||
|
||||
public void RemoveDhcpLease(HttpListenerRequest request)
|
||||
@@ -713,7 +767,7 @@ namespace DnsServerCore
|
||||
|
||||
_dnsWebService.DhcpServer.SaveScope(scopeName);
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] DHCP scope's lease was removed successfully: " + scopeName);
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).User.Username + "] DHCP scope's lease was removed successfully: " + scopeName);
|
||||
}
|
||||
|
||||
public void ConvertToReservedLease(HttpListenerRequest request)
|
||||
@@ -738,7 +792,7 @@ namespace DnsServerCore
|
||||
|
||||
_dnsWebService.DhcpServer.SaveScope(scopeName);
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] DHCP scope's lease was reserved successfully: " + scopeName);
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).User.Username + "] DHCP scope's lease was reserved successfully: " + scopeName);
|
||||
}
|
||||
|
||||
public void ConvertToDynamicLease(HttpListenerRequest request)
|
||||
@@ -763,7 +817,7 @@ namespace DnsServerCore
|
||||
|
||||
_dnsWebService.DhcpServer.SaveScope(scopeName);
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] DHCP scope's lease was unreserved successfully: " + scopeName);
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).User.Username + "] DHCP scope's lease was unreserved successfully: " + scopeName);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Technitium DNS Server
|
||||
Copyright (C) 2021 Shreyas Zare (shreyas@technitium.com)
|
||||
Copyright (C) 2022 Shreyas Zare (shreyas@technitium.com)
|
||||
|
||||
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
|
||||
@@ -76,6 +76,22 @@ namespace DnsServerCore
|
||||
jsonWriter.WriteEndArray();
|
||||
}
|
||||
|
||||
public Task DownloadLogAsync(HttpListenerRequest request, HttpListenerResponse response)
|
||||
{
|
||||
string strFileName = request.QueryString["fileName"];
|
||||
if (string.IsNullOrEmpty(strFileName))
|
||||
throw new DnsWebServiceException("Parameter 'fileName' missing.");
|
||||
|
||||
int limit;
|
||||
string strLimit = request.QueryString["limit"];
|
||||
if (string.IsNullOrEmpty(strLimit))
|
||||
limit = 0;
|
||||
else
|
||||
limit = int.Parse(strLimit);
|
||||
|
||||
return _dnsWebService.Log.DownloadLogAsync(request, response, strFileName, limit * 1024 * 1024);
|
||||
}
|
||||
|
||||
public void DeleteLog(HttpListenerRequest request)
|
||||
{
|
||||
string log = request.QueryString["log"];
|
||||
@@ -84,21 +100,21 @@ namespace DnsServerCore
|
||||
|
||||
_dnsWebService.Log.DeleteLog(log);
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] Log file was deleted: " + log);
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).User.Username + "] Log file was deleted: " + log);
|
||||
}
|
||||
|
||||
public void DeleteAllLogs(HttpListenerRequest request)
|
||||
{
|
||||
_dnsWebService.Log.DeleteAllLogs();
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] All log files were deleted.");
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).User.Username + "] All log files were deleted.");
|
||||
}
|
||||
|
||||
public void DeleteAllStats(HttpListenerRequest request)
|
||||
{
|
||||
_dnsWebService.DnsServer.StatsManager.DeleteAllStats();
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] All stats files were deleted.");
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).User.Username + "] All stats files were deleted.");
|
||||
}
|
||||
|
||||
public async Task QueryLogsAsync(HttpListenerRequest request, JsonTextWriter jsonWriter)
|
||||
|
||||
@@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
using DnsServerCore.Dns.Zones;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
@@ -53,7 +54,7 @@ namespace DnsServerCore
|
||||
{
|
||||
_dnsWebService.DnsServer.CacheZoneManager.Flush();
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] Cache was flushed.");
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).User.Username + "] Cache was flushed.");
|
||||
}
|
||||
|
||||
public void ListCachedZones(HttpListenerRequest request, JsonTextWriter jsonWriter)
|
||||
@@ -128,7 +129,7 @@ namespace DnsServerCore
|
||||
throw new DnsWebServiceException("Parameter 'domain' missing.");
|
||||
|
||||
if (_dnsWebService.DnsServer.CacheZoneManager.DeleteZone(domain))
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] Cached zone was deleted: " + domain);
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).User.Username + "] Cached zone was deleted: " + domain);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -217,7 +218,8 @@ namespace DnsServerCore
|
||||
{
|
||||
if (formPart.StartsWith("allowedZones="))
|
||||
{
|
||||
string[] allowedZones = formPart.Substring(13).Split(',');
|
||||
string value = Uri.UnescapeDataString(formPart.Substring(13));
|
||||
string[] allowedZones = value.Split(',');
|
||||
bool added = false;
|
||||
|
||||
foreach (string allowedZone in allowedZones)
|
||||
@@ -228,7 +230,7 @@ namespace DnsServerCore
|
||||
|
||||
if (added)
|
||||
{
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] Total " + allowedZones.Length + " zones were imported into allowed zone successfully.");
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).User.Username + "] Total " + allowedZones.Length + " zones were imported into allowed zone successfully.");
|
||||
_dnsWebService.DnsServer.AllowedZoneManager.SaveZoneFile();
|
||||
}
|
||||
|
||||
@@ -261,7 +263,7 @@ namespace DnsServerCore
|
||||
|
||||
if (_dnsWebService.DnsServer.AllowedZoneManager.DeleteZone(domain))
|
||||
{
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] Allowed zone was deleted: " + domain);
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).User.Username + "] Allowed zone was deleted: " + domain);
|
||||
_dnsWebService.DnsServer.AllowedZoneManager.SaveZoneFile();
|
||||
}
|
||||
}
|
||||
@@ -270,7 +272,7 @@ namespace DnsServerCore
|
||||
{
|
||||
_dnsWebService.DnsServer.AllowedZoneManager.Flush();
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] Allowed zone was flushed successfully.");
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).User.Username + "] Allowed zone was flushed successfully.");
|
||||
_dnsWebService.DnsServer.AllowedZoneManager.SaveZoneFile();
|
||||
}
|
||||
|
||||
@@ -285,7 +287,7 @@ namespace DnsServerCore
|
||||
|
||||
if (_dnsWebService.DnsServer.AllowedZoneManager.AllowZone(domain))
|
||||
{
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] Zone was allowed: " + domain);
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).User.Username + "] Zone was allowed: " + domain);
|
||||
_dnsWebService.DnsServer.AllowedZoneManager.SaveZoneFile();
|
||||
}
|
||||
}
|
||||
@@ -376,7 +378,8 @@ namespace DnsServerCore
|
||||
{
|
||||
if (formPart.StartsWith("blockedZones="))
|
||||
{
|
||||
string[] blockedZones = formPart.Substring(13).Split(',');
|
||||
string value = Uri.UnescapeDataString(formPart.Substring(13));
|
||||
string[] blockedZones = value.Split(',');
|
||||
bool added = false;
|
||||
|
||||
foreach (string blockedZone in blockedZones)
|
||||
@@ -387,7 +390,7 @@ namespace DnsServerCore
|
||||
|
||||
if (added)
|
||||
{
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] Total " + blockedZones.Length + " zones were imported into blocked zone successfully.");
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).User.Username + "] Total " + blockedZones.Length + " zones were imported into blocked zone successfully.");
|
||||
_dnsWebService.DnsServer.BlockedZoneManager.SaveZoneFile();
|
||||
}
|
||||
|
||||
@@ -420,7 +423,7 @@ namespace DnsServerCore
|
||||
|
||||
if (_dnsWebService.DnsServer.BlockedZoneManager.DeleteZone(domain))
|
||||
{
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] Blocked zone was deleted: " + domain);
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).User.Username + "] Blocked zone was deleted: " + domain);
|
||||
_dnsWebService.DnsServer.BlockedZoneManager.SaveZoneFile();
|
||||
}
|
||||
}
|
||||
@@ -429,7 +432,7 @@ namespace DnsServerCore
|
||||
{
|
||||
_dnsWebService.DnsServer.BlockedZoneManager.Flush();
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] Blocked zone was flushed successfully.");
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).User.Username + "] Blocked zone was flushed successfully.");
|
||||
_dnsWebService.DnsServer.BlockedZoneManager.SaveZoneFile();
|
||||
}
|
||||
|
||||
@@ -444,7 +447,7 @@ namespace DnsServerCore
|
||||
|
||||
if (_dnsWebService.DnsServer.BlockedZoneManager.BlockZone(domain))
|
||||
{
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] Domain was added to blocked zone: " + domain);
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).User.Username + "] Domain was added to blocked zone: " + domain);
|
||||
_dnsWebService.DnsServer.BlockedZoneManager.SaveZoneFile();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
using DnsServerCore.Auth;
|
||||
using DnsServerCore.Dns;
|
||||
using DnsServerCore.Dns.Dnssec;
|
||||
using DnsServerCore.Dns.ResourceRecords;
|
||||
@@ -859,17 +860,23 @@ namespace DnsServerCore
|
||||
|
||||
#region public
|
||||
|
||||
public void ListZones(JsonTextWriter jsonWriter)
|
||||
public void ListZones(HttpListenerRequest request, JsonTextWriter jsonWriter)
|
||||
{
|
||||
List<AuthZoneInfo> zones = _dnsWebService.DnsServer.AuthZoneManager.ListZones();
|
||||
|
||||
zones.Sort();
|
||||
|
||||
UserSession session = _dnsWebService.GetSession(request);
|
||||
|
||||
jsonWriter.WritePropertyName("zones");
|
||||
jsonWriter.WriteStartArray();
|
||||
|
||||
foreach (AuthZoneInfo zone in zones)
|
||||
{
|
||||
if (!_dnsWebService.AuthManager.IsPermitted(PermissionSection.Zones, zone.Name, session.User, PermissionFlag.View))
|
||||
continue;
|
||||
|
||||
WriteZoneInfoAsJson(zone, jsonWriter);
|
||||
}
|
||||
|
||||
jsonWriter.WriteEndArray();
|
||||
}
|
||||
@@ -906,14 +913,27 @@ namespace DnsServerCore
|
||||
if (!string.IsNullOrEmpty(strType))
|
||||
type = Enum.Parse<AuthZoneType>(strType, true);
|
||||
|
||||
AuthZoneInfo zoneInfo;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case AuthZoneType.Primary:
|
||||
if (_dnsWebService.DnsServer.AuthZoneManager.CreatePrimaryZone(zoneName, _dnsWebService.DnsServer.ServerDomain, false) is null)
|
||||
throw new DnsWebServiceException("Zone already exists: " + zoneName);
|
||||
{
|
||||
zoneInfo = _dnsWebService.DnsServer.AuthZoneManager.CreatePrimaryZone(zoneName, _dnsWebService.DnsServer.ServerDomain, false);
|
||||
if (zoneInfo is null)
|
||||
throw new DnsWebServiceException("Zone already exists: " + zoneName);
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] Authoritative primary zone was created: " + zoneName);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneName);
|
||||
UserSession session = _dnsWebService.GetSession(request);
|
||||
|
||||
//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();
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + session.User.Username + "] Authoritative primary zone was created: " + zoneName);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneInfo.Name);
|
||||
}
|
||||
break;
|
||||
|
||||
case AuthZoneType.Secondary:
|
||||
@@ -934,11 +954,20 @@ namespace DnsServerCore
|
||||
if (string.IsNullOrEmpty(tsigKeyName))
|
||||
tsigKeyName = null;
|
||||
|
||||
if (await _dnsWebService.DnsServer.AuthZoneManager.CreateSecondaryZoneAsync(zoneName, primaryNameServerAddresses, zoneTransferProtocol, tsigKeyName) is null)
|
||||
zoneInfo = await _dnsWebService.DnsServer.AuthZoneManager.CreateSecondaryZoneAsync(zoneName, primaryNameServerAddresses, zoneTransferProtocol, tsigKeyName);
|
||||
if (zoneInfo is null)
|
||||
throw new DnsWebServiceException("Zone already exists: " + zoneName);
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] Authoritative secondary zone was created: " + zoneName);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneName);
|
||||
UserSession session = _dnsWebService.GetSession(request);
|
||||
|
||||
//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();
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + session.User.Username + "] Authoritative secondary zone was created: " + zoneName);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneInfo.Name);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -948,11 +977,20 @@ namespace DnsServerCore
|
||||
if (string.IsNullOrEmpty(strPrimaryNameServerAddresses))
|
||||
strPrimaryNameServerAddresses = null;
|
||||
|
||||
if (await _dnsWebService.DnsServer.AuthZoneManager.CreateStubZoneAsync(zoneName, strPrimaryNameServerAddresses) is null)
|
||||
zoneInfo = await _dnsWebService.DnsServer.AuthZoneManager.CreateStubZoneAsync(zoneName, strPrimaryNameServerAddresses);
|
||||
if (zoneInfo is null)
|
||||
throw new DnsWebServiceException("Zone already exists: " + zoneName);
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] Stub zone was created: " + zoneName);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneName);
|
||||
UserSession session = _dnsWebService.GetSession(request);
|
||||
|
||||
//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();
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + session.User.Username + "] Stub zone was created: " + zoneName);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneInfo.Name);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -997,11 +1035,20 @@ namespace DnsServerCore
|
||||
proxyPassword = request.QueryString["proxyPassword"];
|
||||
}
|
||||
|
||||
if (_dnsWebService.DnsServer.AuthZoneManager.CreateForwarderZone(zoneName, forwarderProtocol, strForwarder, dnssecValidation, proxyType, proxyAddress, proxyPort, proxyUsername, proxyPassword, null) is null)
|
||||
zoneInfo = _dnsWebService.DnsServer.AuthZoneManager.CreateForwarderZone(zoneName, forwarderProtocol, strForwarder, dnssecValidation, proxyType, proxyAddress, proxyPort, proxyUsername, proxyPassword, null);
|
||||
if (zoneInfo is null)
|
||||
throw new DnsWebServiceException("Zone already exists: " + zoneName);
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] Forwarder zone was created: " + zoneName);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneName);
|
||||
UserSession session = _dnsWebService.GetSession(request);
|
||||
|
||||
//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();
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + session.User.Username + "] Forwarder zone was created: " + zoneName);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneInfo.Name);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1010,10 +1057,10 @@ namespace DnsServerCore
|
||||
}
|
||||
|
||||
//delete cache for this zone to allow rebuilding cache data as needed by stub or forwarder zones
|
||||
_dnsWebService.DnsServer.CacheZoneManager.DeleteZone(zoneName);
|
||||
_dnsWebService.DnsServer.CacheZoneManager.DeleteZone(zoneInfo.Name);
|
||||
|
||||
jsonWriter.WritePropertyName("domain");
|
||||
jsonWriter.WriteValue(string.IsNullOrEmpty(zoneName) ? "." : zoneName);
|
||||
jsonWriter.WriteValue(string.IsNullOrEmpty(zoneInfo.Name) ? "." : zoneInfo.Name);
|
||||
}
|
||||
|
||||
public void SignPrimaryZone(HttpListenerRequest request)
|
||||
@@ -1024,6 +1071,11 @@ namespace DnsServerCore
|
||||
|
||||
zoneName = zoneName.TrimEnd('.');
|
||||
|
||||
UserSession session = _dnsWebService.GetSession(request);
|
||||
|
||||
if (!_dnsWebService.AuthManager.IsPermitted(PermissionSection.Zones, zoneName, session.User, PermissionFlag.Delete))
|
||||
throw new DnsWebServiceException("Access was denied.");
|
||||
|
||||
string algorithm = request.QueryString["algorithm"];
|
||||
if (string.IsNullOrEmpty(algorithm))
|
||||
throw new DnsWebServiceException("Parameter 'algorithm' missing.");
|
||||
@@ -1116,7 +1168,7 @@ namespace DnsServerCore
|
||||
throw new NotSupportedException("Algorithm is not supported: " + algorithm);
|
||||
}
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] Primary zone was signed successfully: " + zoneName);
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + session.User.Username + "] Primary zone was signed successfully: " + zoneName);
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneName);
|
||||
}
|
||||
@@ -1129,9 +1181,14 @@ namespace DnsServerCore
|
||||
|
||||
zoneName = zoneName.TrimEnd('.');
|
||||
|
||||
UserSession session = _dnsWebService.GetSession(request);
|
||||
|
||||
if (!_dnsWebService.AuthManager.IsPermitted(PermissionSection.Zones, zoneName, session.User, PermissionFlag.Delete))
|
||||
throw new DnsWebServiceException("Access was denied.");
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.UnsignPrimaryZone(zoneName);
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] Primary zone was unsigned successfully: " + zoneName);
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + session.User.Username + "] Primary zone was unsigned successfully: " + zoneName);
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneName);
|
||||
}
|
||||
@@ -1154,6 +1211,11 @@ namespace DnsServerCore
|
||||
if (zoneInfo.Type != AuthZoneType.Primary)
|
||||
throw new DnsWebServiceException("The zone must be a primary zone.");
|
||||
|
||||
UserSession session = _dnsWebService.GetSession(request);
|
||||
|
||||
if (!_dnsWebService.AuthManager.IsPermitted(PermissionSection.Zones, zoneInfo.Name, session.User, PermissionFlag.View))
|
||||
throw new DnsWebServiceException("Access was denied.");
|
||||
|
||||
jsonWriter.WritePropertyName("name");
|
||||
jsonWriter.WriteValue(zoneInfo.Name);
|
||||
|
||||
@@ -1254,9 +1316,14 @@ namespace DnsServerCore
|
||||
|
||||
zoneName = zoneName.TrimEnd('.');
|
||||
|
||||
UserSession session = _dnsWebService.GetSession(request);
|
||||
|
||||
if (!_dnsWebService.AuthManager.IsPermitted(PermissionSection.Zones, zoneName, session.User, PermissionFlag.Delete))
|
||||
throw new DnsWebServiceException("Access was denied.");
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.ConvertPrimaryZoneToNSEC(zoneName);
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] Primary zone was converted to NSEC successfully: " + zoneName);
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + session.User.Username + "] Primary zone was converted to NSEC successfully: " + zoneName);
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneName);
|
||||
}
|
||||
@@ -1269,6 +1336,11 @@ namespace DnsServerCore
|
||||
|
||||
zoneName = zoneName.TrimEnd('.');
|
||||
|
||||
UserSession session = _dnsWebService.GetSession(request);
|
||||
|
||||
if (!_dnsWebService.AuthManager.IsPermitted(PermissionSection.Zones, zoneName, session.User, PermissionFlag.Delete))
|
||||
throw new DnsWebServiceException("Access was denied.");
|
||||
|
||||
ushort iterations = 0;
|
||||
string strIterations = request.QueryString["iterations"];
|
||||
if (!string.IsNullOrEmpty(strIterations))
|
||||
@@ -1281,7 +1353,7 @@ namespace DnsServerCore
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.ConvertPrimaryZoneToNSEC3(zoneName, iterations, saltLength);
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] Primary zone was converted to NSEC3 successfully: " + zoneName);
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + session.User.Username + "] Primary zone was converted to NSEC3 successfully: " + zoneName);
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneName);
|
||||
}
|
||||
@@ -1294,6 +1366,11 @@ namespace DnsServerCore
|
||||
|
||||
zoneName = zoneName.TrimEnd('.');
|
||||
|
||||
UserSession session = _dnsWebService.GetSession(request);
|
||||
|
||||
if (!_dnsWebService.AuthManager.IsPermitted(PermissionSection.Zones, zoneName, session.User, PermissionFlag.Delete))
|
||||
throw new DnsWebServiceException("Access was denied.");
|
||||
|
||||
ushort iterations = 0;
|
||||
string strIterations = request.QueryString["iterations"];
|
||||
if (!string.IsNullOrEmpty(strIterations))
|
||||
@@ -1306,7 +1383,7 @@ namespace DnsServerCore
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.UpdatePrimaryZoneNSEC3Parameters(zoneName, iterations, saltLength);
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] Primary zone NSEC3 parameters were updated successfully: " + zoneName);
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + session.User.Username + "] Primary zone NSEC3 parameters were updated successfully: " + zoneName);
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneName);
|
||||
}
|
||||
@@ -1319,6 +1396,11 @@ namespace DnsServerCore
|
||||
|
||||
zoneName = zoneName.TrimEnd('.');
|
||||
|
||||
UserSession session = _dnsWebService.GetSession(request);
|
||||
|
||||
if (!_dnsWebService.AuthManager.IsPermitted(PermissionSection.Zones, zoneName, session.User, PermissionFlag.Delete))
|
||||
throw new DnsWebServiceException("Access was denied.");
|
||||
|
||||
string strDnsKeyTtl = request.QueryString["ttl"];
|
||||
if (string.IsNullOrEmpty(strDnsKeyTtl))
|
||||
throw new DnsWebServiceException("Parameter 'ttl' missing.");
|
||||
@@ -1327,7 +1409,7 @@ namespace DnsServerCore
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.UpdatePrimaryZoneDnsKeyTtl(zoneName, dnsKeyTtl);
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] Primary zone DNSKEY TTL was updated successfully: " + zoneName);
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + session.User.Username + "] Primary zone DNSKEY TTL was updated successfully: " + zoneName);
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneName);
|
||||
}
|
||||
@@ -1340,6 +1422,11 @@ namespace DnsServerCore
|
||||
|
||||
zoneName = zoneName.TrimEnd('.');
|
||||
|
||||
UserSession session = _dnsWebService.GetSession(request);
|
||||
|
||||
if (!_dnsWebService.AuthManager.IsPermitted(PermissionSection.Zones, zoneName, session.User, PermissionFlag.Delete))
|
||||
throw new DnsWebServiceException("Access was denied.");
|
||||
|
||||
string strKeyType = request.QueryString["keyType"];
|
||||
if (string.IsNullOrEmpty(strKeyType))
|
||||
throw new DnsWebServiceException("Parameter 'keyType' missing.");
|
||||
@@ -1385,7 +1472,7 @@ namespace DnsServerCore
|
||||
throw new NotSupportedException("Algorithm is not supported: " + algorithm);
|
||||
}
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] DNSSEC private key was generated and added to the primary zone successfully: " + zoneName);
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + session.User.Username + "] DNSSEC private key was generated and added to the primary zone successfully: " + zoneName);
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneName);
|
||||
}
|
||||
@@ -1398,6 +1485,11 @@ namespace DnsServerCore
|
||||
|
||||
zoneName = zoneName.TrimEnd('.');
|
||||
|
||||
UserSession session = _dnsWebService.GetSession(request);
|
||||
|
||||
if (!_dnsWebService.AuthManager.IsPermitted(PermissionSection.Zones, zoneName, session.User, PermissionFlag.Delete))
|
||||
throw new DnsWebServiceException("Access was denied.");
|
||||
|
||||
string strKeyTag = request.QueryString["keyTag"];
|
||||
if (string.IsNullOrEmpty(strKeyTag))
|
||||
throw new DnsWebServiceException("Parameter 'keyTag' missing.");
|
||||
@@ -1412,7 +1504,7 @@ namespace DnsServerCore
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.UpdatePrimaryZoneDnssecPrivateKey(zoneName, keyTag, rolloverDays);
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] Primary zone DNSSEC private key config was updated successfully: " + zoneName);
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + session.User.Username + "] Primary zone DNSSEC private key config was updated successfully: " + zoneName);
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneName);
|
||||
}
|
||||
@@ -1425,6 +1517,11 @@ namespace DnsServerCore
|
||||
|
||||
zoneName = zoneName.TrimEnd('.');
|
||||
|
||||
UserSession session = _dnsWebService.GetSession(request);
|
||||
|
||||
if (!_dnsWebService.AuthManager.IsPermitted(PermissionSection.Zones, zoneName, session.User, PermissionFlag.Delete))
|
||||
throw new DnsWebServiceException("Access was denied.");
|
||||
|
||||
string strKeyTag = request.QueryString["keyTag"];
|
||||
if (string.IsNullOrEmpty(strKeyTag))
|
||||
throw new DnsWebServiceException("Parameter 'keyTag' missing.");
|
||||
@@ -1433,7 +1530,7 @@ namespace DnsServerCore
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.DeletePrimaryZoneDnssecPrivateKey(zoneName, keyTag);
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] DNSSEC private key was deleted from primary zone successfully: " + zoneName);
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + session.User.Username + "] DNSSEC private key was deleted from primary zone successfully: " + zoneName);
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneName);
|
||||
}
|
||||
@@ -1446,9 +1543,14 @@ namespace DnsServerCore
|
||||
|
||||
zoneName = zoneName.TrimEnd('.');
|
||||
|
||||
UserSession session = _dnsWebService.GetSession(request);
|
||||
|
||||
if (!_dnsWebService.AuthManager.IsPermitted(PermissionSection.Zones, zoneName, session.User, PermissionFlag.Delete))
|
||||
throw new DnsWebServiceException("Access was denied.");
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.PublishAllGeneratedPrimaryZoneDnssecPrivateKeys(zoneName);
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] All DNSSEC private keys from the primary zone were published successfully: " + zoneName);
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + session.User.Username + "] All DNSSEC private keys from the primary zone were published successfully: " + zoneName);
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneName);
|
||||
}
|
||||
@@ -1461,6 +1563,11 @@ namespace DnsServerCore
|
||||
|
||||
zoneName = zoneName.TrimEnd('.');
|
||||
|
||||
UserSession session = _dnsWebService.GetSession(request);
|
||||
|
||||
if (!_dnsWebService.AuthManager.IsPermitted(PermissionSection.Zones, zoneName, session.User, PermissionFlag.Delete))
|
||||
throw new DnsWebServiceException("Access was denied.");
|
||||
|
||||
string strKeyTag = request.QueryString["keyTag"];
|
||||
if (string.IsNullOrEmpty(strKeyTag))
|
||||
throw new DnsWebServiceException("Parameter 'keyTag' missing.");
|
||||
@@ -1469,7 +1576,7 @@ namespace DnsServerCore
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.RolloverPrimaryZoneDnsKey(zoneName, keyTag);
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] The DNSKEY (" + keyTag + ") from the primary zone was rolled over successfully: " + zoneName);
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + session.User.Username + "] The DNSKEY (" + keyTag + ") from the primary zone was rolled over successfully: " + zoneName);
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneName);
|
||||
}
|
||||
@@ -1482,6 +1589,11 @@ namespace DnsServerCore
|
||||
|
||||
zoneName = zoneName.TrimEnd('.');
|
||||
|
||||
UserSession session = _dnsWebService.GetSession(request);
|
||||
|
||||
if (!_dnsWebService.AuthManager.IsPermitted(PermissionSection.Zones, zoneName, session.User, PermissionFlag.Delete))
|
||||
throw new DnsWebServiceException("Access was denied.");
|
||||
|
||||
string strKeyTag = request.QueryString["keyTag"];
|
||||
if (string.IsNullOrEmpty(strKeyTag))
|
||||
throw new DnsWebServiceException("Parameter 'keyTag' missing.");
|
||||
@@ -1490,7 +1602,7 @@ namespace DnsServerCore
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.RetirePrimaryZoneDnsKey(zoneName, keyTag);
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] The DNSKEY (" + keyTag + ") from the primary zone was retired successfully: " + zoneName);
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + session.User.Username + "] The DNSKEY (" + keyTag + ") from the primary zone was retired successfully: " + zoneName);
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneName);
|
||||
}
|
||||
@@ -1513,11 +1625,18 @@ namespace DnsServerCore
|
||||
if (zoneInfo.Internal)
|
||||
throw new DnsWebServiceException("Access was denied to manage internal DNS Server zone.");
|
||||
|
||||
if (!_dnsWebService.DnsServer.AuthZoneManager.DeleteZone(zoneName))
|
||||
throw new DnsWebServiceException("No authoritative zone was not found for domain: " + zoneName);
|
||||
UserSession session = _dnsWebService.GetSession(request);
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] " + zoneInfo.Type.ToString() + " zone was deleted: " + zoneName);
|
||||
if (!_dnsWebService.AuthManager.IsPermitted(PermissionSection.Zones, zoneInfo.Name, session.User, PermissionFlag.Delete))
|
||||
throw new DnsWebServiceException("Access was denied.");
|
||||
|
||||
if (!_dnsWebService.DnsServer.AuthZoneManager.DeleteZone(zoneInfo.Name))
|
||||
throw new DnsWebServiceException("No authoritative zone was not found for domain: " + zoneInfo.Name);
|
||||
|
||||
_dnsWebService.AuthManager.RemoveAllPermissions(PermissionSection.Zones, zoneInfo.Name);
|
||||
_dnsWebService.AuthManager.SaveConfigFile();
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + session.User.Username + "] " + zoneInfo.Type.ToString() + " zone was deleted: " + zoneName);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.DeleteZoneFile(zoneInfo.Name);
|
||||
}
|
||||
|
||||
@@ -1533,15 +1652,20 @@ namespace DnsServerCore
|
||||
zoneName = zoneName.TrimEnd('.');
|
||||
|
||||
AuthZoneInfo zoneInfo = _dnsWebService.DnsServer.AuthZoneManager.GetAuthZoneInfo(zoneName);
|
||||
if (zoneInfo == null)
|
||||
if (zoneInfo is null)
|
||||
throw new DnsWebServiceException("No authoritative zone was not found for domain: " + zoneName);
|
||||
|
||||
if (zoneInfo.Internal)
|
||||
throw new DnsWebServiceException("Access was denied to manage internal DNS Server zone.");
|
||||
|
||||
UserSession session = _dnsWebService.GetSession(request);
|
||||
|
||||
if (!_dnsWebService.AuthManager.IsPermitted(PermissionSection.Zones, zoneInfo.Name, session.User, PermissionFlag.Modify))
|
||||
throw new DnsWebServiceException("Access was denied.");
|
||||
|
||||
zoneInfo.Disabled = false;
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] " + zoneInfo.Type.ToString() + " zone was enabled: " + zoneInfo.Name);
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + session.User.Username + "] " + zoneInfo.Type.ToString() + " zone was enabled: " + zoneInfo.Name);
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneInfo.Name);
|
||||
|
||||
@@ -1561,15 +1685,20 @@ namespace DnsServerCore
|
||||
zoneName = zoneName.TrimEnd('.');
|
||||
|
||||
AuthZoneInfo zoneInfo = _dnsWebService.DnsServer.AuthZoneManager.GetAuthZoneInfo(zoneName);
|
||||
if (zoneInfo == null)
|
||||
if (zoneInfo is null)
|
||||
throw new DnsWebServiceException("No authoritative zone was not found for domain: " + zoneName);
|
||||
|
||||
if (zoneInfo.Internal)
|
||||
throw new DnsWebServiceException("Access was denied to manage internal DNS Server zone.");
|
||||
|
||||
UserSession session = _dnsWebService.GetSession(request);
|
||||
|
||||
if (!_dnsWebService.AuthManager.IsPermitted(PermissionSection.Zones, zoneInfo.Name, session.User, PermissionFlag.Modify))
|
||||
throw new DnsWebServiceException("Access was denied.");
|
||||
|
||||
zoneInfo.Disabled = true;
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] " + zoneInfo.Type.ToString() + " zone was disabled: " + zoneInfo.Name);
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + session.User.Username + "] " + zoneInfo.Type.ToString() + " zone was disabled: " + zoneInfo.Name);
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneInfo.Name);
|
||||
}
|
||||
@@ -1592,6 +1721,11 @@ namespace DnsServerCore
|
||||
if (zoneInfo.Internal)
|
||||
throw new DnsWebServiceException("Access was denied to manage internal DNS Server zone.");
|
||||
|
||||
UserSession session = _dnsWebService.GetSession(request);
|
||||
|
||||
if (!_dnsWebService.AuthManager.IsPermitted(PermissionSection.Zones, zoneInfo.Name, session.User, PermissionFlag.View))
|
||||
throw new DnsWebServiceException("Access was denied.");
|
||||
|
||||
jsonWriter.WritePropertyName("name");
|
||||
jsonWriter.WriteValue(zoneInfo.Name);
|
||||
|
||||
@@ -1688,12 +1822,17 @@ namespace DnsServerCore
|
||||
zoneName = zoneName.TrimEnd('.');
|
||||
|
||||
AuthZoneInfo zoneInfo = _dnsWebService.DnsServer.AuthZoneManager.GetAuthZoneInfo(zoneName);
|
||||
if (zoneInfo == null)
|
||||
if (zoneInfo is null)
|
||||
throw new DnsWebServiceException("No authoritative zone was not found for domain: " + zoneName);
|
||||
|
||||
if (zoneInfo.Internal)
|
||||
throw new DnsWebServiceException("Access was denied to manage internal DNS Server zone.");
|
||||
|
||||
UserSession session = _dnsWebService.GetSession(request);
|
||||
|
||||
if (!_dnsWebService.AuthManager.IsPermitted(PermissionSection.Zones, zoneInfo.Name, session.User, PermissionFlag.Delete))
|
||||
throw new DnsWebServiceException("Access was denied.");
|
||||
|
||||
string strDisabled = request.QueryString["disabled"];
|
||||
if (!string.IsNullOrEmpty(strDisabled))
|
||||
zoneInfo.Disabled = bool.Parse(strDisabled);
|
||||
@@ -1763,26 +1902,34 @@ namespace DnsServerCore
|
||||
}
|
||||
}
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] " + zoneInfo.Type.ToString() + " zone options were updated successfully: " + zoneInfo.Name);
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + session.User.Username + "] " + zoneInfo.Type.ToString() + " zone options were updated successfully: " + zoneInfo.Name);
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneInfo.Name);
|
||||
}
|
||||
|
||||
public void ResyncZone(HttpListenerRequest request)
|
||||
{
|
||||
string domain = request.QueryString["domain"];
|
||||
if (string.IsNullOrEmpty(domain))
|
||||
throw new DnsWebServiceException("Parameter 'domain' missing.");
|
||||
string zoneName = request.QueryString["zone"];
|
||||
if (string.IsNullOrEmpty(zoneName))
|
||||
zoneName = request.QueryString["domain"];
|
||||
|
||||
domain = domain.TrimEnd('.');
|
||||
if (string.IsNullOrEmpty(zoneName))
|
||||
throw new DnsWebServiceException("Parameter 'zone' missing.");
|
||||
|
||||
AuthZoneInfo zoneInfo = _dnsWebService.DnsServer.AuthZoneManager.GetAuthZoneInfo(domain);
|
||||
if (zoneInfo == null)
|
||||
throw new DnsWebServiceException("No authoritative zone was not found for domain: " + domain);
|
||||
zoneName = zoneName.TrimEnd('.');
|
||||
|
||||
AuthZoneInfo zoneInfo = _dnsWebService.DnsServer.AuthZoneManager.GetAuthZoneInfo(zoneName);
|
||||
if (zoneInfo is null)
|
||||
throw new DnsWebServiceException("No authoritative zone was not found for domain: " + zoneName);
|
||||
|
||||
if (zoneInfo.Internal)
|
||||
throw new DnsWebServiceException("Access was denied to manage internal DNS Server zone.");
|
||||
|
||||
UserSession session = _dnsWebService.GetSession(request);
|
||||
|
||||
if (!_dnsWebService.AuthManager.IsPermitted(PermissionSection.Zones, zoneInfo.Name, session.User, PermissionFlag.Modify))
|
||||
throw new DnsWebServiceException("Access was denied.");
|
||||
|
||||
switch (zoneInfo.Type)
|
||||
{
|
||||
case AuthZoneType.Secondary:
|
||||
@@ -1814,8 +1961,10 @@ namespace DnsServerCore
|
||||
if (zoneInfo.Internal)
|
||||
throw new DnsWebServiceException("Access was denied to manage internal DNS Server zone.");
|
||||
|
||||
if (string.IsNullOrEmpty(zoneName))
|
||||
zoneName = zoneInfo.Name;
|
||||
UserSession session = _dnsWebService.GetSession(request);
|
||||
|
||||
if (!_dnsWebService.AuthManager.IsPermitted(PermissionSection.Zones, zoneInfo.Name, session.User, PermissionFlag.Modify))
|
||||
throw new DnsWebServiceException("Access was denied.");
|
||||
|
||||
string strType = request.QueryString["type"];
|
||||
if (string.IsNullOrEmpty(strType))
|
||||
@@ -1872,7 +2021,7 @@ namespace DnsServerCore
|
||||
string ptrDomain = Zone.GetReverseZone(ipAddress, type == DnsResourceRecordType.A ? 32 : 128);
|
||||
|
||||
AuthZoneInfo reverseZoneInfo = _dnsWebService.DnsServer.AuthZoneManager.FindAuthZoneInfo(ptrDomain);
|
||||
if (reverseZoneInfo == null)
|
||||
if (reverseZoneInfo is null)
|
||||
{
|
||||
bool createPtrZone = false;
|
||||
string strCreatePtrZone = request.QueryString["createPtrZone"];
|
||||
@@ -1887,6 +2036,12 @@ namespace DnsServerCore
|
||||
reverseZoneInfo = _dnsWebService.DnsServer.AuthZoneManager.CreatePrimaryZone(ptrZone, _dnsWebService.DnsServer.ServerDomain, false);
|
||||
if (reverseZoneInfo == null)
|
||||
throw new DnsServerException("Failed to create reverse zone to add PTR record: " + ptrZone);
|
||||
|
||||
//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();
|
||||
}
|
||||
|
||||
if (reverseZoneInfo.Internal)
|
||||
@@ -1908,9 +2063,9 @@ namespace DnsServerCore
|
||||
newRecord.SetComments(comments);
|
||||
|
||||
if (overwrite)
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneName, newRecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneInfo.Name, newRecord);
|
||||
else
|
||||
_dnsWebService.DnsServer.AuthZoneManager.AddRecord(zoneName, newRecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.AddRecord(zoneInfo.Name, newRecord);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1938,9 +2093,9 @@ namespace DnsServerCore
|
||||
newRecord.SetComments(comments);
|
||||
|
||||
if (overwrite)
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneName, newRecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneInfo.Name, newRecord);
|
||||
else
|
||||
_dnsWebService.DnsServer.AuthZoneManager.AddRecord(zoneName, newRecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.AddRecord(zoneInfo.Name, newRecord);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1948,7 +2103,7 @@ namespace DnsServerCore
|
||||
{
|
||||
if (!overwrite)
|
||||
{
|
||||
IReadOnlyList<DnsResourceRecord> existingRecords = _dnsWebService.DnsServer.AuthZoneManager.GetRecords(zoneName, domain, type);
|
||||
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 records.");
|
||||
}
|
||||
@@ -1967,7 +2122,7 @@ namespace DnsServerCore
|
||||
if (!string.IsNullOrEmpty(comments))
|
||||
newRecord.SetComments(comments);
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneName, newRecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneInfo.Name, newRecord);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1988,9 +2143,9 @@ namespace DnsServerCore
|
||||
newRecord.SetComments(comments);
|
||||
|
||||
if (overwrite)
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneName, newRecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneInfo.Name, newRecord);
|
||||
else
|
||||
_dnsWebService.DnsServer.AuthZoneManager.AddRecord(zoneName, newRecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.AddRecord(zoneInfo.Name, newRecord);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2015,9 +2170,9 @@ namespace DnsServerCore
|
||||
newRecord.SetComments(comments);
|
||||
|
||||
if (overwrite)
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneName, newRecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneInfo.Name, newRecord);
|
||||
else
|
||||
_dnsWebService.DnsServer.AuthZoneManager.AddRecord(zoneName, newRecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.AddRecord(zoneInfo.Name, newRecord);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2038,9 +2193,9 @@ namespace DnsServerCore
|
||||
newRecord.SetComments(comments);
|
||||
|
||||
if (overwrite)
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneName, newRecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneInfo.Name, newRecord);
|
||||
else
|
||||
_dnsWebService.DnsServer.AuthZoneManager.AddRecord(zoneName, newRecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.AddRecord(zoneInfo.Name, newRecord);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2073,9 +2228,9 @@ namespace DnsServerCore
|
||||
newRecord.SetComments(comments);
|
||||
|
||||
if (overwrite)
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneName, newRecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneInfo.Name, newRecord);
|
||||
else
|
||||
_dnsWebService.DnsServer.AuthZoneManager.AddRecord(zoneName, newRecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.AddRecord(zoneInfo.Name, newRecord);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2083,7 +2238,7 @@ namespace DnsServerCore
|
||||
{
|
||||
if (!overwrite)
|
||||
{
|
||||
IReadOnlyList<DnsResourceRecord> existingRecords = _dnsWebService.DnsServer.AuthZoneManager.GetRecords(zoneName, domain, type);
|
||||
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 records.");
|
||||
}
|
||||
@@ -2102,7 +2257,7 @@ namespace DnsServerCore
|
||||
if (!string.IsNullOrEmpty(comments))
|
||||
newRecord.SetComments(comments);
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneName, newRecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneInfo.Name, newRecord);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2135,9 +2290,9 @@ namespace DnsServerCore
|
||||
newRecord.SetComments(comments);
|
||||
|
||||
if (overwrite)
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneName, newRecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneInfo.Name, newRecord);
|
||||
else
|
||||
_dnsWebService.DnsServer.AuthZoneManager.AddRecord(zoneName, newRecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.AddRecord(zoneInfo.Name, newRecord);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2160,9 +2315,9 @@ namespace DnsServerCore
|
||||
newRecord.SetComments(comments);
|
||||
|
||||
if (overwrite)
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneName, newRecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneInfo.Name, newRecord);
|
||||
else
|
||||
_dnsWebService.DnsServer.AuthZoneManager.AddRecord(zoneName, newRecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.AddRecord(zoneInfo.Name, newRecord);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2183,9 +2338,9 @@ namespace DnsServerCore
|
||||
newRecord.SetComments(comments);
|
||||
|
||||
if (overwrite)
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneName, newRecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneInfo.Name, newRecord);
|
||||
else
|
||||
_dnsWebService.DnsServer.AuthZoneManager.AddRecord(zoneName, newRecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.AddRecord(zoneInfo.Name, newRecord);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2244,9 +2399,9 @@ namespace DnsServerCore
|
||||
newRecord.SetComments(comments);
|
||||
|
||||
if (overwrite)
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneName, newRecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneInfo.Name, newRecord);
|
||||
else
|
||||
_dnsWebService.DnsServer.AuthZoneManager.AddRecord(zoneName, newRecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.AddRecord(zoneInfo.Name, newRecord);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2271,7 +2426,7 @@ namespace DnsServerCore
|
||||
|
||||
if (!overwrite)
|
||||
{
|
||||
IReadOnlyList<DnsResourceRecord> existingRecords = _dnsWebService.DnsServer.AuthZoneManager.GetRecords(zoneName, domain, type);
|
||||
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 records.");
|
||||
}
|
||||
@@ -2281,7 +2436,7 @@ namespace DnsServerCore
|
||||
if (!string.IsNullOrEmpty(comments))
|
||||
newRecord.SetComments(comments);
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneName, newRecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneInfo.Name, newRecord);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2289,7 +2444,7 @@ namespace DnsServerCore
|
||||
throw new DnsWebServiceException("Type not supported for AddRecords().");
|
||||
}
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] New record was added to authoritative zone {domain: " + domain + "; type: " + type + "; value: " + value + "; ttl: " + ttl + ";}");
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + session.User.Username + "] New record was added to authoritative zone {domain: " + domain + "; type: " + type + "; value: " + value + "; ttl: " + ttl + ";}");
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneInfo.Name);
|
||||
|
||||
@@ -2312,6 +2467,11 @@ namespace DnsServerCore
|
||||
if (zoneInfo is null)
|
||||
throw new DnsWebServiceException("No authoritative zone was not found for domain: " + domain);
|
||||
|
||||
UserSession session = _dnsWebService.GetSession(request);
|
||||
|
||||
if (!_dnsWebService.AuthManager.IsPermitted(PermissionSection.Zones, zoneInfo.Name, session.User, PermissionFlag.View))
|
||||
throw new DnsWebServiceException("Access was denied.");
|
||||
|
||||
jsonWriter.WritePropertyName("zone");
|
||||
WriteZoneInfoAsJson(zoneInfo, jsonWriter);
|
||||
|
||||
@@ -2340,8 +2500,10 @@ namespace DnsServerCore
|
||||
if (zoneInfo.Internal)
|
||||
throw new DnsWebServiceException("Access was denied to manage internal DNS Server zone.");
|
||||
|
||||
if (string.IsNullOrEmpty(zoneName))
|
||||
zoneName = zoneInfo.Name;
|
||||
UserSession session = _dnsWebService.GetSession(request);
|
||||
|
||||
if (!_dnsWebService.AuthManager.IsPermitted(PermissionSection.Zones, zoneInfo.Name, session.User, PermissionFlag.Delete))
|
||||
throw new DnsWebServiceException("Access was denied.");
|
||||
|
||||
string strType = request.QueryString["type"];
|
||||
if (string.IsNullOrEmpty(strType))
|
||||
@@ -2368,9 +2530,9 @@ namespace DnsServerCore
|
||||
IPAddress ipAddress = IPAddress.Parse(strIPAddress);
|
||||
|
||||
if (type == DnsResourceRecordType.A)
|
||||
_dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneName, domain, type, new DnsARecordData(ipAddress));
|
||||
_dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneInfo.Name, domain, type, new DnsARecordData(ipAddress));
|
||||
else
|
||||
_dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneName, domain, type, new DnsAAAARecordData(ipAddress));
|
||||
_dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneInfo.Name, domain, type, new DnsAAAARecordData(ipAddress));
|
||||
|
||||
string ptrDomain = Zone.GetReverseZone(ipAddress, type == DnsResourceRecordType.A ? 32 : 128);
|
||||
AuthZoneInfo reverseZoneInfo = _dnsWebService.DnsServer.AuthZoneManager.FindAuthZoneInfo(ptrDomain);
|
||||
@@ -2405,12 +2567,12 @@ namespace DnsServerCore
|
||||
nameServer = value;
|
||||
}
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneName, domain, type, new DnsNSRecordData(nameServer));
|
||||
_dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneInfo.Name, domain, type, new DnsNSRecordData(nameServer));
|
||||
}
|
||||
break;
|
||||
|
||||
case DnsResourceRecordType.CNAME:
|
||||
_dnsWebService.DnsServer.AuthZoneManager.DeleteRecords(zoneName, domain, type);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.DeleteRecords(zoneInfo.Name, domain, type);
|
||||
break;
|
||||
|
||||
case DnsResourceRecordType.PTR:
|
||||
@@ -2424,7 +2586,7 @@ namespace DnsServerCore
|
||||
ptrName = value;
|
||||
}
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneName, domain, type, new DnsPTRRecordData(ptrName));
|
||||
_dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneInfo.Name, domain, type, new DnsPTRRecordData(ptrName));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2443,7 +2605,7 @@ namespace DnsServerCore
|
||||
exchange = value;
|
||||
}
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneName, domain, type, new DnsMXRecordData(ushort.Parse(preference), exchange));
|
||||
_dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneInfo.Name, domain, type, new DnsMXRecordData(ushort.Parse(preference), exchange));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2458,7 +2620,7 @@ namespace DnsServerCore
|
||||
text = value;
|
||||
}
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneName, domain, type, new DnsTXTRecordData(text));
|
||||
_dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneInfo.Name, domain, type, new DnsTXTRecordData(text));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2485,12 +2647,12 @@ namespace DnsServerCore
|
||||
target = value;
|
||||
}
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneName, domain, type, new DnsSRVRecordData(ushort.Parse(priority), ushort.Parse(weight), ushort.Parse(port), target));
|
||||
_dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneInfo.Name, domain, type, new DnsSRVRecordData(ushort.Parse(priority), ushort.Parse(weight), ushort.Parse(port), target));
|
||||
}
|
||||
break;
|
||||
|
||||
case DnsResourceRecordType.DNAME:
|
||||
_dnsWebService.DnsServer.AuthZoneManager.DeleteRecords(zoneName, domain, type);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.DeleteRecords(zoneInfo.Name, domain, type);
|
||||
break;
|
||||
|
||||
case DnsResourceRecordType.DS:
|
||||
@@ -2516,7 +2678,7 @@ namespace DnsServerCore
|
||||
digest = value;
|
||||
}
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneName, domain, type, new DnsDSRecordData(ushort.Parse(strKeyTag), Enum.Parse<DnssecAlgorithm>(strAlgorithm, true), Enum.Parse<DnssecDigestType>(strDigestType, true), Convert.FromHexString(digest)));
|
||||
_dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneInfo.Name, domain, type, new DnsDSRecordData(ushort.Parse(strKeyTag), Enum.Parse<DnssecAlgorithm>(strAlgorithm, true), Enum.Parse<DnssecDigestType>(strDigestType, true), Convert.FromHexString(digest)));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2533,7 +2695,7 @@ namespace DnsServerCore
|
||||
if (string.IsNullOrEmpty(value))
|
||||
throw new DnsWebServiceException("Parameter 'value' missing.");
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneName, domain, type, new DnsCAARecordData(byte.Parse(flags), tag, value));
|
||||
_dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneInfo.Name, domain, type, new DnsCAARecordData(byte.Parse(flags), tag, value));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2548,7 +2710,7 @@ namespace DnsServerCore
|
||||
aname = value;
|
||||
}
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneName, domain, type, new DnsANAMERecordData(aname));
|
||||
_dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneInfo.Name, domain, type, new DnsANAMERecordData(aname));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2567,19 +2729,19 @@ namespace DnsServerCore
|
||||
forwarder = value;
|
||||
}
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneName, domain, type, new DnsForwarderRecordData(Enum.Parse<DnsTransportProtocol>(strProtocol, true), forwarder));
|
||||
_dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneInfo.Name, domain, type, new DnsForwarderRecordData(Enum.Parse<DnsTransportProtocol>(strProtocol, true), forwarder));
|
||||
}
|
||||
break;
|
||||
|
||||
case DnsResourceRecordType.APP:
|
||||
_dnsWebService.DnsServer.AuthZoneManager.DeleteRecords(zoneName, domain, type);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.DeleteRecords(zoneInfo.Name, domain, type);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new DnsWebServiceException("Type not supported for DeleteRecord().");
|
||||
}
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] Record was deleted from authoritative zone {domain: " + domain + "; type: " + type + ";}");
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + session.User.Username + "] Record was deleted from authoritative zone {domain: " + domain + "; type: " + type + ";}");
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneInfo.Name);
|
||||
}
|
||||
@@ -2609,8 +2771,10 @@ namespace DnsServerCore
|
||||
if (zoneInfo.Internal)
|
||||
throw new DnsWebServiceException("Access was denied to manage internal DNS Server zone.");
|
||||
|
||||
if (string.IsNullOrEmpty(zoneName))
|
||||
zoneName = zoneInfo.Name;
|
||||
UserSession session = _dnsWebService.GetSession(request);
|
||||
|
||||
if (!_dnsWebService.AuthManager.IsPermitted(PermissionSection.Zones, zoneInfo.Name, session.User, PermissionFlag.Modify))
|
||||
throw new DnsWebServiceException("Access was denied.");
|
||||
|
||||
string newDomain = request.QueryString["newDomain"];
|
||||
if (string.IsNullOrEmpty(newDomain))
|
||||
@@ -2686,8 +2850,14 @@ namespace DnsServerCore
|
||||
string ptrZone = Zone.GetReverseZone(newIpAddress, type == DnsResourceRecordType.A ? 24 : 64);
|
||||
|
||||
reverseZoneInfo = _dnsWebService.DnsServer.AuthZoneManager.CreatePrimaryZone(ptrZone, _dnsWebService.DnsServer.ServerDomain, false);
|
||||
if (reverseZoneInfo == null)
|
||||
if (reverseZoneInfo is null)
|
||||
throw new DnsServerException("Failed to create reverse zone to add PTR record: " + ptrZone);
|
||||
|
||||
//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();
|
||||
}
|
||||
|
||||
if (reverseZoneInfo.Internal)
|
||||
@@ -2730,7 +2900,7 @@ namespace DnsServerCore
|
||||
if (!string.IsNullOrEmpty(comments))
|
||||
newRecord.SetComments(comments);
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneName, oldRecord, newRecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneInfo.Name, oldRecord, newRecord);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2767,7 +2937,7 @@ namespace DnsServerCore
|
||||
if (!string.IsNullOrEmpty(glueAddresses))
|
||||
newRecord.SetGlueRecords(glueAddresses);
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneName, oldRecord, newRecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneInfo.Name, oldRecord, newRecord);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2791,7 +2961,7 @@ namespace DnsServerCore
|
||||
if (!string.IsNullOrEmpty(comments))
|
||||
newRecord.SetComments(comments);
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneName, oldRecord, newRecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneInfo.Name, oldRecord, newRecord);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2856,7 +3026,7 @@ namespace DnsServerCore
|
||||
if (!string.IsNullOrEmpty(comments))
|
||||
newSOARecord.SetComments(comments);
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneName, newSOARecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneInfo.Name, newSOARecord);
|
||||
|
||||
newRecord = zoneInfo.GetRecords(DnsResourceRecordType.SOA)[0];
|
||||
}
|
||||
@@ -2891,7 +3061,7 @@ namespace DnsServerCore
|
||||
if (!string.IsNullOrEmpty(comments))
|
||||
newRecord.SetComments(comments);
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneName, oldRecord, newRecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneInfo.Name, oldRecord, newRecord);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2932,7 +3102,7 @@ namespace DnsServerCore
|
||||
if (!string.IsNullOrEmpty(comments))
|
||||
newRecord.SetComments(comments);
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneName, oldRecord, newRecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneInfo.Name, oldRecord, newRecord);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2965,7 +3135,7 @@ namespace DnsServerCore
|
||||
if (!string.IsNullOrEmpty(comments))
|
||||
newRecord.SetComments(comments);
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneName, oldRecord, newRecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneInfo.Name, oldRecord, newRecord);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -3022,7 +3192,7 @@ namespace DnsServerCore
|
||||
if (!string.IsNullOrEmpty(comments))
|
||||
newRecord.SetComments(comments);
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneName, oldRecord, newRecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneInfo.Name, oldRecord, newRecord);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -3046,7 +3216,7 @@ namespace DnsServerCore
|
||||
if (!string.IsNullOrEmpty(comments))
|
||||
newRecord.SetComments(comments);
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneName, oldRecord, newRecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneInfo.Name, oldRecord, newRecord);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -3103,7 +3273,7 @@ namespace DnsServerCore
|
||||
if (!string.IsNullOrEmpty(comments))
|
||||
newRecord.SetComments(comments);
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneName, oldRecord, newRecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneInfo.Name, oldRecord, newRecord);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -3140,7 +3310,7 @@ namespace DnsServerCore
|
||||
if (!string.IsNullOrEmpty(comments))
|
||||
newRecord.SetComments(comments);
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneName, oldRecord, newRecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneInfo.Name, oldRecord, newRecord);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -3173,7 +3343,7 @@ namespace DnsServerCore
|
||||
if (!string.IsNullOrEmpty(comments))
|
||||
newRecord.SetComments(comments);
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneName, oldRecord, newRecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneInfo.Name, oldRecord, newRecord);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -3249,7 +3419,7 @@ namespace DnsServerCore
|
||||
if (!string.IsNullOrEmpty(comments))
|
||||
newRecord.SetComments(comments);
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneName, oldRecord, newRecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneInfo.Name, oldRecord, newRecord);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -3281,7 +3451,7 @@ namespace DnsServerCore
|
||||
if (!string.IsNullOrEmpty(comments))
|
||||
newRecord.SetComments(comments);
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneName, oldRecord, newRecord);
|
||||
_dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneInfo.Name, oldRecord, newRecord);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -3289,7 +3459,7 @@ namespace DnsServerCore
|
||||
throw new DnsWebServiceException("Type not supported for UpdateRecords().");
|
||||
}
|
||||
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] Record was updated for authoritative zone {oldDomain: " + domain + "; domain: " + newDomain + "; type: " + type + "; oldValue: " + value + "; value: " + newValue + "; ttl: " + ttl + "; disabled: " + disable + ";}");
|
||||
_dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + session.User.Username + "] Record was updated for authoritative zone {oldDomain: " + domain + "; domain: " + newDomain + "; type: " + type + "; oldValue: " + value + "; value: " + newValue + "; ttl: " + ttl + "; disabled: " + disable + ";}");
|
||||
|
||||
_dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneInfo.Name);
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
; on server FTP.INTERNIC.NET
|
||||
; -OR- RS.INTERNIC.NET
|
||||
;
|
||||
; last update: March 16, 2022
|
||||
; related version of root zone: 2022031601
|
||||
; last update: August 31, 2022
|
||||
; related version of root zone: 2022083101
|
||||
;
|
||||
; FORMERLY NS.INTERNIC.NET
|
||||
;
|
||||
|
||||
BIN
DnsServerCore/www/img/loader-small.gif
Normal file
BIN
DnsServerCore/www/img/loader-small.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.4 KiB |
@@ -25,6 +25,7 @@
|
||||
<link href="/css/main.css" rel="stylesheet" />
|
||||
<script src="/js/common.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
<script src="/js/auth.js"></script>
|
||||
<script src="/js/zone.js"></script>
|
||||
<script src="/js/other-zones.js"></script>
|
||||
<script src="/js/apps.js"></script>
|
||||
@@ -42,7 +43,10 @@
|
||||
</span>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="#" onclick="resetChangePasswordModal(); return false;" data-toggle="modal" data-target="#modalChangePassword">Change Password</a></li>
|
||||
<li><a href="#" onclick="showMyProfileModal(); return false;">My Profile</a></li>
|
||||
<li><a href="#" onclick="showCreateMyApiTokenModal(); return false;">Create API Token</a></li>
|
||||
<li><a href="#" onclick="showChangePasswordModal(); return false;">Change Password</a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a href="#" onclick="logout(); return false;">Logout</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -109,6 +113,7 @@
|
||||
<li id="mainPanelTabListDnsClient" role="presentation"><a href="#mainPanelTabPaneDnsClient" aria-controls="mainPanelTabPaneDnsClient" role="tab" data-toggle="tab">DNS Client</a></li>
|
||||
<li id="mainPanelTabListSettings" role="presentation"><a href="#mainPanelTabPaneSettings" aria-controls="mainPanelTabPaneSettings" role="tab" data-toggle="tab" onclick="loadDnsSettings();">Settings</a></li>
|
||||
<li id="mainPanelTabListDhcp" role="presentation"><a href="#mainPanelTabPaneDhcp" aria-controls="mainPanelTabPaneDhcp" role="tab" data-toggle="tab" onclick="refreshDhcpTab();">DHCP</a></li>
|
||||
<li id="mainPanelTabListAdmin" role="presentation"><a href="#mainPanelTabPaneAdmin" aria-controls="mainPanelTabPaneAdmin" role="tab" data-toggle="tab" onclick="refreshAdminTab();">Administration</a></li>
|
||||
<li id="mainPanelTabListLogs" role="presentation"><a href="#mainPanelTabPaneLogs" aria-controls="mainPanelTabPaneLogs" role="tab" data-toggle="tab" onclick="refreshLogsTab();">Logs</a></li>
|
||||
<li id="mainPanelTabListAbout" role="presentation"><a href="#mainPanelTabPaneAbout" aria-controls="mainPanelTabPaneAbout" role="tab" data-toggle="tab">About</a></li>
|
||||
</ul>
|
||||
@@ -347,7 +352,7 @@
|
||||
<th onclick="sortTable('tableZonesBody', 2);">DNSSEC</th>
|
||||
<th onclick="sortTable('tableZonesBody', 3);">Status</th>
|
||||
<th onclick="sortTable('tableZonesBody', 4);">Expiry</th>
|
||||
<th></th>
|
||||
<th style="width: 36px;"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tableZonesBody">
|
||||
@@ -364,7 +369,7 @@
|
||||
</ul>
|
||||
|
||||
<div style="padding: 10px 0px;">
|
||||
<h3 style="margin: 4px 0;"><span id="titleEditZone" style="margin-right: 10px;">example.com</span><a href="#" onclick="showEditZone($('#titleEditZone').text()); return false;"><span class="glyphicon glyphicon-refresh" style="font-size: 20px;" aria-hidden="true"></span></a></h3>
|
||||
<h3 style="margin: 4px 0;"><span id="titleEditZone" style="margin-right: 10px;">example.com</span><a href="#" onclick="showEditZone($('#titleEditZone').attr('data-zone')); return false;"><span class="glyphicon glyphicon-refresh" style="font-size: 20px;" aria-hidden="true"></span></a></h3>
|
||||
<div style="float: left;">
|
||||
<span id="titleEditZoneType" class="label label-default">Primary</span>
|
||||
<span id="titleDnssecStatusEditZone" class="label label-default">DNSSEC</span>
|
||||
@@ -373,21 +378,22 @@
|
||||
</div>
|
||||
<div style="float: right; padding: 2px 0px;">
|
||||
<button id="btnEditZoneAddRecord" type="button" class="btn btn-primary" style="padding: 2px 0px; width: 100px;" onclick="showAddRecordModal(this);" data-loading-text="Loading...">Add Record</button>
|
||||
<button id="btnEnableZoneEditZone" type="button" class="btn btn-default" style="padding: 2px 0px; width: 100px;" onclick="enableZone(this, $('#titleEditZone').text(), true);">Enable Zone</button>
|
||||
<button id="btnDisableZoneEditZone" type="button" class="btn btn-warning" style="padding: 2px 0px; width: 100px;" onclick="disableZone(this, $('#titleEditZone').text(), true);">Disable Zone</button>
|
||||
<button id="btnEditZoneDeleteZone" type="button" class="btn btn-danger" style="padding: 2px 0px; width: 100px;" onclick="deleteZone(this, $('#titleEditZone').text(), true);">Delete Zone</button>
|
||||
<button id="btnZoneResync" type="button" class="btn btn-primary" style="padding: 2px 0px; width: 100px;" onclick="resyncZone(this, $('#titleEditZone').text());" data-loading-text="Resyncing...">Resync</button>
|
||||
<button id="btnZoneOptions" type="button" class="btn btn-primary" style="padding: 2px 0px; width: 100px;" onclick="showZoneOptionsModal($('#titleEditZone').text());">Options</button>
|
||||
<button id="btnEnableZoneEditZone" type="button" class="btn btn-default" style="padding: 2px 0px; width: 100px;" onclick="enableZone(this);">Enable Zone</button>
|
||||
<button id="btnDisableZoneEditZone" type="button" class="btn btn-warning" style="padding: 2px 0px; width: 100px;" onclick="disableZone(this);">Disable Zone</button>
|
||||
<button id="btnEditZoneDeleteZone" type="button" class="btn btn-danger" style="padding: 2px 0px; width: 100px;" onclick="deleteZone(this);">Delete Zone</button>
|
||||
<button id="btnZoneResync" type="button" class="btn btn-primary" style="padding: 2px 0px; width: 100px;" onclick="resyncZone(this, $('#titleEditZone').attr('data-zone'));" data-loading-text="Resyncing...">Resync</button>
|
||||
<button id="btnZoneOptions" type="button" class="btn btn-primary" style="padding: 2px 0px; width: 100px;" onclick="showZoneOptionsModal($('#titleEditZone').attr('data-zone'));">Options</button>
|
||||
<button id="btnZonePermissions" type="button" class="btn btn-primary" style="padding: 2px 0px; width: 100px;" onclick="showZonePermissionsModal($('#titleEditZone').attr('data-zone'));">Permissions</button>
|
||||
<div id="divZoneDnssecOptions" class="btn-group">
|
||||
<button type="button" class="btn btn-primary dropdown-toggle" style="padding: 2px 0px; width: 100px;" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
DNSSEC <span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li id="lnkZoneDnssecSignZone"><a href="#" onclick="showSignZoneModal($('#titleEditZone').text()); return false;">Sign Zone</a></li>
|
||||
<li id="lnkZoneDnssecSignZone"><a href="#" onclick="showSignZoneModal($('#titleEditZone').attr('data-zone')); return false;">Sign Zone</a></li>
|
||||
<li id="lnkZoneDnssecHideRecords"><a href="#" onclick="toggleHideDnssecRecords(true); return false;">Hide DNSSEC Records</a></li>
|
||||
<li id="lnkZoneDnssecShowRecords"><a href="#" onclick="toggleHideDnssecRecords(false); return false;">Show DNSSEC Records</a></li>
|
||||
<li id="lnkZoneDnssecProperties"><a href="#" onclick="showDnssecPropertiesModal($('#titleEditZone').text()); return false;">Properties</a></li>
|
||||
<li id="lnkZoneDnssecUnsignZone"><a href="#" onclick="showUnsignZoneModal($('#titleEditZone').text()); return false;">Unsign Zone</a></li>
|
||||
<li id="lnkZoneDnssecProperties"><a href="#" onclick="showDnssecPropertiesModal($('#titleEditZone').attr('data-zone')); return false;">Properties</a></li>
|
||||
<li id="lnkZoneDnssecUnsignZone"><a href="#" onclick="showUnsignZoneModal($('#titleEditZone').attr('data-zone')); return false;">Unsign Zone</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -738,6 +744,18 @@
|
||||
</div>
|
||||
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The default TTL value to use if not specified when adding or updating records in a Zone.</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="txtDefaultRecordTtl" class="col-sm-3 control-label">DNS Apps</label>
|
||||
<div class="col-sm-8">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input id="chkDnsAppsEnableAutomaticUpdate" type="checkbox"> Enable Automatic Update
|
||||
</label>
|
||||
</div>
|
||||
<div style="padding-top: 5px; padding-left: 20px;">DNS server will check for DNS Apps update every day and will automatically download and install the updates.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="well well-sm form-horizontal">
|
||||
@@ -1008,7 +1026,7 @@
|
||||
<th>Key Name</th>
|
||||
<th>Shared Secret</th>
|
||||
<th>Algorithm</th>
|
||||
<th><button type="button" class="btn btn-default" style="padding: 0px 20px;" onclick="addTsigKeyRow('', '', 'hmac-sha256');">Add</button></th>
|
||||
<th style="width: 84px;"><button type="button" class="btn btn-default" style="padding: 0px 20px;" onclick="addTsigKeyRow('', '', 'hmac-sha256');">Add</button></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tableTsigKeys"></tbody>
|
||||
@@ -1350,7 +1368,7 @@
|
||||
<label for="txtBlockListUpdateIntervalHours" class="col-sm-3 control-label">Block List Update Interval</label>
|
||||
<div class="col-sm-6">
|
||||
<input type="number" class="form-control" id="txtBlockListUpdateIntervalHours" placeholder="hours" style="width: 100px; display: inline;">
|
||||
<span>hours (default 24, valid range 1-168)</span>
|
||||
<span>hours (valid range 0-168; default 24; set 0 to disable)</span>
|
||||
</div>
|
||||
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The interval in hours to automatically download and update the block lists.</div>
|
||||
</div>
|
||||
@@ -1667,7 +1685,7 @@
|
||||
<th onclick="sortTable('tableDhcpLeasesBody', 4);">Host Name</th>
|
||||
<th onclick="sortTable('tableDhcpLeasesBody', 5);">Lease Obtained</th>
|
||||
<th onclick="sortTable('tableDhcpLeasesBody', 6);">Lease Expires</th>
|
||||
<th style="width: 30px;" align="right"></th>
|
||||
<th style="width: 36px;"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tableDhcpLeasesBody">
|
||||
@@ -1917,7 +1935,7 @@
|
||||
<tr>
|
||||
<th>Vendor Class Identifier</th>
|
||||
<th>Vendor Specific Information</th>
|
||||
<th><button type="button" class="btn btn-default" style="padding: 0px 20px;" onclick="addDhcpScopeVendorInfoRow('', '');">Add</button></th>
|
||||
<th style="width: 84px;"><button type="button" class="btn btn-default" style="padding: 0px 20px;" onclick="addDhcpScopeVendorInfoRow('', '');">Add</button></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tableDhcpScopeVendorInfo"></tbody>
|
||||
@@ -1936,7 +1954,7 @@
|
||||
<tr>
|
||||
<th>Starting Address</th>
|
||||
<th>Ending Address</th>
|
||||
<th><button type="button" class="btn btn-default" style="padding: 0px 20px;" onclick="addDhcpScopeExclusionRow('', '');">Add</button></th>
|
||||
<th style="width: 84px;"><button type="button" class="btn btn-default" style="padding: 0px 20px;" onclick="addDhcpScopeExclusionRow('', '');">Add</button></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tableDhcpScopeExclusions"></tbody>
|
||||
@@ -1986,6 +2004,130 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="mainPanelTabPaneAdmin" role="tabpanel" class="tab-pane" style="padding: 10px 0 0 0;">
|
||||
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
<li id="adminTabListSessions" role="presentation" class="active"><a href="#adminTabPaneSessions" aria-controls="adminTabPaneSessions" role="tab" data-toggle="tab" onclick="refreshAdminSessions();">Sessions</a></li>
|
||||
<li id="adminTabListUsers" role="presentation"><a href="#adminTabPaneUsers" aria-controls="adminTabPaneUsers" role="tab" data-toggle="tab" onclick="refreshAdminUsers();">Users</a></li>
|
||||
<li id="adminTabListGroups" role="presentation"><a href="#adminTabPaneGroups" aria-controls="adminTabPaneGroups" role="tab" data-toggle="tab" onclick="refreshAdminGroups();">Groups</a></li>
|
||||
<li id="adminTabListPermissions" role="presentation"><a href="#adminTabPanePermissions" aria-controls="adminTabPanePermissions" role="tab" data-toggle="tab" onclick="refreshAdminPermissions();">Permissions</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content">
|
||||
|
||||
<div id="adminTabPaneSessions" class="tab-pane active">
|
||||
<div id="divAdminSessionsLoader" style="margin-top: 10px; height: 350px;"></div>
|
||||
|
||||
<div id="divAdminSessionsView" style="margin-top: 10px;">
|
||||
<div style="float: right; padding: 2px 0px;">
|
||||
<button type="button" class="btn btn-primary" style="padding: 2px 0px; width: 100px;" onclick="showCreateApiTokenModal();">Create Token</button>
|
||||
</div>
|
||||
|
||||
<div style="clear: both;"></div>
|
||||
|
||||
<table id="tableAdminSessions" class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th onclick="sortTable('tbodyAdminSessions', 0);">Username</th>
|
||||
<th onclick="sortTable('tbodyAdminSessions', 1);">Session</th>
|
||||
<th onclick="sortTable('tbodyAdminSessions', 2);">Last Seen</th>
|
||||
<th onclick="sortTable('tbodyAdminSessions', 3);">Remote Address</th>
|
||||
<th onclick="sortTable('tbodyAdminSessions', 4);">User Agent</th>
|
||||
<th style="width: 36px;"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tbodyAdminSessions">
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr><th colspan="6" id="tfootAdminSessions"></th></tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="adminTabPaneUsers" class="tab-pane">
|
||||
<div id="divAdminUsersLoader" style="margin-top: 10px; height: 350px;"></div>
|
||||
|
||||
<div id="divAdminUsersView" style="margin-top: 10px;">
|
||||
<div style="float: right; padding: 2px 0px;">
|
||||
<button type="button" class="btn btn-primary" style="padding: 2px 0px; width: 100px;" onclick="showAddUserModal();">Add User</button>
|
||||
</div>
|
||||
|
||||
<div style="clear: both;"></div>
|
||||
|
||||
<table id="tableAdminUsers" class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th onclick="sortTable('tbodyAdminUsers', 0);">Username</th>
|
||||
<th onclick="sortTable('tbodyAdminUsers', 1);">Display Name</th>
|
||||
<th onclick="sortTable('tbodyAdminUsers', 2);">Status</th>
|
||||
<th onclick="sortTable('tbodyAdminUsers', 3);">Previous Login</th>
|
||||
<th onclick="sortTable('tbodyAdminUsers', 4);">Recent Login</th>
|
||||
<th style="width: 36px;"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tbodyAdminUsers">
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr><th colspan="6" id="tfootAdminUsers"></th></tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="adminTabPaneGroups" class="tab-pane">
|
||||
<div id="divAdminGroupsLoader" style="margin-top: 10px; height: 350px;"></div>
|
||||
|
||||
<div id="divAdminGroupsView" style="margin-top: 10px;">
|
||||
<div style="float: right; padding: 2px 0px;">
|
||||
<button type="button" class="btn btn-primary" style="padding: 2px 0px; width: 100px;" onclick="showAddGroupModal();">Add Group</button>
|
||||
</div>
|
||||
|
||||
<div style="clear: both;"></div>
|
||||
|
||||
<table id="tableAdminGroups" class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th onclick="sortTable('tbodyAdminGroups', 0);">Name</th>
|
||||
<th onclick="sortTable('tbodyAdminGroups', 1);">Description</th>
|
||||
<th style="width: 36px;"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tbodyAdminGroups">
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr><th colspan="3" id="tfootAdminGroups"></th></tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="adminTabPanePermissions" class="tab-pane">
|
||||
<div id="divAdminPermissionsLoader" style="margin-top: 10px; height: 350px;"></div>
|
||||
|
||||
<div id="divAdminPermissionsView" style="margin-top: 10px;">
|
||||
<table id="tableAdminPermissions" class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th onclick="sortTable('tbodyAdminPermissions', 0);">Section</th>
|
||||
<th>User Permissions</th>
|
||||
<th>Group Permissions</th>
|
||||
<th style="width: 36px;"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tbodyAdminPermissions">
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr><th colspan="4" id="tfootAdminPermissions"></th></tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="mainPanelTabPaneLogs" role="tabpanel" class="tab-pane" style="padding: 10px 0 0 0;">
|
||||
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
@@ -2154,7 +2296,7 @@
|
||||
|
||||
<div id="divQueryLogsLoader" style="margin-top: 20px; height: 300px;"></div>
|
||||
|
||||
<div id="divQueryLogsTable">
|
||||
<div id="divQueryLogsTable" style="display: none;">
|
||||
<div>
|
||||
<div class="pull-left" style="padding: 8px;">
|
||||
<b id="tableQueryLogsTopStatus">Found: 0 logs</b>
|
||||
@@ -2266,13 +2408,171 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="modalMyProfile" class="modal fade" tabindex="-1" role="dialog">
|
||||
<form class="form-horizontal">
|
||||
<div class="modal-dialog" role="document" style="width: 940px;">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title">My Profile</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div id="divMyProfileAlert"></div>
|
||||
|
||||
<div id="divMyProfileLoader" style="height: 500px;"></div>
|
||||
|
||||
<div id="divMyProfileViewer" style="max-height: 500px; overflow-y: auto; padding: 0 6px; overflow-x: hidden;">
|
||||
<div class="form-group">
|
||||
<label for="txtMyProfileDisplayName" class="col-sm-4 control-label">Display Name</label>
|
||||
<div class="col-sm-7">
|
||||
<input id="txtMyProfileDisplayName" type="text" class="form-control" placeholder="display name" maxlength="255">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="txtMyProfileUsername" class="col-sm-4 control-label">Username</label>
|
||||
<div class="col-sm-7">
|
||||
<input id="txtMyProfileUsername" type="text" class="form-control" placeholder="username" disabled>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="txtMyProfileSessionTimeout" class="col-sm-4 control-label">Session Timeout</label>
|
||||
<div class="col-sm-7">
|
||||
<input id="txtMyProfileSessionTimeout" type="number" class="form-control" placeholder="1800" style="width: 100px; display: inline;">
|
||||
<span>seconds (valid range 0-604800; default 1800; set 0 to disable)</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4 control-label">Member Of</label>
|
||||
<div class="col-sm-7">
|
||||
<table class="table table-hover" style="margin-bottom: 0px;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th onclick="sortTable('tbodyMyProfileMemberOf', 0);">Group</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tbodyMyProfileMemberOf">
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr><th colspan="1" id="tfootMyProfileMemberOf"></th></tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="well well-sm" style="background-color: #fbfbfb;">
|
||||
<p style="font-size: 16px; font-weight: bold;">Active Sessions</p>
|
||||
<table id="tableMyProfileActiveSessions" class="table table-hover" style="margin-bottom: 0px;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th onclick="sortTable('tbodyMyProfileActiveSessions', 0);">Session</th>
|
||||
<th onclick="sortTable('tbodyMyProfileActiveSessions', 1);">Last Seen</th>
|
||||
<th onclick="sortTable('tbodyMyProfileActiveSessions', 2);">Remote Address</th>
|
||||
<th onclick="sortTable('tbodyMyProfileActiveSessions', 3);">User Agent</th>
|
||||
<th style="width: 36px;"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tbodyMyProfileActiveSessions">
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr><th colspan="5" id="tfootMyProfileActiveSessions"></th></tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn btn-primary" data-loading-text="Saving..." onclick="saveMyProfile(this); return false;">Save</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="modalCreateApiToken" class="modal fade" tabindex="-1" role="dialog">
|
||||
<form class="form-horizontal">
|
||||
<div class="modal-dialog" role="document" style="width: 780px;">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title">Create API Token</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div id="divCreateApiTokenAlert"></div>
|
||||
|
||||
<div id="divCreateApiTokenLoader" style="height: 350px;"></div>
|
||||
|
||||
<div id="divCreateApiTokenForm">
|
||||
<div class="form-group">
|
||||
<label for="txtCreateApiTokenUsername" class="col-sm-4 control-label">Username</label>
|
||||
<div class="col-sm-7">
|
||||
<input id="txtCreateApiTokenUsername" type="text" class="form-control" placeholder="username" disabled>
|
||||
<select id="optCreateApiTokenUsername" class="form-control"></select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" id="divCreateApiTokenPassword">
|
||||
<label for="txtCreateApiTokenPassword" class="col-sm-4 control-label">Password</label>
|
||||
<div class="col-sm-7">
|
||||
<input id="txtCreateApiTokenPassword" type="password" class="form-control" placeholder="password" maxlength="255">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="txtCreateApiTokenName" class="col-sm-4 control-label">Token Name</label>
|
||||
<div class="col-sm-7">
|
||||
<input id="txtCreateApiTokenName" type="text" class="form-control" placeholder="token name" maxlength="255">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="divCreateApiTokenOutput">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">Username</label>
|
||||
<div class="col-sm-9">
|
||||
<div id="lblCreateApiTokenOutputUsername" style="padding-top: 7px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">Token Name</label>
|
||||
<div class="col-sm-9">
|
||||
<div id="lblCreateApiTokenOutputTokenName" style="padding-top: 7px; word-wrap: anywhere;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">Token</label>
|
||||
<div class="col-sm-9">
|
||||
<div id="lblCreateApiTokenOutputToken" style="padding-top: 7px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
<b>WARNING!</b> The token value shown above will not be displayed later. You must copy the token value immediately and save it for use later.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button id="btnCreateApiToken" type="submit" class="btn btn-primary" data-loading-text="Creating...">Create</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="modalChangePassword" class="modal fade" tabindex="-1" role="dialog">
|
||||
<form class="form-horizontal">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title">Change Password</h4>
|
||||
<h4 id="titleChangePassword" class="modal-title">Change Password</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div id="divChangePasswordAlert"></div>
|
||||
@@ -2287,19 +2587,19 @@
|
||||
<div class="form-group">
|
||||
<label for="txtChangePasswordNewPassword" class="col-sm-4 control-label">New Password</label>
|
||||
<div class="col-sm-7">
|
||||
<input id="txtChangePasswordNewPassword" type="password" class="form-control" placeholder="new password">
|
||||
<input id="txtChangePasswordNewPassword" type="password" class="form-control" placeholder="new password" maxlength="255">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="txtChangePasswordConfirmPassword" class="col-sm-4 control-label">Confirm Password</label>
|
||||
<div class="col-sm-7">
|
||||
<input id="txtChangePasswordConfirmPassword" type="password" class="form-control" placeholder="confirm password">
|
||||
<input id="txtChangePasswordConfirmPassword" type="password" class="form-control" placeholder="confirm password" maxlength="255">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button id="btnChangePasswordSave" type="submit" class="btn btn-primary" data-loading-text="Saving..." onclick="changePassword(); return false;">Save</button>
|
||||
<button id="btnChangePassword" type="submit" class="btn btn-primary" data-loading-text="Working...">Change</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -2315,14 +2615,16 @@
|
||||
<h4 class="modal-title">Forgot Password?</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Follow these steps to reset 'admin' password:</p>
|
||||
<p>To reset your password, you need to contact the DNS server administrator.</p>
|
||||
<p>If you are an administrator, follow these steps to reset the 'admin' user's password:</p>
|
||||
<ol>
|
||||
<li>Find the DNS Server config folder and locate the <b>dns.config</b> file. The config folder will be found where the DNS Server is installed.</li>
|
||||
<li>Rename the <b>dns.config</b> file as <b>reset.config</b></li>
|
||||
<li>Restart the DNS Server to complete the password reset process.</li>
|
||||
<li>Stop the DNS server.</li>
|
||||
<li>Find the DNS Server config folder and locate the <b>auth.config</b> file. The config folder will be found where the DNS Server is installed.</li>
|
||||
<li>Rename the <b>auth.config</b> file as <b>resetadmin.config</b></li>
|
||||
<li>Start the DNS Server to complete the password reset process.</li>
|
||||
<li>Just refresh this web page in the web browser to auto login with default credentials and quickly change the password.</li>
|
||||
</ol>
|
||||
<p>Note: To reset 'admin' password, you will need file system access on the server running this DNS Server. </p>
|
||||
<p>Note: To reset 'admin' password, you will need file system access on the server running this DNS Server. If the 'admin' user does not exists then it will be created automatically.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
@@ -2378,7 +2680,7 @@
|
||||
<div class="form-group">
|
||||
<label for="txtAddZone" class="col-sm-4 control-label">Zone</label>
|
||||
<div class="col-sm-7">
|
||||
<input id="txtAddZone" type="text" class="form-control" placeholder="example.com or 192.168.0.0/24 or 2001:db8::/64">
|
||||
<input id="txtAddZone" type="text" class="form-control" placeholder="example.com or 192.168.0.0/24 or 2001:db8::/64" maxlength="255">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3289,7 +3591,7 @@ ns1.example.com ([2001:db8::])
|
||||
<span>(valid range 0-50, recommended 0)</span>
|
||||
</div>
|
||||
<div class="col-sm-offset-4 col-sm-8" style="padding-top: 5px;">
|
||||
The number of iterations used by NSEC3 for hashing the domain names. It is recommended to use 0 iterations since more iterations will increase computational costs for both the DNS server and resolver while not providing much value against "zone walking" [<a href="https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-nsec3-guidance-03#section-2.3" target="_blank">draft-ietf-dnsop-nsec3-guidance</a>].
|
||||
The number of iterations used by NSEC3 for hashing the domain names. It is recommended to use 0 iterations since more iterations will increase computational costs for both the DNS server and resolver while not providing much value against "zone walking" [<a href="https://www.rfc-editor.org/rfc/rfc9276.html#name-iterations" target="_blank">RFC 9276</a>].
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3300,7 +3602,7 @@ ns1.example.com ([2001:db8::])
|
||||
<span>(valid range 0-32, recommended 0)</span>
|
||||
</div>
|
||||
<div class="col-sm-offset-4 col-sm-8" style="padding-top: 5px;">
|
||||
The number of bytes of random salt to generate to be used with the NSEC3 hash computation. It is recommended to not use salt by setting the length to 0 [<a href="https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-nsec3-guidance-03#section-2.4" target="_blank">draft-ietf-dnsop-nsec3-guidance</a>].
|
||||
The number of bytes of random salt to generate to be used with the NSEC3 hash computation. It is recommended to not use salt by setting the length to 0 [<a href="https://www.rfc-editor.org/rfc/rfc9276.html#name-salt" target="_blank">RFC 9276</a>].
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -3402,7 +3704,7 @@ ns1.example.com ([2001:db8::])
|
||||
|
||||
<div>
|
||||
<button type="button" class="btn btn-primary" style="padding: 2px 0; width: 120px;" data-toggle="collapse" data-target="#divDnssecPropertiesGenerateKey" aria-expanded="false" aria-controls="divDnssecPropertiesGenerateKey">Add Private Key</button>
|
||||
<button type="button" class="btn btn-warning" style="padding: 2px 0; width: 120px;" data-loading-text="Publishing..." onclick="publishAllDnssecPrivateKeys(this);">Publish All Keys</button>
|
||||
<button id="btnDnssecPropertiesPublishKeys" type="button" class="btn btn-warning" style="padding: 2px 0; width: 120px;" data-loading-text="Publishing..." onclick="publishAllDnssecPrivateKeys(this);">Publish All Keys</button>
|
||||
</div>
|
||||
|
||||
<div id="divDnssecPropertiesGenerateKey" class="collapse">
|
||||
@@ -3521,7 +3823,7 @@ ns1.example.com ([2001:db8::])
|
||||
<span>(valid range 0-50, recommended 0)</span>
|
||||
</div>
|
||||
<div class="col-sm-offset-4 col-sm-8" style="padding-top: 5px;">
|
||||
The number of iterations used by NSEC3 for hashing the domain names. It is recommended to use 0 iterations since more iterations will increase computational costs for both the DNS server and resolver while not providing much value against "zone walking" [<a href="https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-nsec3-guidance-03#section-2.3" target="_blank">draft-ietf-dnsop-nsec3-guidance</a>].
|
||||
The number of iterations used by NSEC3 for hashing the domain names. It is recommended to use 0 iterations since more iterations will increase computational costs for both the DNS server and resolver while not providing much value against "zone walking" [<a href="https://www.rfc-editor.org/rfc/rfc9276.html#name-iterations" target="_blank">RFC 9276</a>].
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3532,7 +3834,7 @@ ns1.example.com ([2001:db8::])
|
||||
<span>(valid range 0-32, recommended 0)</span>
|
||||
</div>
|
||||
<div class="col-sm-offset-4 col-sm-8" style="padding-top: 5px;">
|
||||
The number of bytes of random salt to generate to be used with the NSEC3 hash computation. It is recommended to not use salt by setting the length to 0 [<a href="https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-nsec3-guidance-03#section-2.4" target="_blank">draft-ietf-dnsop-nsec3-guidance</a>].
|
||||
The number of bytes of random salt to generate to be used with the NSEC3 hash computation. It is recommended to not use salt by setting the length to 0 [<a href="https://www.rfc-editor.org/rfc/rfc9276.html#name-salt" target="_blank">RFC 9276</a>].
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -3775,6 +4077,12 @@ ns1.example.com ([2001:db8::])
|
||||
<div class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<div style="padding-left: 40px;">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input id="chkBackupAuthConfig" type="checkbox" checked> Authentication Config File (auth.config)
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input id="chkBackupDnsSettings" type="checkbox" checked> DNS Settings File (dns.config)
|
||||
@@ -3871,6 +4179,12 @@ ns1.example.com ([2001:db8::])
|
||||
|
||||
<div class="form-group">
|
||||
<div style="padding-left: 40px;">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input id="chkRestoreAuthConfig" type="checkbox" checked> Authentication Config File (auth.config)
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input id="chkRestoreDnsSettings" type="checkbox" checked> DNS Settings File (dns.config)
|
||||
@@ -4056,6 +4370,290 @@ ns1.example.com ([2001:db8::])
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="modalAddUser" class="modal fade" tabindex="-1" role="dialog">
|
||||
<form class="form-horizontal">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title">Add User</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div id="divAddUserAlert"></div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="txtAddUserDisplayName" class="col-sm-4 control-label">Display Name</label>
|
||||
<div class="col-sm-7">
|
||||
<input id="txtAddUserDisplayName" type="text" class="form-control" placeholder="display name" maxlength="255">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="txtAddUserUsername" class="col-sm-4 control-label">Username</label>
|
||||
<div class="col-sm-7">
|
||||
<input id="txtAddUserUsername" type="text" class="form-control" placeholder="username" maxlength="255">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="txtAddUserPassword" class="col-sm-4 control-label">Password</label>
|
||||
<div class="col-sm-7">
|
||||
<input id="txtAddUserPassword" type="password" class="form-control" placeholder="password" maxlength="255">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="txtAddUserConfirmPassword" class="col-sm-4 control-label">Confirm Password</label>
|
||||
<div class="col-sm-7">
|
||||
<input id="txtAddUserConfirmPassword" type="password" class="form-control" placeholder="confirm password" maxlength="255">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button id="btnAddUser" type="submit" class="btn btn-primary" data-loading-text="Adding..." onclick="addUser(this); return false;">Add</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="modalUserDetails" class="modal fade" tabindex="-1" role="dialog">
|
||||
<form class="form-horizontal">
|
||||
<div class="modal-dialog" role="document" style="width: 940px;">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title">User Details</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div id="divUserDetailsAlert"></div>
|
||||
|
||||
<div id="divUserDetailsLoader" style="height: 500px;"></div>
|
||||
|
||||
<div id="divUserDetailsViewer" style="max-height: 500px; overflow-y: auto; padding: 0 6px; overflow-x: hidden;">
|
||||
<div class="form-group">
|
||||
<label for="txtUserDetailsDisplayName" class="col-sm-4 control-label">Display Name</label>
|
||||
<div class="col-sm-7">
|
||||
<input id="txtUserDetailsDisplayName" type="text" class="form-control" placeholder="display name" maxlength="255">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="txtUserDetailsUsername" class="col-sm-4 control-label">Username</label>
|
||||
<div class="col-sm-7">
|
||||
<input id="txtUserDetailsUsername" type="text" class="form-control" placeholder="username" maxlength="255">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-4 col-sm-7">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input id="chkUserDetailsDisableAccount" type="checkbox"> Disable User Account
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="txtUserDetailsSessionTimeout" class="col-sm-4 control-label">Session Timeout</label>
|
||||
<div class="col-sm-7">
|
||||
<input id="txtUserDetailsSessionTimeout" type="number" class="form-control" placeholder="1800" style="width: 100px; display: inline;">
|
||||
<span>seconds (valid range 0-604800; default 1800; set 0 to disable)</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4 control-label">Member Of</label>
|
||||
<div class="col-sm-7">
|
||||
<textarea id="txtUserDetailsMemberOf" class="form-control" rows="5"></textarea>
|
||||
<label class="control-label" for="optUserDetailsGroupList">Add Group</label>
|
||||
<select id="optUserDetailsGroupList" class="form-control"></select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="well well-sm" style="background-color: #fbfbfb;">
|
||||
<p style="font-size: 16px; font-weight: bold;">Active Sessions</p>
|
||||
<table id="tableUserDetailsActiveSessions" class="table table-hover" style="margin-bottom: 0px;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th onclick="sortTable('tbodyUserDetailsActiveSessions', 0);">Session</th>
|
||||
<th onclick="sortTable('tbodyUserDetailsActiveSessions', 1);">Last Seen</th>
|
||||
<th onclick="sortTable('tbodyUserDetailsActiveSessions', 2);">Remote Address</th>
|
||||
<th onclick="sortTable('tbodyUserDetailsActiveSessions', 3);">User Agent</th>
|
||||
<th style="width: 36px;"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tbodyUserDetailsActiveSessions">
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr><th colspan="5" id="tfootUserDetailsActiveSessions"></th></tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button id="btnUserDetailsSave" type="submit" class="btn btn-primary" data-loading-text="Saving..." onclick="saveUserDetails(this); return false;">Save</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="modalAddGroup" class="modal fade" tabindex="-1" role="dialog">
|
||||
<form class="form-horizontal">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title">Add Group</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div id="divAddGroupAlert"></div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="txtAddGroupName" class="col-sm-4 control-label">Name</label>
|
||||
<div class="col-sm-7">
|
||||
<input id="txtAddGroupName" type="text" class="form-control" placeholder="group name" maxlength="255">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="txtAddGroupDescription" class="col-sm-4 control-label">Description</label>
|
||||
<div class="col-sm-7">
|
||||
<textarea id="txtAddGroupDescription" class="form-control" rows="5" maxlength="255"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button id="btnAddGroup" type="submit" class="btn btn-primary" data-loading-text="Adding..." onclick="addGroup(this); return false;">Add</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="modalGroupDetails" class="modal fade" tabindex="-1" role="dialog">
|
||||
<form class="form-horizontal">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title">Group Details</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div id="divGroupDetailsAlert"></div>
|
||||
|
||||
<div id="divGroupDetailsLoader" style="height: 500px;"></div>
|
||||
|
||||
<div id="divGroupDetailsViewer" style="max-height: 500px; overflow-y: auto; padding: 0 6px; overflow-x: hidden;">
|
||||
<div class="form-group">
|
||||
<label for="txtGroupDetailsName" class="col-sm-4 control-label">Name</label>
|
||||
<div class="col-sm-7">
|
||||
<input id="txtGroupDetailsName" type="text" class="form-control" placeholder="group name" maxlength="255">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="txtGroupDetailsDescription" class="col-sm-4 control-label">Description</label>
|
||||
<div class="col-sm-7">
|
||||
<textarea id="txtGroupDetailsDescription" class="form-control" rows="3" maxlength="255"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4 control-label">Members</label>
|
||||
<div class="col-sm-7">
|
||||
<textarea id="txtGroupDetailsMembers" class="form-control" rows="7"></textarea>
|
||||
<label class="control-label" for="optGroupDetailsUserList">Add User</label>
|
||||
<select id="optGroupDetailsUserList" class="form-control"></select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button id="btnGroupDetailsSave" type="submit" class="btn btn-primary" data-loading-text="Saving..." onclick="saveGroupDetails(this); return false;">Save</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="modalEditPermissions" class="modal fade" tabindex="-1" role="dialog">
|
||||
<form class="form-horizontal">
|
||||
<div class="modal-dialog" role="document" style="width: 780px;">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title">Edit Permissions - <span id="lblEditPermissionsName"></span></h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div id="divEditPermissionsAlert"></div>
|
||||
|
||||
<div id="divEditPermissionsLoader" style="height: 500px;"></div>
|
||||
|
||||
<div id="divEditPermissionsViewer" style="max-height: 500px; overflow-y: auto; padding: 0 6px; overflow-x: hidden;">
|
||||
<div class="well well-sm" style="background-color: #fbfbfb;">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">User Permissions</label>
|
||||
<div class="col-sm-9">
|
||||
<table id="tableEditPermissionsUser" class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th onclick="sortTable('tbodyEditPermissionsUser', 0);">User</th>
|
||||
<th onclick="sortTable('tbodyEditPermissionsUser', 0);" style="width: 65px;">View</th>
|
||||
<th onclick="sortTable('tbodyEditPermissionsUser', 0);" style="width: 65px;">Modify</th>
|
||||
<th onclick="sortTable('tbodyEditPermissionsUser', 0);" style="width: 65px;">Delete</th>
|
||||
<th style="width: 76px;"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tbodyEditPermissionsUser"></tbody>
|
||||
</table>
|
||||
<label class="control-label" for="optEditPermissionsUserList">Add User</label>
|
||||
<select id="optEditPermissionsUserList" class="form-control"></select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="well well-sm" style="background-color: #fbfbfb;">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">Group Permissions</label>
|
||||
<div class="col-sm-9">
|
||||
<table id="tableEditPermissionsGroup" class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th onclick="sortTable('tbodyEditPermissionsGroup', 0);">Group</th>
|
||||
<th onclick="sortTable('tbodyEditPermissionsGroup', 0);" style="width: 65px;">View</th>
|
||||
<th onclick="sortTable('tbodyEditPermissionsGroup', 0);" style="width: 65px;">Modify</th>
|
||||
<th onclick="sortTable('tbodyEditPermissionsGroup', 0);" style="width: 65px;">Delete</th>
|
||||
<th style="width: 76px;"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tbodyEditPermissionsGroup"></tbody>
|
||||
</table>
|
||||
<label class="control-label" for="optEditPermissionsGroupList">Add Group</label>
|
||||
<select id="optEditPermissionsGroupList" class="form-control"></select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button id="btnEditPermissionsSave" type="submit" class="btn btn-primary" data-loading-text="Saving...">Save</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="footer"></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Technitium DNS Server
|
||||
Copyright (C) 2021 Shreyas Zare (shreyas@technitium.com)
|
||||
Copyright (C) 2022 Shreyas Zare (shreyas@technitium.com)
|
||||
|
||||
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
|
||||
@@ -25,7 +25,7 @@ function refreshApps() {
|
||||
divViewAppsLoader.show();
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/apps/list?token=" + token,
|
||||
url: "/api/apps/list?token=" + sessionData.token,
|
||||
success: function (responseJSON) {
|
||||
var apps = responseJSON.response.apps;
|
||||
var tableHtmlRows = "";
|
||||
@@ -117,7 +117,7 @@ function showStoreAppsModal() {
|
||||
$("#modalStoreApps").modal("show");
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/apps/listStoreApps?token=" + token,
|
||||
url: "/api/apps/listStoreApps?token=" + sessionData.token,
|
||||
success: function (responseJSON) {
|
||||
var storeApps = responseJSON.response.storeApps;
|
||||
var tableHtmlRows = "";
|
||||
@@ -196,7 +196,7 @@ function installStoreApp(objBtn, appName, url) {
|
||||
btn.button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/apps/downloadAndInstall?token=" + token + "&name=" + encodeURIComponent(appName) + "&url=" + encodeURIComponent(url),
|
||||
url: "/api/apps/downloadAndInstall?token=" + sessionData.token + "&name=" + encodeURIComponent(appName) + "&url=" + encodeURIComponent(url),
|
||||
success: function (responseJSON) {
|
||||
btn.button('reset');
|
||||
btn.hide();
|
||||
@@ -230,7 +230,7 @@ function updateStoreApp(objBtn, appName, url, isModal) {
|
||||
btn.button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/apps/downloadAndUpdate?token=" + token + "&name=" + encodeURIComponent(appName) + "&url=" + encodeURIComponent(url),
|
||||
url: "/api/apps/downloadAndUpdate?token=" + sessionData.token + "&name=" + encodeURIComponent(appName) + "&url=" + encodeURIComponent(url),
|
||||
success: function (responseJSON) {
|
||||
btn.button('reset');
|
||||
btn.hide();
|
||||
@@ -272,7 +272,7 @@ function uninstallStoreApp(objBtn, appName) {
|
||||
btn.button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/apps/uninstall?token=" + token + "&name=" + encodeURIComponent(appName),
|
||||
url: "/api/apps/uninstall?token=" + sessionData.token + "&name=" + encodeURIComponent(appName),
|
||||
success: function (responseJSON) {
|
||||
btn.button('reset');
|
||||
btn.hide();
|
||||
@@ -321,9 +321,9 @@ function installApp() {
|
||||
var btn = $("#btnInstallApp").button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/apps/install?token=" + token + "&name=" + encodeURIComponent(appName),
|
||||
url: "/api/apps/install?token=" + sessionData.token + "&name=" + encodeURIComponent(appName),
|
||||
data: formData,
|
||||
dataIsFormData: true,
|
||||
processData: false,
|
||||
success: function (responseJSON) {
|
||||
$("#modalInstallApp").modal("hide");
|
||||
|
||||
@@ -359,9 +359,9 @@ function updateApp() {
|
||||
var btn = $("#btnUpdateApp").button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/apps/update?token=" + token + "&name=" + encodeURIComponent(appName),
|
||||
url: "/api/apps/update?token=" + sessionData.token + "&name=" + encodeURIComponent(appName),
|
||||
data: formData,
|
||||
dataIsFormData: true,
|
||||
processData: false,
|
||||
success: function (responseJSON) {
|
||||
$("#modalUpdateApp").modal("hide");
|
||||
|
||||
@@ -389,7 +389,7 @@ function uninstallApp(objBtn, appName) {
|
||||
btn.button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/apps/uninstall?token=" + token + "&name=" + encodeURIComponent(appName),
|
||||
url: "/api/apps/uninstall?token=" + sessionData.token + "&name=" + encodeURIComponent(appName),
|
||||
success: function (responseJSON) {
|
||||
var id = btn.attr("data-id");
|
||||
$("#trApp" + id).remove();
|
||||
@@ -418,7 +418,7 @@ function showAppConfigModal(objBtn, appName) {
|
||||
btn.button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/apps/getConfig?token=" + token + "&name=" + encodeURIComponent(appName),
|
||||
url: "/api/apps/config/get?token=" + sessionData.token + "&name=" + encodeURIComponent(appName),
|
||||
success: function (responseJSON) {
|
||||
btn.button('reset');
|
||||
|
||||
@@ -453,8 +453,9 @@ function saveAppConfig() {
|
||||
var btn = $("#btnAppConfig").button("loading");
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/apps/setConfig?token=" + token + "&name=" + encodeURIComponent(appName),
|
||||
data: "config=" + config,
|
||||
url: "/api/apps/config/set?token=" + sessionData.token + "&name=" + encodeURIComponent(appName),
|
||||
data: "config=" + encodeURIComponent(config),
|
||||
processData: false,
|
||||
success: function (responseJSON) {
|
||||
$("#modalAppConfig").modal("hide");
|
||||
|
||||
@@ -469,4 +470,4 @@ function saveAppConfig() {
|
||||
},
|
||||
objAlertPlaceholder: divAppConfigAlert
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
1710
DnsServerCore/www/js/auth.js
Normal file
1710
DnsServerCore/www/js/auth.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Technitium DNS Server
|
||||
Copyright (C) 2021 Shreyas Zare (shreyas@technitium.com)
|
||||
Copyright (C) 2022 Shreyas Zare (shreyas@technitium.com)
|
||||
|
||||
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
|
||||
@@ -25,25 +25,20 @@ function htmlDecode(value) {
|
||||
return $('<div/>').html(value).text();
|
||||
}
|
||||
|
||||
function HTTPRequest(url, data, success, error, invalidToken, objAlertPlaceholder, objLoaderPlaceholder, dataIsFormData, dataContentType, dontHideAlert, showInnerError) {
|
||||
var async = false;
|
||||
function HTTPRequest(url, data, success, error, invalidToken, objAlertPlaceholder, objLoaderPlaceholder, processData, dataContentType, dontHideAlert, showInnerError) {
|
||||
var finalUrl;
|
||||
|
||||
finalUrl = arguments[0].url;
|
||||
|
||||
if (data == null)
|
||||
if (data == null) {
|
||||
if (arguments[0].data == null)
|
||||
data = "";
|
||||
else
|
||||
data = arguments[0].data;
|
||||
}
|
||||
|
||||
if (success != null)
|
||||
async = true;
|
||||
else
|
||||
if (arguments[0].success != null) {
|
||||
async = true;
|
||||
success = arguments[0].success;
|
||||
}
|
||||
if (success == null)
|
||||
success = arguments[0].success;
|
||||
|
||||
if (error == null)
|
||||
error = arguments[0].error;
|
||||
@@ -69,8 +64,8 @@ function HTTPRequest(url, data, success, error, invalidToken, objAlertPlaceholde
|
||||
if (objLoaderPlaceholder == null)
|
||||
objLoaderPlaceholder = arguments[0].objLoaderPlaceholder;
|
||||
|
||||
if (dataIsFormData == null)
|
||||
dataIsFormData = arguments[0].dataIsFormData;
|
||||
if (processData == null)
|
||||
processData = arguments[0].processData;
|
||||
|
||||
if (dataContentType == null)
|
||||
dataContentType = arguments[0].dataContentType;
|
||||
@@ -78,22 +73,12 @@ function HTTPRequest(url, data, success, error, invalidToken, objAlertPlaceholde
|
||||
if (objLoaderPlaceholder != null)
|
||||
objLoaderPlaceholder.html("<div style='width: 64px; height: inherit; margin: auto;'><div style='height: inherit; display: table-cell; vertical-align: middle;'><img src='/img/loader.gif'/></div></div>");
|
||||
|
||||
var successFlag = false;
|
||||
var processData;
|
||||
|
||||
if (dataIsFormData != null) {
|
||||
if (dataIsFormData == true) {
|
||||
processData = false;
|
||||
dataContentType = false;
|
||||
}
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: finalUrl,
|
||||
data: data,
|
||||
dataType: "json",
|
||||
async: async,
|
||||
async: true,
|
||||
cache: false,
|
||||
processData: processData,
|
||||
contentType: dataContentType,
|
||||
@@ -157,8 +142,6 @@ function HTTPRequest(url, data, success, error, invalidToken, objAlertPlaceholde
|
||||
showAlert("danger", "Error!", msg, objAlertPlaceholder);
|
||||
}
|
||||
});
|
||||
|
||||
return successFlag;
|
||||
}
|
||||
|
||||
function HTTPGetFileRequest(url, success, error, objAlertPlaceholder, objLoaderPlaceholder, dontHideAlert) {
|
||||
@@ -312,7 +295,7 @@ function sortTable(tableId, n) {
|
||||
}
|
||||
|
||||
function serializeTableData(table, columns) {
|
||||
var data = table.find('input:text, select');
|
||||
var data = table.find('input:text, input:checkbox, input:hidden, select');
|
||||
var output = "";
|
||||
|
||||
for (var i = 0; i < data.length; i += columns) {
|
||||
@@ -324,19 +307,28 @@ function serializeTableData(table, columns) {
|
||||
output += "|";
|
||||
|
||||
var cell = $(data[i + j]);
|
||||
var cellValue = cell.val();
|
||||
var optional = (cell.attr("data-optional") === "true");
|
||||
|
||||
if ((cellValue === "") && !optional) {
|
||||
showAlert("warning", "Missing!", "Please enter a valid value in the text field in focus.");
|
||||
cell.focus();
|
||||
return false;
|
||||
var cellValue;
|
||||
|
||||
if (cell.attr("type") == "checkbox") {
|
||||
cellValue = cell.prop("checked").toString();
|
||||
}
|
||||
else {
|
||||
cellValue = cell.val();
|
||||
|
||||
if (cellValue.includes("|")) {
|
||||
showAlert("warning", "Invalid Character!", "Please edit the value in the text field in focus to remove '|' character.");
|
||||
cell.focus();
|
||||
return false;
|
||||
var optional = (cell.attr("data-optional") === "true");
|
||||
|
||||
if ((cellValue === "") && !optional) {
|
||||
showAlert("warning", "Missing!", "Please enter a valid value in the text field in focus.");
|
||||
cell.focus();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cellValue.includes("|")) {
|
||||
showAlert("warning", "Invalid Character!", "Please edit the value in the text field in focus to remove '|' character.");
|
||||
cell.focus();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
output += htmlDecode(cellValue);
|
||||
|
||||
@@ -34,7 +34,7 @@ function refreshDhcpLeases() {
|
||||
divDhcpLeasesLoader.show();
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/listDhcpLeases?token=" + token,
|
||||
url: "/api/dhcp/leases/list?token=" + sessionData.token,
|
||||
success: function (responseJSON) {
|
||||
var dhcpLeases = responseJSON.response.leases;
|
||||
var tableHtmlRows = "";
|
||||
@@ -72,22 +72,25 @@ function refreshDhcpLeases() {
|
||||
});
|
||||
}
|
||||
|
||||
function convertToReservedLease(index, scopeName, clientIdentifier) {
|
||||
function convertToReservedLease(id, scopeName, clientIdentifier) {
|
||||
if (!confirm("Are you sure you want to convert the dynamic lease to reserved lease?"))
|
||||
return;
|
||||
|
||||
var btn = $("#btnDhcpLeaseRowOption" + index);
|
||||
var btn = $("#btnDhcpLeaseRowOption" + id);
|
||||
var originalBtnHtml = btn.html();
|
||||
btn.prop("disabled", true);
|
||||
btn.html("<img src='/img/loader-small.gif'/>");
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/convertToReservedLease?token=" + token + "&name=" + encodeURIComponent(scopeName) + "&clientIdentifier=" + encodeURIComponent(clientIdentifier),
|
||||
url: "/api/dhcp/leases/convertToReserved?token=" + sessionData.token + "&name=" + encodeURIComponent(scopeName) + "&clientIdentifier=" + encodeURIComponent(clientIdentifier),
|
||||
success: function (responseJSON) {
|
||||
btn.prop("disabled", false);
|
||||
btn.html(originalBtnHtml);
|
||||
|
||||
$("#btnDhcpLeaseReserve" + index).hide();
|
||||
$("#btnDhcpLeaseUnreserve" + index).show();
|
||||
$("#btnDhcpLeaseReserve" + id).hide();
|
||||
$("#btnDhcpLeaseUnreserve" + id).show();
|
||||
|
||||
var spanDhcpLeaseType = $("#spanDhcpLeaseType" + index);
|
||||
var spanDhcpLeaseType = $("#spanDhcpLeaseType" + id);
|
||||
spanDhcpLeaseType.html("Reserved");
|
||||
spanDhcpLeaseType.attr("class", "label label-default");
|
||||
|
||||
@@ -95,6 +98,7 @@ function convertToReservedLease(index, scopeName, clientIdentifier) {
|
||||
},
|
||||
error: function () {
|
||||
btn.prop("disabled", false);
|
||||
btn.html(originalBtnHtml);
|
||||
},
|
||||
invalidToken: function () {
|
||||
showPageLogin();
|
||||
@@ -102,22 +106,25 @@ function convertToReservedLease(index, scopeName, clientIdentifier) {
|
||||
});
|
||||
}
|
||||
|
||||
function convertToDynamicLease(index, scopeName, clientIdentifier) {
|
||||
function convertToDynamicLease(id, scopeName, clientIdentifier) {
|
||||
if (!confirm("Are you sure you want to convert the reserved lease to dynamic lease?"))
|
||||
return;
|
||||
|
||||
var btn = $("#btnDhcpLeaseRowOption" + index);
|
||||
var btn = $("#btnDhcpLeaseRowOption" + id);
|
||||
var originalBtnHtml = btn.html();
|
||||
btn.prop("disabled", true);
|
||||
btn.html("<img src='/img/loader-small.gif'/>");
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/convertToDynamicLease?token=" + token + "&name=" + encodeURIComponent(scopeName) + "&clientIdentifier=" + encodeURIComponent(clientIdentifier),
|
||||
url: "/api/dhcp/leases/convertToDynamic?token=" + sessionData.token + "&name=" + encodeURIComponent(scopeName) + "&clientIdentifier=" + encodeURIComponent(clientIdentifier),
|
||||
success: function (responseJSON) {
|
||||
btn.prop("disabled", false);
|
||||
btn.html(originalBtnHtml);
|
||||
|
||||
$("#btnDhcpLeaseReserve" + index).show();
|
||||
$("#btnDhcpLeaseUnreserve" + index).hide();
|
||||
$("#btnDhcpLeaseReserve" + id).show();
|
||||
$("#btnDhcpLeaseUnreserve" + id).hide();
|
||||
|
||||
var spanDhcpLeaseType = $("#spanDhcpLeaseType" + index);
|
||||
var spanDhcpLeaseType = $("#spanDhcpLeaseType" + id);
|
||||
spanDhcpLeaseType.html("Dynamic");
|
||||
spanDhcpLeaseType.attr("class", "label label-primary");
|
||||
|
||||
@@ -125,6 +132,7 @@ function convertToDynamicLease(index, scopeName, clientIdentifier) {
|
||||
},
|
||||
error: function () {
|
||||
btn.prop("disabled", false);
|
||||
btn.html(originalBtnHtml);
|
||||
},
|
||||
invalidToken: function () {
|
||||
showPageLogin();
|
||||
@@ -145,7 +153,7 @@ function removeLease(objBtn, index, scopeName, clientIdentifier) {
|
||||
btn.button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/removeDhcpLease?token=" + token + "&name=" + encodeURIComponent(scopeName) + "&clientIdentifier=" + encodeURIComponent(clientIdentifier),
|
||||
url: "/api/dhcp/leases/remove?token=" + sessionData.token + "&name=" + encodeURIComponent(scopeName) + "&clientIdentifier=" + encodeURIComponent(clientIdentifier),
|
||||
success: function (responseJSON) {
|
||||
btn.button('reset');
|
||||
$("#modalDhcpRemoveLease").modal("hide");
|
||||
@@ -187,7 +195,7 @@ function refreshDhcpScopes(checkDisplay) {
|
||||
divDhcpViewScopesLoader.show();
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/listDhcpScopes?token=" + token,
|
||||
url: "/api/dhcp/scopes/list?token=" + sessionData.token,
|
||||
success: function (responseJSON) {
|
||||
var dhcpScopes = responseJSON.response.scopes;
|
||||
var tableHtmlRows = "";
|
||||
@@ -321,7 +329,7 @@ function showEditDhcpScope(scopeName) {
|
||||
divDhcpViewScopesLoader.show();
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/getDhcpScope?token=" + token + "&name=" + scopeName,
|
||||
url: "/api/dhcp/scopes/get?token=" + sessionData.token + "&name=" + scopeName,
|
||||
success: function (responseJSON) {
|
||||
$("#txtDhcpScopeName").attr("data-name", responseJSON.response.name);
|
||||
$("#txtDhcpScopeName").val(responseJSON.response.name);
|
||||
@@ -459,7 +467,7 @@ function saveDhcpScope() {
|
||||
var btn = $("#btnSaveDhcpScope").button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/setDhcpScope?token=" + token + "&name=" + encodeURIComponent(name) + (newName == null ? "" : "&newName=" + encodeURIComponent(newName)) + "&startingAddress=" + encodeURIComponent(startingAddress) + "&endingAddress=" + encodeURIComponent(endingAddress) + "&subnetMask=" + encodeURIComponent(subnetMask) +
|
||||
url: "/api/dhcp/scopes/set?token=" + sessionData.token + "&name=" + encodeURIComponent(name) + (newName == null ? "" : "&newName=" + encodeURIComponent(newName)) + "&startingAddress=" + encodeURIComponent(startingAddress) + "&endingAddress=" + encodeURIComponent(endingAddress) + "&subnetMask=" + encodeURIComponent(subnetMask) +
|
||||
"&leaseTimeDays=" + leaseTimeDays + "&leaseTimeHours=" + leaseTimeHours + "&leaseTimeMinutes=" + leaseTimeMinutes + "&offerDelayTime=" + offerDelayTime + "&pingCheckEnabled=" + pingCheckEnabled + "&pingCheckTimeout=" + pingCheckTimeout + "&pingCheckRetries=" + pingCheckRetries +
|
||||
"&domainName=" + encodeURIComponent(domainName) + "&dnsTtl=" + dnsTtl + "&serverAddress=" + encodeURIComponent(serverAddress) + "&serverHostName=" + encodeURIComponent(serverHostName) + "&bootFileName=" + encodeURIComponent(bootFileName) +
|
||||
"&routerAddress=" + encodeURIComponent(routerAddress) + "&useThisDnsServer=" + useThisDnsServer + (useThisDnsServer ? "" : "&dnsServers=" + encodeURIComponent(dnsServers)) + "&winsServers=" + encodeURIComponent(winsServers) + "&ntpServers=" + encodeURIComponent(ntpServers) +
|
||||
@@ -492,7 +500,7 @@ function disableDhcpScope(scopeName) {
|
||||
divDhcpViewScopesLoader.show();
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/disableDhcpScope?token=" + token + "&name=" + scopeName,
|
||||
url: "/api/dhcp/scopes/disable?token=" + sessionData.token + "&name=" + scopeName,
|
||||
success: function (responseJSON) {
|
||||
refreshDhcpScopes();
|
||||
showAlert("success", "Scope Disabled!", "DHCP Scope was disabled successfully.");
|
||||
@@ -518,7 +526,7 @@ function enableDhcpScope(scopeName) {
|
||||
divDhcpViewScopesLoader.show();
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/enableDhcpScope?token=" + token + "&name=" + scopeName,
|
||||
url: "/api/dhcp/scopes/enable?token=" + sessionData.token + "&name=" + scopeName,
|
||||
success: function (responseJSON) {
|
||||
refreshDhcpScopes();
|
||||
showAlert("success", "Scope Enabled!", "DHCP Scope was enabled successfully.");
|
||||
@@ -547,7 +555,7 @@ function deleteDhcpScope(index, scopeName) {
|
||||
divDhcpViewScopesLoader.show();
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/deleteDhcpScope?token=" + token + "&name=" + scopeName,
|
||||
url: "/api/dhcp/scopes/delete?token=" + sessionData.token + "&name=" + scopeName,
|
||||
success: function (responseJSON) {
|
||||
$("#trDhcpScopeRow" + index).remove();
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Technitium DNS Server
|
||||
Copyright (C) 2021 Shreyas Zare (shreyas@technitium.com)
|
||||
Copyright (C) 2022 Shreyas Zare (shreyas@technitium.com)
|
||||
|
||||
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
|
||||
@@ -55,7 +55,7 @@ function refreshLogFilesList() {
|
||||
var lstLogFiles = $("#lstLogFiles");
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/listLogs?token=" + token,
|
||||
url: "/api/logs/list?token=" + sessionData.token,
|
||||
success: function (responseJSON) {
|
||||
var logFiles = responseJSON.response.logFiles;
|
||||
|
||||
@@ -96,7 +96,7 @@ function viewLog(logFile) {
|
||||
divLogViewer.show();
|
||||
|
||||
HTTPGetFileRequest({
|
||||
url: "/log/" + logFile + "?limit=2&token=" + token,
|
||||
url: "/api/logs/download?token=" + sessionData.token + "&fileName=" + encodeURIComponent(logFile) + "&limit=2",
|
||||
success: function (response) {
|
||||
|
||||
divLogViewerLoader.hide();
|
||||
@@ -110,7 +110,7 @@ function viewLog(logFile) {
|
||||
|
||||
function downloadLog() {
|
||||
var logFile = $("#txtLogViewerTitle").text();
|
||||
window.open("/log/" + logFile + "?token=" + token + "&ts=" + (new Date().getTime()), "_blank");
|
||||
window.open("/api/logs/download?token=" + sessionData.token + "&fileName=" + encodeURIComponent(logFile) + "&ts=" + (new Date().getTime()), "_blank");
|
||||
}
|
||||
|
||||
function deleteLog() {
|
||||
@@ -122,7 +122,7 @@ function deleteLog() {
|
||||
var btn = $("#btnDeleteLog").button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/deleteLog?token=" + token + "&log=" + logFile,
|
||||
url: "/api/logs/delete?token=" + sessionData.token + "&log=" + logFile,
|
||||
success: function (responseJSON) {
|
||||
refreshLogFilesList();
|
||||
|
||||
@@ -146,7 +146,7 @@ function deleteAllLogs() {
|
||||
return;
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/deleteAllLogs?token=" + token,
|
||||
url: "/api/logs/deleteAll?token=" + sessionData.token,
|
||||
success: function (responseJSON) {
|
||||
refreshLogFilesList();
|
||||
|
||||
@@ -165,7 +165,7 @@ function deleteAllStats() {
|
||||
return;
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/deleteAllStats?token=" + token,
|
||||
url: "/api/dashboard/stats/deleteAll?token=" + sessionData.token,
|
||||
success: function (responseJSON) {
|
||||
showAlert("success", "Stats Deleted!", "All stats files were deleted successfully.");
|
||||
},
|
||||
@@ -180,7 +180,6 @@ var appsList;
|
||||
function refreshQueryLogsTab() {
|
||||
var frmQueryLogs = $("#frmQueryLogs");
|
||||
var divQueryLogsLoader = $("#divQueryLogsLoader");
|
||||
var divQueryLogsTable = $("#divQueryLogsTable");
|
||||
|
||||
var optQueryLogsAppName = $("#optQueryLogsAppName");
|
||||
var optQueryLogsClassPath = $("#optQueryLogsClassPath");
|
||||
@@ -191,7 +190,6 @@ function refreshQueryLogsTab() {
|
||||
|
||||
if (appsList == null) {
|
||||
frmQueryLogs.hide();
|
||||
divQueryLogsTable.hide();
|
||||
loader = divQueryLogsLoader;
|
||||
}
|
||||
else {
|
||||
@@ -200,7 +198,7 @@ function refreshQueryLogsTab() {
|
||||
}
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/apps/list?token=" + token,
|
||||
url: "/api/apps/list?token=" + sessionData.token,
|
||||
success: function (responseJSON) {
|
||||
var apps = responseJSON.response.apps;
|
||||
|
||||
@@ -254,7 +252,6 @@ function refreshQueryLogsTab() {
|
||||
error: function () {
|
||||
if (appsList == null) {
|
||||
frmQueryLogs.show();
|
||||
divQueryLogsTable.show();
|
||||
}
|
||||
else {
|
||||
optQueryLogsAppName.prop('disabled', false);
|
||||
@@ -315,7 +312,7 @@ function queryLogs(pageNumber) {
|
||||
btn.button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/queryLogs?token=" + token + "&name=" + encodeURIComponent(name) + "&classPath=" + encodeURIComponent(classPath) + "&pageNumber=" + pageNumber + "&entriesPerPage=" + entriesPerPage + "&descendingOrder=" + descendingOrder +
|
||||
url: "/api/logs/query?token=" + sessionData.token + "&name=" + encodeURIComponent(name) + "&classPath=" + encodeURIComponent(classPath) + "&pageNumber=" + pageNumber + "&entriesPerPage=" + entriesPerPage + "&descendingOrder=" + descendingOrder +
|
||||
"&start=" + encodeURIComponent(start) + "&end=" + encodeURIComponent(end) + "&clientIpAddress=" + encodeURIComponent(clientIpAddress) + "&protocol=" + protocol + "&responseType=" + responseType + "&rcode=" + rcode +
|
||||
"&qname=" + encodeURIComponent(qname) + "&qtype=" + qtype + "&qclass=" + qclass,
|
||||
success: function (responseJSON) {
|
||||
|
||||
@@ -17,14 +17,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
var token = null;
|
||||
var refreshTimerHandle;
|
||||
var reverseProxyDetected = false;
|
||||
|
||||
function showPageLogin() {
|
||||
hideAlert();
|
||||
|
||||
localStorage.removeItem("username");
|
||||
localStorage.removeItem("token");
|
||||
|
||||
$("#pageMain").hide();
|
||||
@@ -43,13 +41,10 @@ function showPageLogin() {
|
||||
}
|
||||
}
|
||||
|
||||
function showPageMain(username) {
|
||||
function showPageMain() {
|
||||
hideAlert();
|
||||
|
||||
$("#pageLogin").hide();
|
||||
|
||||
$("#mnuUserDisplayName").text(username);
|
||||
$("#txtChangePasswordUsername").val(username);
|
||||
$("#mnuUser").show();
|
||||
|
||||
$(".nav-tabs li").removeClass("active");
|
||||
@@ -60,14 +55,17 @@ function showPageMain(username) {
|
||||
$("#settingsTabPaneGeneral").addClass("active");
|
||||
$("#dhcpTabListLeases").addClass("active");
|
||||
$("#dhcpTabPaneLeases").addClass("active");
|
||||
$("#adminTabListSessions").addClass("active");
|
||||
$("#adminTabPaneSessions").addClass("active");
|
||||
$("#logsTabListLogViewer").addClass("active");
|
||||
$("#logsTabPaneLogViewer").addClass("active");
|
||||
$("#divDhcpViewScopes").show();
|
||||
$("#divDhcpEditScope").hide();
|
||||
|
||||
$("#divViewZones").show();
|
||||
$("#divEditZone").hide();
|
||||
|
||||
$("#divDhcpViewScopes").show();
|
||||
$("#divDhcpEditScope").hide();
|
||||
|
||||
$("#txtDnsClientNameServer").val("This Server {this-server}");
|
||||
$("#txtDnsClientDomain").val("");
|
||||
$("#optDnsClientType").val("A");
|
||||
@@ -79,13 +77,143 @@ function showPageMain(username) {
|
||||
$("#divLogViewer").hide();
|
||||
$("#divQueryLogsTable").hide();
|
||||
|
||||
if (sessionData.info.permissions.Dashboard.canView) {
|
||||
$("#mainPanelTabListDashboard").show();
|
||||
refreshDashboard();
|
||||
}
|
||||
else {
|
||||
$("#mainPanelTabListDashboard").hide();
|
||||
|
||||
$("#mainPanelTabListDashboard").removeClass("active");
|
||||
$("#mainPanelTabPaneDashboard").removeClass("active");
|
||||
|
||||
if (sessionData.info.permissions.Zones.canView) {
|
||||
$("#mainPanelTabListZones").addClass("active");
|
||||
$("#mainPanelTabPaneZones").addClass("active");
|
||||
refreshZones(true);
|
||||
}
|
||||
else if (sessionData.info.permissions.Cache.canView) {
|
||||
$("#mainPanelTabListCachedZones").addClass("active");
|
||||
$("#mainPanelTabPaneCachedZones").addClass("active");
|
||||
}
|
||||
else if (sessionData.info.permissions.Allowed.canView) {
|
||||
$("#mainPanelTabListAllowedZones").addClass("active");
|
||||
$("#mainPanelTabPaneAllowedZones").addClass("active");
|
||||
}
|
||||
else if (sessionData.info.permissions.Blocked.canView) {
|
||||
$("#mainPanelTabListBlockedZones").addClass("active");
|
||||
$("#mainPanelTabPaneBlockedZones").addClass("active");
|
||||
}
|
||||
else if (sessionData.info.permissions.Apps.canView) {
|
||||
$("#mainPanelTabListApps").addClass("active");
|
||||
$("#mainPanelTabPaneApps").addClass("active");
|
||||
refreshApps();
|
||||
}
|
||||
else if (sessionData.info.permissions.DnsClient.canView) {
|
||||
$("#mainPanelTabListDnsClient").addClass("active");
|
||||
$("#mainPanelTabPaneDnsClient").addClass("active");
|
||||
}
|
||||
else if (sessionData.info.permissions.Settings.canView) {
|
||||
$("#mainPanelTabListSettings").addClass("active");
|
||||
$("#mainPanelTabPaneSettings").addClass("active");
|
||||
loadDnsSettings()
|
||||
}
|
||||
else if (sessionData.info.permissions.DhcpServer.canView) {
|
||||
$("#mainPanelTabListDhcp").addClass("active");
|
||||
$("#mainPanelTabPaneDhcp").addClass("active");
|
||||
refreshDhcpTab();
|
||||
}
|
||||
else if (sessionData.info.permissions.Administration.canView) {
|
||||
$("#mainPanelTabListAdmin").addClass("active");
|
||||
$("#mainPanelTabPaneAdmin").addClass("active");
|
||||
refreshAdminTab();
|
||||
}
|
||||
else if (sessionData.info.permissions.Logs.canView) {
|
||||
$("#mainPanelTabListLogs").addClass("active");
|
||||
$("#mainPanelTabPaneLogs").addClass("active");
|
||||
refreshLogsTab();
|
||||
}
|
||||
else {
|
||||
$("#mainPanelTabListAbout").addClass("active");
|
||||
$("#mainPanelTabPaneAbout").addClass("active");
|
||||
}
|
||||
}
|
||||
|
||||
if (sessionData.info.permissions.Zones.canView) {
|
||||
$("#mainPanelTabListZones").show();
|
||||
}
|
||||
else {
|
||||
$("#mainPanelTabListZones").hide();
|
||||
}
|
||||
|
||||
if (sessionData.info.permissions.Cache.canView) {
|
||||
$("#mainPanelTabListCachedZones").show();
|
||||
refreshCachedZonesList();
|
||||
}
|
||||
else {
|
||||
$("#mainPanelTabListCachedZones").hide();
|
||||
}
|
||||
|
||||
if (sessionData.info.permissions.Allowed.canView) {
|
||||
$("#mainPanelTabListAllowedZones").show();
|
||||
refreshAllowedZonesList();
|
||||
}
|
||||
else {
|
||||
$("#mainPanelTabListAllowedZones").hide();
|
||||
}
|
||||
|
||||
if (sessionData.info.permissions.Blocked.canView) {
|
||||
$("#mainPanelTabListBlockedZones").show();
|
||||
refreshBlockedZonesList();
|
||||
}
|
||||
else {
|
||||
$("#mainPanelTabListBlockedZones").hide();
|
||||
}
|
||||
|
||||
if (sessionData.info.permissions.Apps.canView) {
|
||||
$("#mainPanelTabListApps").show();
|
||||
}
|
||||
else {
|
||||
$("#mainPanelTabListApps").hide();
|
||||
}
|
||||
|
||||
if (sessionData.info.permissions.DnsClient.canView) {
|
||||
$("#mainPanelTabListDnsClient").show();
|
||||
}
|
||||
else {
|
||||
$("#mainPanelTabListDnsClient").hide();
|
||||
}
|
||||
|
||||
if (sessionData.info.permissions.Settings.canView) {
|
||||
$("#mainPanelTabListSettings").show();
|
||||
}
|
||||
else {
|
||||
$("#mainPanelTabListSettings").hide();
|
||||
}
|
||||
|
||||
if (sessionData.info.permissions.DhcpServer.canView) {
|
||||
$("#mainPanelTabListDhcp").show();
|
||||
}
|
||||
else {
|
||||
$("#mainPanelTabListDhcp").hide();
|
||||
}
|
||||
|
||||
if (sessionData.info.permissions.Administration.canView) {
|
||||
$("#mainPanelTabListAdmin").show();
|
||||
}
|
||||
else {
|
||||
$("#mainPanelTabListAdmin").hide();
|
||||
}
|
||||
|
||||
if (sessionData.info.permissions.Logs.canView) {
|
||||
$("#mainPanelTabListLogs").show();
|
||||
}
|
||||
else {
|
||||
$("#mainPanelTabListLogs").hide();
|
||||
}
|
||||
|
||||
$("#pageMain").show();
|
||||
|
||||
loadDnsSettings();
|
||||
refreshDashboard();
|
||||
refreshCachedZonesList();
|
||||
refreshAllowedZonesList();
|
||||
refreshBlockedZonesList();
|
||||
checkForUpdate();
|
||||
|
||||
refreshTimerHandle = setInterval(function () {
|
||||
@@ -505,145 +633,11 @@ $(function () {
|
||||
});
|
||||
|
||||
$("#lblDoHHost").text(window.location.hostname + ":8053");
|
||||
|
||||
token = localStorage.getItem("token");
|
||||
if (token == null) {
|
||||
showPageLogin();
|
||||
login("admin", "admin");
|
||||
}
|
||||
else {
|
||||
username = localStorage.getItem("username");
|
||||
if (username == null)
|
||||
username = "admin";
|
||||
|
||||
showPageMain(username);
|
||||
}
|
||||
});
|
||||
|
||||
function login(username, password) {
|
||||
var autoLogin = false;
|
||||
|
||||
if (username == null) {
|
||||
username = $("#txtUser").val().toLowerCase();
|
||||
password = $("#txtPass").val();
|
||||
}
|
||||
else {
|
||||
autoLogin = true;
|
||||
}
|
||||
|
||||
if ((username === null) || (username === "")) {
|
||||
showAlert("warning", "Missing!", "Please enter an username.");
|
||||
$("#txtUser").focus();
|
||||
return;
|
||||
}
|
||||
|
||||
if ((password === null) || (password === "")) {
|
||||
showAlert("warning", "Missing!", "Please enter a password.");
|
||||
$("#txtPass").focus();
|
||||
return;
|
||||
}
|
||||
|
||||
var btn = $("#btnLogin").button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/login?user=" + encodeURIComponent(username) + "&pass=" + encodeURIComponent(password),
|
||||
success: function (responseJSON) {
|
||||
token = responseJSON.token;
|
||||
|
||||
localStorage.setItem("username", username);
|
||||
localStorage.setItem("token", token);
|
||||
|
||||
showPageMain(username);
|
||||
|
||||
if ((username === "admin") && (password === "admin")) {
|
||||
$('#modalChangePassword').modal();
|
||||
|
||||
setTimeout(function () {
|
||||
$("#txtChangePasswordNewPassword").focus();
|
||||
}, 1000);
|
||||
}
|
||||
},
|
||||
error: function () {
|
||||
btn.button('reset');
|
||||
$("#txtUser").focus();
|
||||
|
||||
if (autoLogin)
|
||||
hideAlert();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function logout() {
|
||||
HTTPRequest({
|
||||
url: "/api/logout?token=" + token,
|
||||
success: function (responseJSON) {
|
||||
token = null;
|
||||
showPageLogin();
|
||||
},
|
||||
error: function () {
|
||||
token = null;
|
||||
showPageLogin();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function resetChangePasswordModal() {
|
||||
$("#divChangePasswordAlert").html("");
|
||||
$("#txtChangePasswordNewPassword").val("");
|
||||
$("#txtChangePasswordConfirmPassword").val("");
|
||||
|
||||
setTimeout(function () {
|
||||
$("#txtChangePasswordNewPassword").focus();
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function changePassword() {
|
||||
var divChangePasswordAlert = $("#divChangePasswordAlert");
|
||||
var newPassword = $("#txtChangePasswordNewPassword").val();
|
||||
var confirmPassword = $("#txtChangePasswordConfirmPassword").val();
|
||||
|
||||
if ((newPassword === null) || (newPassword === "")) {
|
||||
showAlert("warning", "Missing!", "Please enter new password.", divChangePasswordAlert);
|
||||
$("#txtChangePasswordNewPassword").focus();
|
||||
return;
|
||||
}
|
||||
|
||||
if ((confirmPassword === null) || (confirmPassword === "")) {
|
||||
showAlert("warning", "Missing!", "Please enter confirm password.", divChangePasswordAlert);
|
||||
$("#txtChangePasswordConfirmPassword").focus();
|
||||
return;
|
||||
}
|
||||
|
||||
if (newPassword !== confirmPassword) {
|
||||
showAlert("warning", "Mismatch!", "Passwords do not match. Please try again.", divChangePasswordAlert);
|
||||
$("#txtChangePasswordNewPassword").focus();
|
||||
return;
|
||||
}
|
||||
|
||||
var btn = $("#btnChangePasswordSave").button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/changePassword?token=" + token + "&pass=" + encodeURIComponent(newPassword),
|
||||
success: function (responseJSON) {
|
||||
$("#modalChangePassword").modal("hide");
|
||||
btn.button('reset');
|
||||
|
||||
showAlert("success", "Password Changed!", "Password was changed successfully.");
|
||||
},
|
||||
error: function () {
|
||||
btn.button('reset');
|
||||
},
|
||||
invalidToken: function () {
|
||||
btn.button('reset');
|
||||
showPageLogin();
|
||||
},
|
||||
objAlertPlaceholder: divChangePasswordAlert
|
||||
});
|
||||
}
|
||||
|
||||
function checkForUpdate() {
|
||||
HTTPRequest({
|
||||
url: "/api/checkForUpdate?token=" + token,
|
||||
url: "/api/user/checkForUpdate?token=" + sessionData.token,
|
||||
success: function (responseJSON) {
|
||||
var lnkUpdateAvailable = $("#lnkUpdateAvailable");
|
||||
|
||||
@@ -714,7 +708,7 @@ function loadDnsSettings() {
|
||||
divDnsSettingsLoader.show();
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/getDnsSettings?token=" + token,
|
||||
url: "/api/settings/get?token=" + sessionData.token,
|
||||
success: function (responseJSON) {
|
||||
document.title = responseJSON.response.dnsServerDomain + " - " + "Technitium DNS Server v" + responseJSON.response.version;
|
||||
$("#lblAboutVersion").text(responseJSON.response.version);
|
||||
@@ -794,6 +788,7 @@ function loadDnsSettings() {
|
||||
|
||||
$("#txtDefaultRecordTtl").val(responseJSON.response.defaultRecordTtl);
|
||||
$("#txtAddEditRecordTtl").attr("placeholder", responseJSON.response.defaultRecordTtl);
|
||||
$("#chkDnsAppsEnableAutomaticUpdate").prop("checked", responseJSON.response.dnsAppsEnableAutomaticUpdate);
|
||||
|
||||
$("#chkPreferIPv6").prop("checked", responseJSON.response.preferIPv6);
|
||||
$("#txtEdnsUdpPayloadSize").val(responseJSON.response.udpPayloadSize);
|
||||
@@ -1112,6 +1107,7 @@ function saveDnsSettings() {
|
||||
tsigKeys = false;
|
||||
|
||||
var defaultRecordTtl = $("#txtDefaultRecordTtl").val();
|
||||
var dnsAppsEnableAutomaticUpdate = $("#chkDnsAppsEnableAutomaticUpdate").prop('checked');
|
||||
var preferIPv6 = $("#chkPreferIPv6").prop('checked');
|
||||
var udpPayloadSize = $("#txtEdnsUdpPayloadSize").val();
|
||||
var dnssecValidation = $("#chkDnssecValidation").prop('checked');
|
||||
@@ -1371,11 +1367,11 @@ function saveDnsSettings() {
|
||||
var btn = $("#btnSaveDnsSettings").button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/setDnsSettings?token=" + token + "&dnsServerDomain=" + dnsServerDomain + "&dnsServerLocalEndPoints=" + encodeURIComponent(dnsServerLocalEndPoints)
|
||||
url: "/api/settings/set?token=" + sessionData.token + "&dnsServerDomain=" + dnsServerDomain + "&dnsServerLocalEndPoints=" + encodeURIComponent(dnsServerLocalEndPoints)
|
||||
+ "&webServiceLocalAddresses=" + encodeURIComponent(webServiceLocalAddresses) + "&webServiceHttpPort=" + webServiceHttpPort + "&webServiceEnableTls=" + webServiceEnableTls + "&webServiceHttpToTlsRedirect=" + webServiceHttpToTlsRedirect + "&webServiceUseSelfSignedTlsCertificate=" + webServiceUseSelfSignedTlsCertificate + "&webServiceTlsPort=" + webServiceTlsPort + "&webServiceTlsCertificatePath=" + encodeURIComponent(webServiceTlsCertificatePath) + "&webServiceTlsCertificatePassword=" + encodeURIComponent(webServiceTlsCertificatePassword)
|
||||
+ "&enableDnsOverHttp=" + enableDnsOverHttp + "&enableDnsOverTls=" + enableDnsOverTls + "&enableDnsOverHttps=" + enableDnsOverHttps + "&dnsTlsCertificatePath=" + encodeURIComponent(dnsTlsCertificatePath) + "&dnsTlsCertificatePassword=" + encodeURIComponent(dnsTlsCertificatePassword)
|
||||
+ "&tsigKeys=" + encodeURIComponent(tsigKeys)
|
||||
+ "&defaultRecordTtl=" + defaultRecordTtl + "&preferIPv6=" + preferIPv6 + "&udpPayloadSize=" + udpPayloadSize + "&dnssecValidation=" + dnssecValidation
|
||||
+ "&defaultRecordTtl=" + defaultRecordTtl + "&dnsAppsEnableAutomaticUpdate=" + dnsAppsEnableAutomaticUpdate + "&preferIPv6=" + preferIPv6 + "&udpPayloadSize=" + udpPayloadSize + "&dnssecValidation=" + dnssecValidation
|
||||
+ "&resolverRetries=" + resolverRetries + "&resolverTimeout=" + resolverTimeout + "&resolverMaxStackCount=" + resolverMaxStackCount
|
||||
+ "&forwarderRetries=" + forwarderRetries + "&forwarderTimeout=" + forwarderTimeout + "&forwarderConcurrency=" + forwarderConcurrency
|
||||
+ "&clientTimeout=" + clientTimeout + "&tcpSendTimeout=" + tcpSendTimeout + "&tcpReceiveTimeout=" + tcpReceiveTimeout
|
||||
@@ -1421,6 +1417,20 @@ function saveDnsSettings() {
|
||||
if (enableBlocking)
|
||||
$("#lblTemporaryDisableBlockingTill").text("Not Set");
|
||||
|
||||
if (responseJSON.response.blockListNextUpdatedOn == null) {
|
||||
$("#lblBlockListNextUpdatedOn").text("Not Scheduled");
|
||||
}
|
||||
else {
|
||||
var blockListNextUpdatedOn = moment(responseJSON.response.blockListNextUpdatedOn);
|
||||
|
||||
if (moment().utc().isBefore(blockListNextUpdatedOn))
|
||||
$("#lblBlockListNextUpdatedOn").text(blockListNextUpdatedOn.local().format("YYYY-MM-DD HH:mm:ss"));
|
||||
else
|
||||
$("#lblBlockListNextUpdatedOn").text("Updating Now");
|
||||
}
|
||||
|
||||
$("#btnUpdateBlockListsNow").prop("disabled", (responseJSON.response.blockListUrls == null));
|
||||
|
||||
//reload forwarders
|
||||
var forwarders = responseJSON.response.forwarders;
|
||||
if (forwarders == null) {
|
||||
@@ -1543,7 +1553,7 @@ function forceUpdateBlockLists() {
|
||||
var btn = $("#btnUpdateBlockListsNow").button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/forceUpdateBlockLists?token=" + token,
|
||||
url: "/api/settings/forceUpdateBlockLists?token=" + sessionData.token,
|
||||
success: function (responseJSON) {
|
||||
btn.button('reset');
|
||||
|
||||
@@ -1576,7 +1586,7 @@ function temporaryDisableBlockingNow() {
|
||||
var btn = $("#btnTemporaryDisableBlockingNow").button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/temporaryDisableBlocking?token=" + token + "&minutes=" + minutes,
|
||||
url: "/api/settings/temporaryDisableBlocking?token=" + sessionData.token + "&minutes=" + minutes,
|
||||
success: function (responseJSON) {
|
||||
btn.button('reset');
|
||||
|
||||
@@ -1711,7 +1721,7 @@ function refreshDashboard(hideLoader) {
|
||||
}
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/getStats?token=" + token + "&type=" + type + custom,
|
||||
url: "/api/dashboard/stats/get?token=" + sessionData.token + "&type=" + type + custom,
|
||||
success: function (responseJSON) {
|
||||
|
||||
//stats
|
||||
@@ -1946,7 +1956,7 @@ function showTopStats(statsType, limit) {
|
||||
}
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/getTopStats?token=" + token + "&type=" + type + custom + "&statsType=" + statsType + "&limit=" + limit,
|
||||
url: "/api/dashboard/stats/getTop?token=" + sessionData.token + "&type=" + type + custom + "&statsType=" + statsType + "&limit=" + limit,
|
||||
success: function (responseJSON) {
|
||||
divTopStatsLoader.hide();
|
||||
|
||||
@@ -2101,7 +2111,7 @@ function resolveQuery(importRecords) {
|
||||
divDnsClientLoader.show();
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/resolveQuery?token=" + token + "&server=" + encodeURIComponent(server) + "&domain=" + encodeURIComponent(domain) + "&type=" + type + "&protocol=" + protocol + "&dnssec=" + dnssecValidation + (importRecords ? "&import=true" : ""),
|
||||
url: "/api/dnsClient/resolve?token=" + sessionData.token + "&server=" + encodeURIComponent(server) + "&domain=" + encodeURIComponent(domain) + "&type=" + type + "&protocol=" + protocol + "&dnssec=" + dnssecValidation + (importRecords ? "&import=true" : ""),
|
||||
success: function (responseJSON) {
|
||||
preDnsClientOutput.text(JSON.stringify(responseJSON.response.result, null, 2));
|
||||
|
||||
@@ -2149,6 +2159,7 @@ function resolveQuery(importRecords) {
|
||||
function resetBackupSettingsModal() {
|
||||
$("#divBackupSettingsAlert").html("");
|
||||
|
||||
$("#chkBackupAuthConfig").prop("checked", true);
|
||||
$("#chkBackupDnsSettings").prop("checked", true);
|
||||
$("#chkBackupLogSettings").prop("checked", true);
|
||||
$("#chkBackupZones").prop("checked", true);
|
||||
@@ -2172,14 +2183,15 @@ function backupSettings() {
|
||||
var allowedZones = $("#chkBackupAllowedZones").prop('checked');
|
||||
var blockedZones = $("#chkBackupBlockedZones").prop('checked');
|
||||
var dnsSettings = $("#chkBackupDnsSettings").prop('checked');
|
||||
var authConfig = $("#chkBackupAuthConfig").prop('checked');
|
||||
var logSettings = $("#chkBackupLogSettings").prop('checked');
|
||||
|
||||
if (!blockLists && !logs && !scopes && !apps && !stats && !zones && !allowedZones && !blockedZones && !dnsSettings && !logSettings) {
|
||||
if (!blockLists && !logs && !scopes && !apps && !stats && !zones && !allowedZones && !blockedZones && !dnsSettings && !authConfig && !logSettings) {
|
||||
showAlert("warning", "Missing!", "Please select at least one item to backup.", divBackupSettingsAlert);
|
||||
return;
|
||||
}
|
||||
|
||||
window.open("/api/backupSettings?token=" + token + "&blockLists=" + blockLists + "&logs=" + logs + "&scopes=" + scopes + "&apps=" + apps + "&stats=" + stats + "&zones=" + zones + "&allowedZones=" + allowedZones + "&blockedZones=" + blockedZones + "&dnsSettings=" + dnsSettings + "&logSettings=" + logSettings + "&ts=" + (new Date().getTime()), "_blank");
|
||||
window.open("/api/settings/backup?token=" + sessionData.token + "&blockLists=" + blockLists + "&logs=" + logs + "&scopes=" + scopes + "&apps=" + apps + "&stats=" + stats + "&zones=" + zones + "&allowedZones=" + allowedZones + "&blockedZones=" + blockedZones + "&dnsSettings=" + dnsSettings + "&authConfig=" + authConfig + "&logSettings=" + logSettings + "&ts=" + (new Date().getTime()), "_blank");
|
||||
|
||||
$("#modalBackupSettings").modal("hide");
|
||||
showAlert("success", "Backed Up!", "Settings were backed up successfully.");
|
||||
@@ -2190,6 +2202,7 @@ function resetRestoreSettingsModal() {
|
||||
|
||||
$("#fileBackupZip").val("");
|
||||
|
||||
$("#chkRestoreAuthConfig").prop("checked", true);
|
||||
$("#chkRestoreDnsSettings").prop("checked", true);
|
||||
$("#chkRestoreLogSettings").prop("checked", true);
|
||||
$("#chkRestoreZones").prop("checked", true);
|
||||
@@ -2222,11 +2235,12 @@ function restoreSettings() {
|
||||
var allowedZones = $("#chkRestoreAllowedZones").prop('checked');
|
||||
var blockedZones = $("#chkRestoreBlockedZones").prop('checked');
|
||||
var dnsSettings = $("#chkRestoreDnsSettings").prop('checked');
|
||||
var authConfig = $("#chkRestoreAuthConfig").prop('checked');
|
||||
var logSettings = $("#chkRestoreLogSettings").prop('checked');
|
||||
|
||||
var deleteExistingFiles = $("#chkDeleteExistingFiles").prop('checked');
|
||||
|
||||
if (!blockLists && !logs && !scopes && !apps && !stats && !zones && !allowedZones && !blockedZones && !dnsSettings && !logSettings) {
|
||||
if (!blockLists && !logs && !scopes && !apps && !stats && !zones && !allowedZones && !blockedZones && !dnsSettings && !authConfig && !logSettings) {
|
||||
showAlert("warning", "Missing!", "Please select at least one item to restore.", divRestoreSettingsAlert);
|
||||
return;
|
||||
}
|
||||
@@ -2237,9 +2251,9 @@ function restoreSettings() {
|
||||
var btn = $("#btnRestoreSettings").button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/restoreSettings?token=" + token + "&blockLists=" + blockLists + "&logs=" + logs + "&scopes=" + scopes + "&apps=" + apps + "&stats=" + stats + "&zones=" + zones + "&allowedZones=" + allowedZones + "&blockedZones=" + blockedZones + "&dnsSettings=" + dnsSettings + "&logSettings=" + logSettings + "&deleteExistingFiles=" + deleteExistingFiles,
|
||||
url: "/api/settings/restore?token=" + sessionData.token + "&blockLists=" + blockLists + "&logs=" + logs + "&scopes=" + scopes + "&apps=" + apps + "&stats=" + stats + "&zones=" + zones + "&allowedZones=" + allowedZones + "&blockedZones=" + blockedZones + "&dnsSettings=" + dnsSettings + "&authConfig=" + authConfig + "&logSettings=" + logSettings + "&deleteExistingFiles=" + deleteExistingFiles,
|
||||
data: formData,
|
||||
dataIsFormData: true,
|
||||
processData: false,
|
||||
success: function (responseJSON) {
|
||||
document.title = responseJSON.response.dnsServerDomain + " - " + "Technitium DNS Server v" + responseJSON.response.version;
|
||||
$("#lblDnsServerDomain").text(" - " + responseJSON.response.dnsServerDomain);
|
||||
|
||||
@@ -25,7 +25,7 @@ function flushDnsCache(objBtn) {
|
||||
btn.button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/flushDnsCache?token=" + token,
|
||||
url: "/api/cache/flush?token=" + sessionData.token,
|
||||
success: function (responseJSON) {
|
||||
$("#lstCachedZones").html("<div class=\"zone\"><a href=\"#\" onclick=\"refreshCachedZonesList(); return false;\"><b>[refresh]</b></a></div>");
|
||||
$("#txtCachedZoneViewerTitle").text("<ROOT>");
|
||||
@@ -55,7 +55,7 @@ function deleteCachedZone() {
|
||||
var btn = $("#btnDeleteCachedZone").button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/deleteCachedZone?token=" + token + "&domain=" + domain,
|
||||
url: "/api/cache/delete?token=" + sessionData.token + "&domain=" + domain,
|
||||
success: function (responseJSON) {
|
||||
refreshCachedZonesList(getParentDomain(domain), "up");
|
||||
|
||||
@@ -103,7 +103,7 @@ function refreshCachedZonesList(domain, direction) {
|
||||
preCachedZoneViewerBody.hide();
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/listCachedZones?token=" + token + "&domain=" + domain + ((direction == null) ? "" : "&direction=" + direction),
|
||||
url: "/api/cache/list?token=" + sessionData.token + "&domain=" + domain + ((direction == null) ? "" : "&direction=" + direction),
|
||||
success: function (responseJSON) {
|
||||
var newDomain = responseJSON.response.domain;
|
||||
var zones = responseJSON.response.zones;
|
||||
@@ -161,7 +161,7 @@ function allowZone() {
|
||||
var btn = $("#btnAllowZone").button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/allowZone?token=" + token + "&domain=" + domain,
|
||||
url: "/api/allowed/add?token=" + sessionData.token + "&domain=" + domain,
|
||||
success: function (responseJSON) {
|
||||
refreshAllowedZonesList(domain);
|
||||
|
||||
@@ -189,7 +189,7 @@ function deleteAllowedZone() {
|
||||
var btn = $("#btnDeleteAllowedZone").button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/deleteAllowedZone?token=" + token + "&domain=" + domain,
|
||||
url: "/api/allowed/delete?token=" + sessionData.token + "&domain=" + domain,
|
||||
success: function (responseJSON) {
|
||||
refreshAllowedZonesList(getParentDomain(domain), "up");
|
||||
|
||||
@@ -213,7 +213,7 @@ function flushAllowedZone() {
|
||||
var btn = $("#btnFlushAllowedZone").button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/flushAllowedZone?token=" + token,
|
||||
url: "/api/allowed/flush?token=" + sessionData.token,
|
||||
success: function (responseJSON) {
|
||||
$("#lstAllowedZones").html("<div class=\"zone\"><a href=\"#\" onclick=\"refreshAllowedZonesList(); return false;\"><b>[refresh]</b></a></div>");
|
||||
$("#txtAllowedZoneViewerTitle").text("<ROOT>");
|
||||
@@ -247,7 +247,7 @@ function refreshAllowedZonesList(domain, direction) {
|
||||
preAllowedZoneViewerBody.hide();
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/listAllowedZones?token=" + token + "&domain=" + domain + ((direction == null) ? "" : "&direction=" + direction),
|
||||
url: "/api/allowed/list?token=" + sessionData.token + "&domain=" + domain + ((direction == null) ? "" : "&direction=" + direction),
|
||||
success: function (responseJSON) {
|
||||
var newDomain = responseJSON.response.domain;
|
||||
var zones = responseJSON.response.zones;
|
||||
@@ -306,7 +306,7 @@ function blockZone() {
|
||||
var btn = $("#btnBlockZone").button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/blockZone?token=" + token + "&domain=" + domain,
|
||||
url: "/api/blocked/add?token=" + sessionData.token + "&domain=" + domain,
|
||||
success: function (responseJSON) {
|
||||
refreshBlockedZonesList(domain);
|
||||
|
||||
@@ -334,7 +334,7 @@ function deleteBlockedZone() {
|
||||
var btn = $("#btnDeleteBlockedZone").button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/deleteBlockedZone?token=" + token + "&domain=" + domain,
|
||||
url: "/api/blocked/delete?token=" + sessionData.token + "&domain=" + domain,
|
||||
success: function (responseJSON) {
|
||||
refreshBlockedZonesList(getParentDomain(domain), "up");
|
||||
|
||||
@@ -358,7 +358,7 @@ function flushBlockedZone() {
|
||||
var btn = $("#btnFlushBlockedZone").button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/flushBlockedZone?token=" + token,
|
||||
url: "/api/blocked/flush?token=" + sessionData.token,
|
||||
success: function (responseJSON) {
|
||||
$("#lstBlockedZones").html("<div class=\"zone\"><a href=\"#\" onclick=\"refreshBlockedZonesList(); return false;\"><b>[refresh]</b></a></div>");
|
||||
$("#txtBlockedZoneViewerTitle").text("<ROOT>");
|
||||
@@ -392,7 +392,7 @@ function refreshBlockedZonesList(domain, direction) {
|
||||
preBlockedZoneViewerBody.hide();
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/listBlockedZones?token=" + token + "&domain=" + domain + ((direction == null) ? "" : "&direction=" + direction),
|
||||
url: "/api/blocked/list?token=" + sessionData.token + "&domain=" + domain + ((direction == null) ? "" : "&direction=" + direction),
|
||||
success: function (responseJSON) {
|
||||
var newDomain = responseJSON.response.domain;
|
||||
var zones = responseJSON.response.zones;
|
||||
@@ -461,8 +461,9 @@ function importAllowedZones() {
|
||||
var btn = $("#btnImportAllowedZones").button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/importAllowedZones?token=" + token,
|
||||
data: "allowedZones=" + allowedZones,
|
||||
url: "/api/allowed/import?token=" + sessionData.token,
|
||||
data: "allowedZones=" + encodeURIComponent(allowedZones),
|
||||
processData: false,
|
||||
success: function (responseJSON) {
|
||||
$("#modalImportAllowedZones").modal("hide");
|
||||
btn.button('reset');
|
||||
@@ -481,7 +482,7 @@ function importAllowedZones() {
|
||||
}
|
||||
|
||||
function exportAllowedZones() {
|
||||
window.open("/api/exportAllowedZones?token=" + token, "_blank");
|
||||
window.open("/api/allowed/export?token=" + sessionData.token, "_blank");
|
||||
|
||||
showAlert("success", "Exported!", "Allowed zones were exported successfully.");
|
||||
}
|
||||
@@ -508,8 +509,9 @@ function importBlockedZones() {
|
||||
var btn = $("#btnImportBlockedZones").button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/importBlockedZones?token=" + token,
|
||||
data: "blockedZones=" + blockedZones,
|
||||
url: "/api/blocked/import?token=" + sessionData.token,
|
||||
data: "blockedZones=" + encodeURIComponent(blockedZones),
|
||||
processData: false,
|
||||
success: function (responseJSON) {
|
||||
$("#modalImportBlockedZones").modal("hide");
|
||||
btn.button('reset');
|
||||
@@ -528,7 +530,7 @@ function importBlockedZones() {
|
||||
}
|
||||
|
||||
function exportBlockedZones() {
|
||||
window.open("/api/exportBlockedZones?token=" + token, "_blank");
|
||||
window.open("/api/blocked/export?token=" + sessionData.token, "_blank");
|
||||
|
||||
showAlert("success", "Exported!", "Blocked zones were exported successfully.");
|
||||
}
|
||||
|
||||
@@ -272,7 +272,7 @@ function refreshZones(checkDisplay) {
|
||||
divViewZonesLoader.show();
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/zone/list?token=" + token,
|
||||
url: "/api/zones/list?token=" + sessionData.token,
|
||||
success: function (responseJSON) {
|
||||
var zones = responseJSON.response.zones;
|
||||
var tableHtmlRows = "";
|
||||
@@ -320,29 +320,47 @@ function refreshZones(checkDisplay) {
|
||||
|
||||
var isReadOnlyZone = zones[i].internal;
|
||||
|
||||
var disableOptions;
|
||||
var hideOptionsMenu;
|
||||
|
||||
switch (zones[i].type) {
|
||||
case "Primary":
|
||||
case "Secondary":
|
||||
disableOptions = zones[i].internal;
|
||||
hideOptionsMenu = zones[i].internal;
|
||||
break;
|
||||
|
||||
default:
|
||||
disableOptions = true;
|
||||
hideOptionsMenu = true;
|
||||
break;
|
||||
}
|
||||
|
||||
tableHtmlRows += "<tr id=\"trZone" + id + "\"><td>" + htmlEncode(name) + "</td>";
|
||||
tableHtmlRows += "<tr id=\"trZone" + id + "\"><td><a href=\"#\" onclick=\"showEditZone('" + name + "'); return false;\">" + htmlEncode(name === "." ? "<root>" : name) + "</a></td>";
|
||||
tableHtmlRows += "<td>" + type + "</td>";
|
||||
tableHtmlRows += "<td>" + dnssecStatus + "</td>";
|
||||
tableHtmlRows += "<td>" + status + "</td>";
|
||||
tableHtmlRows += "<td>" + expiry + "</td>";
|
||||
tableHtmlRows += "<td align=\"right\" style=\"width: 290px;\"><button type=\"button\" class=\"btn btn-primary\" style=\"font-size: 12px; padding: 2px 0px; width: 60px; margin: 0 6px 0 0;\" onclick=\"showEditZone('" + name + "');\">" + (isReadOnlyZone ? "View" : "Edit") + "</button>";
|
||||
tableHtmlRows += "<button type=\"button\" data-id=\"" + id + "\" id=\"btnEnableZone" + id + "\" class=\"btn btn-default\" style=\"font-size: 12px; padding: 2px 0px; width: 60px; margin: 0 6px 0 0;" + (zones[i].disabled ? "" : " display: none;") + "\" onclick=\"enableZone(this, '" + name + "');\" data-loading-text=\"Enabling...\"" + (zones[i].internal ? " disabled" : "") + ">Enable</button>";
|
||||
tableHtmlRows += "<button type=\"button\" data-id=\"" + id + "\" id=\"btnDisableZone" + id + "\" class=\"btn btn-warning\" style=\"font-size: 12px; padding: 2px 0px; width: 60px; margin: 0 6px 0 0;" + (!zones[i].disabled ? "" : " display: none;") + "\" onclick=\"disableZone(this, '" + name + "');\" data-loading-text=\"Disabling...\"" + (zones[i].internal ? " disabled" : "") + ">Disable</button>";
|
||||
tableHtmlRows += "<button type=\"button\" data-id=\"" + id + "\" class=\"btn btn-danger\" style=\"font-size: 12px; padding: 2px 0px; width: 60px; margin: 0 6px 0 0;\" onclick=\"deleteZone(this, '" + name + "');\" data-loading-text=\"Deleting...\"" + (zones[i].internal ? " disabled" : "") + ">Delete</button>";
|
||||
tableHtmlRows += "<button type=\"button\" class=\"btn btn-primary\" style=\"font-size: 12px; padding: 2px 0px; width: 60px; margin: 0 6px 0 0;\" onclick=\"showZoneOptionsModal('" + name + "');\"" + (disableOptions ? " disabled" : "") + ">Options</button></td></tr>";
|
||||
|
||||
tableHtmlRows += "<td align=\"right\"><div class=\"dropdown\"><a href=\"#\" id=\"btnZoneRowOption" + id + "\" class=\"dropdown-toggle\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"true\"><span class=\"glyphicon glyphicon-option-vertical\" aria-hidden=\"true\"></span></a><ul class=\"dropdown-menu dropdown-menu-right\">";
|
||||
tableHtmlRows += "<li><a href=\"#\" onclick=\"showEditZone('" + name + "'); return false;\">" + (isReadOnlyZone ? "View" : "Edit") + " Zone</a></li>";
|
||||
|
||||
if (!zones[i].internal) {
|
||||
tableHtmlRows += "<li id=\"mnuEnableZone" + id + "\"" + (zones[i].disabled ? "" : " style=\"display: none;\"") + "><a href=\"#\" data-id=\"" + id + "\" data-zone=\"" + htmlEncode(name) + "\" onclick=\"enableZoneMenu(this); return false;\">Enable</a></li>";
|
||||
tableHtmlRows += "<li id=\"mnuDisableZone" + id + "\"" + (!zones[i].disabled ? "" : " style=\"display: none;\"") + "><a href=\"#\" data-id=\"" + id + "\" data-zone=\"" + htmlEncode(name) + "\" onclick=\"disableZoneMenu(this); return false;\">Disable</a></li>";
|
||||
}
|
||||
|
||||
if (!hideOptionsMenu) {
|
||||
tableHtmlRows += "<li><a href=\"#\" onclick=\"showZoneOptionsModal('" + name + "'); return false;\">Options</a></li>";
|
||||
}
|
||||
|
||||
if (!zones[i].internal) {
|
||||
tableHtmlRows += "<li><a href=\"#\" onclick=\"showZonePermissionsModal('" + name + "'); return false;\">Permissions</a></li>";
|
||||
}
|
||||
|
||||
if (!zones[i].internal) {
|
||||
tableHtmlRows += "<li role=\"separator\" class=\"divider\"></li>";
|
||||
tableHtmlRows += "<li><a href=\"#\" data-id=\"" + id + "\" data-zone=\"" + htmlEncode(name) + "\" onclick=\"deleteZoneMenu(this); return false;\">Delete Zone</a></li>";
|
||||
}
|
||||
|
||||
tableHtmlRows += "</ul></div></td></tr>";
|
||||
}
|
||||
|
||||
$("#tableZonesBody").html(tableHtmlRows);
|
||||
@@ -366,30 +384,55 @@ function refreshZones(checkDisplay) {
|
||||
});
|
||||
}
|
||||
|
||||
function enableZone(objBtn, zone, editZone) {
|
||||
var btn = $(objBtn);
|
||||
function enableZoneMenu(objMenuItem) {
|
||||
var mnuItem = $(objMenuItem);
|
||||
|
||||
var id = mnuItem.attr("data-id");
|
||||
var zone = mnuItem.attr("data-zone");
|
||||
|
||||
var btn = $("#btnZoneRowOption" + id);
|
||||
var originalBtnHtml = btn.html();
|
||||
btn.prop("disabled", true);
|
||||
btn.html("<img src='/img/loader-small.gif'/>");
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/zones/enable?token=" + sessionData.token + "&zone=" + zone,
|
||||
success: function (responseJSON) {
|
||||
btn.prop("disabled", false);
|
||||
btn.html(originalBtnHtml);
|
||||
|
||||
$("#mnuEnableZone" + id).hide();
|
||||
$("#mnuDisableZone" + id).show();
|
||||
$("#tdZoneStatus" + id).attr("class", "label label-success");
|
||||
$("#tdZoneStatus" + id).html("Enabled");
|
||||
|
||||
showAlert("success", "Zone Enabled!", "Zone '" + zone + "' was enabled successfully.");
|
||||
},
|
||||
error: function () {
|
||||
btn.prop("disabled", false);
|
||||
btn.html(originalBtnHtml);
|
||||
},
|
||||
invalidToken: function () {
|
||||
showPageLogin();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function enableZone(objBtn) {
|
||||
var zone = $("#titleEditZone").attr("data-zone");
|
||||
|
||||
var btn = $(objBtn);
|
||||
btn.button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/zone/enable?token=" + token + "&zone=" + zone,
|
||||
url: "/api/zones/enable?token=" + sessionData.token + "&zone=" + zone,
|
||||
success: function (responseJSON) {
|
||||
btn.button('reset');
|
||||
|
||||
if (editZone) {
|
||||
$("#btnEnableZoneEditZone").hide();
|
||||
$("#btnDisableZoneEditZone").show();
|
||||
$("#titleStatusEditZone").attr("class", "label label-success");
|
||||
$("#titleStatusEditZone").html("Enabled");
|
||||
}
|
||||
else {
|
||||
var id = btn.attr("data-id");
|
||||
|
||||
$("#btnEnableZone" + id).hide();
|
||||
$("#btnDisableZone" + id).show();
|
||||
$("#tdZoneStatus" + id).attr("class", "label label-success");
|
||||
$("#tdZoneStatus" + id).html("Enabled");
|
||||
}
|
||||
$("#btnEnableZoneEditZone").hide();
|
||||
$("#btnDisableZoneEditZone").show();
|
||||
$("#titleStatusEditZone").attr("class", "label label-success");
|
||||
$("#titleStatusEditZone").html("Enabled");
|
||||
|
||||
showAlert("success", "Zone Enabled!", "Zone '" + zone + "' was enabled successfully.");
|
||||
},
|
||||
@@ -402,33 +445,61 @@ function enableZone(objBtn, zone, editZone) {
|
||||
});
|
||||
}
|
||||
|
||||
function disableZone(objBtn, zone, editZone) {
|
||||
function disableZoneMenu(objMenuItem) {
|
||||
var mnuItem = $(objMenuItem);
|
||||
|
||||
var id = mnuItem.attr("data-id");
|
||||
var zone = mnuItem.attr("data-zone");
|
||||
|
||||
if (!confirm("Are you sure you want to disable the zone '" + zone + "'?"))
|
||||
return;
|
||||
|
||||
var btn = $("#btnZoneRowOption" + id);
|
||||
var originalBtnHtml = btn.html();
|
||||
btn.prop("disabled", true);
|
||||
btn.html("<img src='/img/loader-small.gif'/>");
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/zones/disable?token=" + sessionData.token + "&zone=" + zone,
|
||||
success: function (responseJSON) {
|
||||
btn.prop("disabled", false);
|
||||
btn.html(originalBtnHtml);
|
||||
|
||||
$("#mnuEnableZone" + id).show();
|
||||
$("#mnuDisableZone" + id).hide();
|
||||
$("#tdZoneStatus" + id).attr("class", "label label-warning");
|
||||
$("#tdZoneStatus" + id).html("Disabled");
|
||||
|
||||
showAlert("success", "Zone Disabled!", "Zone '" + zone + "' was disabled successfully.");
|
||||
},
|
||||
error: function () {
|
||||
btn.prop("disabled", false);
|
||||
btn.html(originalBtnHtml);
|
||||
},
|
||||
invalidToken: function () {
|
||||
showPageLogin();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function disableZone(objBtn) {
|
||||
var zone = $("#titleEditZone").attr("data-zone");
|
||||
|
||||
if (!confirm("Are you sure you want to disable the zone '" + zone + "'?"))
|
||||
return;
|
||||
|
||||
var btn = $(objBtn);
|
||||
|
||||
btn.button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/zone/disable?token=" + token + "&zone=" + zone,
|
||||
url: "/api/zones/disable?token=" + sessionData.token + "&zone=" + zone,
|
||||
success: function (responseJSON) {
|
||||
btn.button('reset');
|
||||
|
||||
if (editZone) {
|
||||
$("#btnEnableZoneEditZone").show();
|
||||
$("#btnDisableZoneEditZone").hide();
|
||||
$("#titleStatusEditZone").attr("class", "label label-warning");
|
||||
$("#titleStatusEditZone").html("Disabled");
|
||||
}
|
||||
else {
|
||||
var id = btn.attr("data-id");
|
||||
|
||||
$("#btnEnableZone" + id).show();
|
||||
$("#btnDisableZone" + id).hide();
|
||||
$("#tdZoneStatus" + id).attr("class", "label label-warning");
|
||||
$("#tdZoneStatus" + id).html("Disabled");
|
||||
}
|
||||
$("#btnEnableZoneEditZone").show();
|
||||
$("#btnDisableZoneEditZone").hide();
|
||||
$("#titleStatusEditZone").attr("class", "label label-warning");
|
||||
$("#titleStatusEditZone").html("Disabled");
|
||||
|
||||
showAlert("success", "Zone Disabled!", "Zone '" + zone + "' was disabled successfully.");
|
||||
},
|
||||
@@ -441,35 +512,58 @@ function disableZone(objBtn, zone, editZone) {
|
||||
});
|
||||
}
|
||||
|
||||
function deleteZone(objBtn, zone, editZone) {
|
||||
function deleteZoneMenu(objMenuItem) {
|
||||
var mnuItem = $(objMenuItem);
|
||||
|
||||
var id = mnuItem.attr("data-id");
|
||||
var zone = mnuItem.attr("data-zone");
|
||||
|
||||
if (!confirm("Are you sure you want to permanently delete the zone '" + zone + "' and all its records?"))
|
||||
return;
|
||||
|
||||
if (editZone == null)
|
||||
editZone = false;
|
||||
var btn = $("#btnZoneRowOption" + id);
|
||||
var originalBtnHtml = btn.html();
|
||||
btn.prop("disabled", true);
|
||||
btn.html("<img src='/img/loader-small.gif'/>");
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/zones/delete?token=" + sessionData.token + "&zone=" + zone,
|
||||
success: function (responseJSON) {
|
||||
$("#trZone" + id).remove();
|
||||
|
||||
var totalZones = $('#tableZones >tbody >tr').length;
|
||||
|
||||
if (totalZones > 0)
|
||||
$("#tableZonesFooter").html("<tr><td colspan=\"6\"><b>Total Zones: " + totalZones + "</b></td></tr>");
|
||||
else
|
||||
$("#tableZonesFooter").html("<tr><td colspan=\"6\" align=\"center\">No Zones Found</td></tr>");
|
||||
|
||||
showAlert("success", "Zone Deleted!", "Zone '" + zone + "' was deleted successfully.");
|
||||
},
|
||||
error: function () {
|
||||
btn.prop("disabled", false);
|
||||
btn.html(originalBtnHtml);
|
||||
},
|
||||
invalidToken: function () {
|
||||
showPageLogin();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function deleteZone(objBtn) {
|
||||
var zone = $("#titleEditZone").attr("data-zone");
|
||||
|
||||
if (!confirm("Are you sure you want to permanently delete the zone '" + zone + "' and all its records?"))
|
||||
return;
|
||||
|
||||
var btn = $(objBtn);
|
||||
var id = btn.attr("data-id");
|
||||
|
||||
btn.button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/zone/delete?token=" + token + "&zone=" + zone,
|
||||
url: "/api/zones/delete?token=" + sessionData.token + "&zone=" + zone,
|
||||
success: function (responseJSON) {
|
||||
if (editZone) {
|
||||
btn.button('reset');
|
||||
refreshZones();
|
||||
}
|
||||
else {
|
||||
$("#trZone" + id).remove();
|
||||
|
||||
var totalZones = $('#tableZones >tbody >tr').length;
|
||||
|
||||
if (totalZones > 0)
|
||||
$("#tableZonesFooter").html("<tr><td colspan=\"6\"><b>Total Zones: " + totalZones + "</b></td></tr>");
|
||||
else
|
||||
$("#tableZonesFooter").html("<tr><td colspan=\"6\" align=\"center\">No Zones Found</td></tr>");
|
||||
}
|
||||
btn.button('reset');
|
||||
refreshZones();
|
||||
|
||||
showAlert("success", "Zone Deleted!", "Zone '" + zone + "' was deleted successfully.");
|
||||
},
|
||||
@@ -487,14 +581,15 @@ function showZoneOptionsModal(zone) {
|
||||
var divZoneOptionsLoader = $("#divZoneOptionsLoader");
|
||||
var divZoneOptions = $("#divZoneOptions");
|
||||
|
||||
$("#lblZoneOptionsZoneName").text(zone);
|
||||
$("#lblZoneOptionsZoneName").text(zone === "." ? "<root>" : zone);
|
||||
$("#lblZoneOptionsZoneName").attr("data-zone", zone);
|
||||
divZoneOptionsLoader.show();
|
||||
divZoneOptions.hide();
|
||||
|
||||
$("#modalZoneOptions").modal("show");
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/zone/options/get?token=" + token + "&zone=" + zone,
|
||||
url: "/api/zones/options/get?token=" + sessionData.token + "&zone=" + zone,
|
||||
success: function (responseJSON) {
|
||||
$("#txtZoneTransferNameServers").prop("disabled", true);
|
||||
$("#txtZoneNotifyNameServers").prop("disabled", true);
|
||||
@@ -605,7 +700,7 @@ function showZoneOptionsModal(zone) {
|
||||
function saveZoneOptions() {
|
||||
var divZoneOptionsAlert = $("#divZoneOptionsAlert");
|
||||
var divZoneOptionsLoader = $("#divZoneOptionsLoader");
|
||||
var zone = $("#lblZoneOptionsZoneName").text();
|
||||
var zone = $("#lblZoneOptionsZoneName").attr("data-zone");
|
||||
|
||||
var zoneTransfer = $("input[name=rdZoneTransfer]:checked").val();
|
||||
|
||||
@@ -636,7 +731,7 @@ function saveZoneOptions() {
|
||||
btn.button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/zone/options/set?token=" + token + "&zone=" + zone
|
||||
url: "/api/zones/options/set?token=" + sessionData.token + "&zone=" + zone
|
||||
+ "&zoneTransfer=" + zoneTransfer + "&zoneTransferNameServers=" + encodeURIComponent(zoneTransferNameServers)
|
||||
+ "¬ify=" + notify + "¬ifyNameServers=" + encodeURIComponent(notifyNameServers)
|
||||
+ "&zoneTransferTsigKeyNames=" + encodeURIComponent(zoneTransferTsigKeyNames),
|
||||
@@ -660,13 +755,115 @@ function saveZoneOptions() {
|
||||
});
|
||||
}
|
||||
|
||||
function resyncZone(objBtn, domain) {
|
||||
function showZonePermissionsModal(zone) {
|
||||
var divEditPermissionsAlert = $("#divEditPermissionsAlert");
|
||||
var divEditPermissionsLoader = $("#divEditPermissionsLoader");
|
||||
var divEditPermissionsViewer = $("#divEditPermissionsViewer");
|
||||
|
||||
$("#lblEditPermissionsName").text("Zones / " + (zone === "." ? "<root>" : zone));
|
||||
$("#tbodyEditPermissionsUser").html("");
|
||||
$("#tbodyEditPermissionsGroup").html("");
|
||||
|
||||
divEditPermissionsLoader.show();
|
||||
divEditPermissionsViewer.hide();
|
||||
|
||||
var btnEditPermissionsSave = $("#btnEditPermissionsSave");
|
||||
btnEditPermissionsSave.attr("onclick", "saveZonePermissions(this); return false;");
|
||||
btnEditPermissionsSave.show();
|
||||
|
||||
var modalEditPermissions = $("#modalEditPermissions");
|
||||
modalEditPermissions.modal("show");
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/zones/permissions/get?token=" + sessionData.token + "&zone=" + htmlEncode(zone) + "&includeUsersAndGroups=true",
|
||||
success: function (responseJSON) {
|
||||
$("#lblEditPermissionsName").text(responseJSON.response.section + " / " + (responseJSON.response.subItem == "." ? "<root>" : responseJSON.response.subItem));
|
||||
|
||||
//user permissions
|
||||
for (var i = 0; i < responseJSON.response.userPermissions.length; i++) {
|
||||
addEditPermissionUserRow(i, responseJSON.response.userPermissions[i].username, responseJSON.response.userPermissions[i].canView, responseJSON.response.userPermissions[i].canModify, responseJSON.response.userPermissions[i].canDelete);
|
||||
}
|
||||
|
||||
//load users list
|
||||
var userListHtml = "<option value=\"blank\" selected></option><option value=\"none\">None</option>";
|
||||
|
||||
for (var i = 0; i < responseJSON.response.users.length; i++) {
|
||||
userListHtml += "<option>" + htmlEncode(responseJSON.response.users[i]) + "</option>";
|
||||
}
|
||||
|
||||
$("#optEditPermissionsUserList").html(userListHtml);
|
||||
|
||||
//group permissions
|
||||
for (var i = 0; i < responseJSON.response.groupPermissions.length; i++) {
|
||||
addEditPermissionGroupRow(i, responseJSON.response.groupPermissions[i].name, responseJSON.response.groupPermissions[i].canView, responseJSON.response.groupPermissions[i].canModify, responseJSON.response.groupPermissions[i].canDelete);
|
||||
}
|
||||
|
||||
//load groups list
|
||||
var groupListHtml = "<option value=\"blank\" selected></option><option value=\"none\">None</option>";
|
||||
|
||||
for (var i = 0; i < responseJSON.response.groups.length; i++) {
|
||||
groupListHtml += "<option>" + htmlEncode(responseJSON.response.groups[i]) + "</option>";
|
||||
}
|
||||
|
||||
$("#optEditPermissionsGroupList").html(groupListHtml);
|
||||
|
||||
btnEditPermissionsSave.attr("data-zone", responseJSON.response.subItem);
|
||||
|
||||
divEditPermissionsLoader.hide();
|
||||
divEditPermissionsViewer.show();
|
||||
},
|
||||
error: function () {
|
||||
divEditPermissionsLoader.hide();
|
||||
},
|
||||
invalidToken: function () {
|
||||
modalEditPermissions.modal("hide");
|
||||
showPageLogin();
|
||||
},
|
||||
objAlertPlaceholder: divEditPermissionsAlert,
|
||||
objLoaderPlaceholder: divEditPermissionsLoader
|
||||
});
|
||||
}
|
||||
|
||||
function saveZonePermissions(objBtn) {
|
||||
var btn = $(objBtn);
|
||||
var divEditPermissionsAlert = $("#divEditPermissionsAlert");
|
||||
|
||||
var zone = btn.attr("data-zone");
|
||||
|
||||
var userPermissions = serializeTableData($("#tableEditPermissionsUser"), 4);
|
||||
var groupPermissions = serializeTableData($("#tableEditPermissionsGroup"), 4);
|
||||
|
||||
var apiUrl = "/api/zones/permissions/set?token=" + sessionData.token + "&zone=" + encodeURIComponent(zone) + "&userPermissions=" + encodeURIComponent(userPermissions) + "&groupPermissions=" + encodeURIComponent(groupPermissions);
|
||||
|
||||
btn.button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: apiUrl,
|
||||
success: function (responseJSON) {
|
||||
btn.button('reset');
|
||||
$("#modalEditPermissions").modal("hide");
|
||||
|
||||
showAlert("success", "Permissions Saved!", "Zone permissions were saved successfully.");
|
||||
},
|
||||
error: function () {
|
||||
btn.button('reset');
|
||||
},
|
||||
invalidToken: function () {
|
||||
btn.button('reset');
|
||||
$("#modalEditPermissions").modal("hide");
|
||||
showPageLogin();
|
||||
},
|
||||
objAlertPlaceholder: divEditPermissionsAlert
|
||||
});
|
||||
}
|
||||
|
||||
function resyncZone(objBtn, zone) {
|
||||
if ($("#titleEditZoneType").text() == "Secondary") {
|
||||
if (!confirm("The resync action will perform a full zone transfer (AXFR). You will need to check the logs to confirm if the resync action was successful.\r\n\r\nAre you sure you want to resync the '" + domain + "' zone?"))
|
||||
if (!confirm("The resync action will perform a full zone transfer (AXFR). You will need to check the logs to confirm if the resync action was successful.\r\n\r\nAre you sure you want to resync the '" + zone + "' zone?"))
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (!confirm("The resync action will perform a full zone refresh. You will need to check the logs to confirm if the resync action was successful.\r\n\r\nAre you sure you want to resync the '" + domain + "' zone?"))
|
||||
if (!confirm("The resync action will perform a full zone refresh. You will need to check the logs to confirm if the resync action was successful.\r\n\r\nAre you sure you want to resync the '" + zone + "' zone?"))
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -674,10 +871,10 @@ function resyncZone(objBtn, domain) {
|
||||
btn.button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/zone/resync?token=" + token + "&domain=" + domain,
|
||||
url: "/api/zones/resync?token=" + sessionData.token + "&zone=" + zone,
|
||||
success: function (responseJSON) {
|
||||
btn.button('reset');
|
||||
showAlert("success", "Resync Triggered!", "Zone '" + domain + "' resync was triggered successfully. Please check the Logs for confirmation.");
|
||||
showAlert("success", "Resync Triggered!", "Zone '" + zone + "' resync was triggered successfully. Please check the Logs for confirmation.");
|
||||
},
|
||||
error: function () {
|
||||
btn.button('reset');
|
||||
@@ -829,7 +1026,7 @@ function addZone() {
|
||||
var btn = $("#btnAddZone").button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/zone/create?token=" + token + "&zone=" + zone + "&type=" + type + parameters,
|
||||
url: "/api/zones/create?token=" + sessionData.token + "&zone=" + zone + "&type=" + type + parameters,
|
||||
success: function (responseJSON) {
|
||||
$("#modalAddZone").modal("hide");
|
||||
showEditZone(responseJSON.response.domain);
|
||||
@@ -849,7 +1046,7 @@ function addZone() {
|
||||
|
||||
function toggleHideDnssecRecords(hideDnssecRecords) {
|
||||
localStorage.setItem("zoneHideDnssecRecords", hideDnssecRecords);
|
||||
showEditZone($("#titleEditZone").text());
|
||||
showEditZone($("#titleEditZone").attr("data-zone"));
|
||||
}
|
||||
|
||||
function showEditZone(zone) {
|
||||
@@ -862,7 +1059,7 @@ function showEditZone(zone) {
|
||||
divViewZonesLoader.show();
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/zone/getRecords?token=" + token + "&domain=" + zone,
|
||||
url: "/api/zones/records/get?token=" + sessionData.token + "&domain=" + zone,
|
||||
success: function (responseJSON) {
|
||||
var zoneType;
|
||||
if (responseJSON.response.zone.internal)
|
||||
@@ -936,7 +1133,7 @@ function showEditZone(zone) {
|
||||
$("#optAddEditRecordTypeDs").hide();
|
||||
$("#optAddEditRecordTypeAName").show();
|
||||
$("#optAddEditRecordTypeFwd").show();
|
||||
$("#optAddEditRecordTypeApp").hide();
|
||||
$("#optAddEditRecordTypeApp").show();
|
||||
break;
|
||||
|
||||
case "Primary":
|
||||
@@ -998,6 +1195,19 @@ function showEditZone(zone) {
|
||||
break;
|
||||
}
|
||||
|
||||
switch (zoneType) {
|
||||
case "Primary":
|
||||
case "Secondary":
|
||||
case "Stub":
|
||||
case "Forwarder":
|
||||
$("#btnZonePermissions").show();
|
||||
break;
|
||||
|
||||
default:
|
||||
$("#btnZonePermissions").hide();
|
||||
break;
|
||||
}
|
||||
|
||||
var zoneHideDnssecRecords = (localStorage.getItem("zoneHideDnssecRecords") == "true");
|
||||
|
||||
switch (zoneType) {
|
||||
@@ -1084,7 +1294,8 @@ function showEditZone(zone) {
|
||||
tableHtmlRows += getZoneRecordRowHtml(i, zone, zoneType, records[i]);
|
||||
}
|
||||
|
||||
$("#titleEditZone").text(zone);
|
||||
$("#titleEditZone").text(zone === "." ? "<root>" : zone);
|
||||
$("#titleEditZone").attr("data-zone", zone);
|
||||
$("#tableEditZoneBody").html(tableHtmlRows);
|
||||
|
||||
if (recordCount > 0)
|
||||
@@ -1694,13 +1905,13 @@ function clearAddEditForm() {
|
||||
|
||||
function showAddRecordModal(objBtn) {
|
||||
var zoneType = $("#titleEditZoneType").text();
|
||||
if (zoneType === "Primary") {
|
||||
if ((zoneType === "Primary") || (zoneType === "Forwarder")) {
|
||||
var btn = $(objBtn);
|
||||
|
||||
btn.button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/apps/list?token=" + token,
|
||||
url: "/api/apps/list?token=" + sessionData.token,
|
||||
success: function (responseJSON) {
|
||||
btn.button('reset');
|
||||
|
||||
@@ -1722,7 +1933,7 @@ function showAddRecordModal(objBtn) {
|
||||
var appsList;
|
||||
|
||||
function showAddRecordModalNow(apps) {
|
||||
var zone = $("#titleEditZone").text();
|
||||
var zone = $("#titleEditZone").attr("data-zone");
|
||||
|
||||
clearAddEditForm();
|
||||
|
||||
@@ -1898,7 +2109,7 @@ function addRecord() {
|
||||
var btn = $("#btnAddEditRecord");
|
||||
var divAddEditRecordAlert = $("#divAddEditRecordAlert");
|
||||
|
||||
var zone = $("#titleEditZone").text();
|
||||
var zone = $("#titleEditZone").attr("data-zone");
|
||||
|
||||
var domain;
|
||||
{
|
||||
@@ -1920,7 +2131,7 @@ function addRecord() {
|
||||
var overwrite = $("#chkAddEditRecordOverwrite").prop("checked");
|
||||
var comments = $("#txtAddEditRecordComments").val();
|
||||
|
||||
var apiUrl = "/api/zone/addRecord?token=" + token + "&zone=" + encodeURIComponent(zone) + "&domain=" + encodeURIComponent(domain) + "&type=" + type + "&ttl=" + ttl + "&overwrite=" + overwrite + "&comments=" + encodeURIComponent(comments);
|
||||
var apiUrl = "/api/zones/records/add?token=" + sessionData.token + "&zone=" + encodeURIComponent(zone) + "&domain=" + encodeURIComponent(domain) + "&type=" + type + "&ttl=" + ttl + "&overwrite=" + overwrite + "&comments=" + encodeURIComponent(comments);
|
||||
|
||||
switch (type) {
|
||||
case "A":
|
||||
@@ -2271,7 +2482,7 @@ function showEditRecordModal(objBtn) {
|
||||
var id = btn.attr("data-id");
|
||||
var divData = $("#data" + id);
|
||||
|
||||
var zone = $("#titleEditZone").text();
|
||||
var zone = $("#titleEditZone").attr("data-zone");
|
||||
var name = divData.attr("data-record-name");
|
||||
var type = divData.attr("data-record-type");
|
||||
var ttl = divData.attr("data-record-ttl");
|
||||
@@ -2512,7 +2723,7 @@ function updateRecord() {
|
||||
var id = btn.attr("data-id");
|
||||
var divData = $("#data" + id);
|
||||
|
||||
var zone = $("#titleEditZone").text();
|
||||
var zone = $("#titleEditZone").attr("data-zone");
|
||||
var type = divData.attr("data-record-type");
|
||||
var domain = divData.attr("data-record-name");
|
||||
|
||||
@@ -2537,7 +2748,7 @@ function updateRecord() {
|
||||
var disable = (divData.attr("data-record-disabled") === "true");
|
||||
var comments = $("#txtAddEditRecordComments").val();
|
||||
|
||||
var apiUrl = "/api/zone/updateRecord?token=" + token + "&zone=" + encodeURIComponent(zone) + "&type=" + type + "&domain=" + encodeURIComponent(domain) + "&newDomain=" + encodeURIComponent(newDomain) + "&ttl=" + ttl + "&disable=" + disable + "&comments=" + encodeURIComponent(comments);
|
||||
var apiUrl = "/api/zones/records/update?token=" + sessionData.token + "&zone=" + encodeURIComponent(zone) + "&type=" + type + "&domain=" + encodeURIComponent(domain) + "&newDomain=" + encodeURIComponent(newDomain) + "&ttl=" + ttl + "&disable=" + disable + "&comments=" + encodeURIComponent(comments);
|
||||
|
||||
switch (type) {
|
||||
case "A":
|
||||
@@ -2933,7 +3144,7 @@ function updateRecordState(objBtn, disable) {
|
||||
if (disable && !confirm("Are you sure to disable the " + type + " record '" + domain + "'?"))
|
||||
return;
|
||||
|
||||
var apiUrl = "/api/zone/updateRecord?token=" + token + "&type=" + type + "&domain=" + encodeURIComponent(domain) + "&ttl=" + ttl + "&disable=" + disable + "&comments=" + encodeURIComponent(comments);
|
||||
var apiUrl = "/api/zones/records/update?token=" + sessionData.token + "&type=" + type + "&domain=" + encodeURIComponent(domain) + "&ttl=" + ttl + "&disable=" + disable + "&comments=" + encodeURIComponent(comments);
|
||||
|
||||
switch (type) {
|
||||
case "A":
|
||||
@@ -3035,7 +3246,7 @@ function deleteRecord(objBtn) {
|
||||
var id = btn.attr("data-id");
|
||||
var divData = $("#data" + id);
|
||||
|
||||
var zone = $("#titleEditZone").text();
|
||||
var zone = $("#titleEditZone").attr("data-zone");
|
||||
var domain = divData.attr("data-record-name");
|
||||
var type = divData.attr("data-record-type");
|
||||
|
||||
@@ -3045,7 +3256,7 @@ function deleteRecord(objBtn) {
|
||||
if (!confirm("Are you sure to permanently delete the " + type + " record '" + domain + "'?"))
|
||||
return;
|
||||
|
||||
var apiUrl = "/api/zone/deleteRecord?token=" + token + "&zone=" + encodeURIComponent(zone) + "&domain=" + domain + "&type=" + type;
|
||||
var apiUrl = "/api/zones/records/delete?token=" + sessionData.token + "&zone=" + encodeURIComponent(zone) + "&domain=" + domain + "&type=" + type;
|
||||
|
||||
switch (type) {
|
||||
case "A":
|
||||
@@ -3116,7 +3327,8 @@ function deleteRecord(objBtn) {
|
||||
|
||||
function showSignZoneModal(zoneName) {
|
||||
$("#divDnssecSignZoneAlert").html("");
|
||||
$("#lblDnssecSignZoneZoneName").text(zoneName);
|
||||
$("#lblDnssecSignZoneZoneName").text(zoneName === "." ? "<root>" : zoneName);
|
||||
$("#lblDnssecSignZoneZoneName").attr("data-zone", zoneName);
|
||||
$("#rdDnssecSignZoneAlgorithmEcdsa").prop("checked", true);
|
||||
|
||||
$("#divDnssecSignZoneRsaParameters").hide();
|
||||
@@ -3141,7 +3353,7 @@ function showSignZoneModal(zoneName) {
|
||||
|
||||
function signPrimaryZone() {
|
||||
var divDnssecSignZoneAlert = $("#divDnssecSignZoneAlert");
|
||||
var zone = $("#lblDnssecSignZoneZoneName").text();
|
||||
var zone = $("#lblDnssecSignZoneZoneName").attr("data-zone");
|
||||
var algorithm = $("input[name=rdDnssecSignZoneAlgorithm]:checked").val();
|
||||
var dnsKeyTtl = $("#txtDnssecSignZoneDnsKeyTtl").val();
|
||||
var zskRolloverDays = $("#txtDnssecSignZoneZskAutoRollover").val();
|
||||
@@ -3176,7 +3388,7 @@ function signPrimaryZone() {
|
||||
btn.button("loading");
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/zone/dnssec/sign?token=" + token + "&zone=" + encodeURIComponent(zone) + "&algorithm=" + algorithm + "&dnsKeyTtl=" + dnsKeyTtl + "&zskRolloverDays=" + zskRolloverDays + "&nxProof=" + nxProof + additionalParameters,
|
||||
url: "/api/zones/dnssec/sign?token=" + sessionData.token + "&zone=" + encodeURIComponent(zone) + "&algorithm=" + algorithm + "&dnsKeyTtl=" + dnsKeyTtl + "&zskRolloverDays=" + zskRolloverDays + "&nxProof=" + nxProof + additionalParameters,
|
||||
success: function (responseJSON) {
|
||||
btn.button('reset');
|
||||
$("#modalDnssecSignZone").modal("hide");
|
||||
@@ -3213,20 +3425,21 @@ function signPrimaryZone() {
|
||||
|
||||
function showUnsignZoneModal(zoneName) {
|
||||
$("#divDnssecUnsignZoneAlert").html("");
|
||||
$("#lblDnssecUnsignZoneZoneName").text(zoneName);
|
||||
$("#lblDnssecUnsignZoneZoneName").text(zoneName === "." ? "<root>" : zoneName);
|
||||
$("#lblDnssecUnsignZoneZoneName").attr("data-zone", zoneName);
|
||||
|
||||
$("#modalDnssecUnsignZone").modal("show");
|
||||
}
|
||||
|
||||
function unsignPrimaryZone() {
|
||||
var divDnssecUnsignZoneAlert = $("#divDnssecUnsignZoneAlert");
|
||||
var zone = $("#lblDnssecUnsignZoneZoneName").text();
|
||||
var zone = $("#lblDnssecUnsignZoneZoneName").attr("data-zone");
|
||||
|
||||
var btn = $("#btnDnssecUnsignZone");
|
||||
btn.button("loading");
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/zone/dnssec/unsign?token=" + token + "&zone=" + encodeURIComponent(zone),
|
||||
url: "/api/zones/dnssec/unsign?token=" + sessionData.token + "&zone=" + encodeURIComponent(zone),
|
||||
success: function (responseJSON) {
|
||||
btn.button('reset');
|
||||
$("#modalDnssecUnsignZone").modal("hide");
|
||||
@@ -3266,7 +3479,8 @@ function showDnssecPropertiesModal(zoneName) {
|
||||
var divDnssecProperties = $("#divDnssecProperties");
|
||||
|
||||
$("#divDnssecPropertiesAlert").html("");
|
||||
$("#lblDnssecPropertiesZoneName").text(zoneName);
|
||||
$("#lblDnssecPropertiesZoneName").text(zoneName === "." ? "<root>" : zoneName);
|
||||
$("#lblDnssecPropertiesZoneName").attr("data-zone", zoneName);
|
||||
|
||||
$("#divDnssecPropertiesGenerateKey").collapse("hide");
|
||||
$("#optDnssecPropertiesGenerateKeyKeyType").val("KeySigningKey");
|
||||
@@ -3288,12 +3502,13 @@ function showDnssecPropertiesModal(zoneName) {
|
||||
|
||||
function refreshDnssecProperties(divDnssecPropertiesLoader) {
|
||||
var divDnssecPropertiesAlert = $("#divDnssecPropertiesAlert");
|
||||
var zone = $("#lblDnssecPropertiesZoneName").text();
|
||||
var zone = $("#lblDnssecPropertiesZoneName").attr("data-zone");
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/zone/dnssec/getProperties?token=" + token + "&zone=" + zone,
|
||||
url: "/api/zones/dnssec/properties/get?token=" + sessionData.token + "&zone=" + zone,
|
||||
success: function (responseJSON) {
|
||||
var tableHtmlRows = "";
|
||||
var foundGeneratedKey = false;
|
||||
|
||||
for (var i = 0; i < responseJSON.response.dnssecPrivateKeys.length; i++) {
|
||||
var id = Math.floor(Math.random() * 10000);
|
||||
@@ -3336,6 +3551,7 @@ function refreshDnssecProperties(divDnssecPropertiesLoader) {
|
||||
switch (responseJSON.response.dnssecPrivateKeys[i].state) {
|
||||
case "Generated":
|
||||
tableHtmlRows += "<button type=\"button\" class=\"btn btn-danger\" style=\"font-size: 12px; padding: 2px 0px; width: 60px;\" data-id=\"" + id + "\" data-loading-text=\"Deleting...\" onclick=\"deleteDnssecPrivateKey(" + responseJSON.response.dnssecPrivateKeys[i].keyTag + ", this);\">Delete</button>";
|
||||
foundGeneratedKey = true;
|
||||
break;
|
||||
|
||||
case "Ready":
|
||||
@@ -3351,6 +3567,7 @@ function refreshDnssecProperties(divDnssecPropertiesLoader) {
|
||||
}
|
||||
|
||||
$("#tableDnssecPropertiesPrivateKeysBody").html(tableHtmlRows);
|
||||
$("#btnDnssecPropertiesPublishKeys").prop("disabled", !foundGeneratedKey);
|
||||
|
||||
switch (responseJSON.response.dnssecStatus) {
|
||||
case "SignedWithNSEC":
|
||||
@@ -3400,13 +3617,13 @@ function updateDnssecPrivateKey(keyTag, objBtn) {
|
||||
var btn = $(objBtn);
|
||||
var id = btn.attr("data-id");
|
||||
var divDnssecPropertiesAlert = $("#divDnssecPropertiesAlert");
|
||||
var zone = $("#lblDnssecPropertiesZoneName").text();
|
||||
var zone = $("#lblDnssecPropertiesZoneName").attr("data-zone");
|
||||
var rolloverDays = $("#txtDnssecPropertiesPrivateKeyAutomaticRollover" + id).val();
|
||||
|
||||
btn.button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/zone/dnssec/updatePrivateKey?token=" + token + "&zone=" + zone + "&keyTag=" + keyTag + "&rolloverDays=" + rolloverDays,
|
||||
url: "/api/zones/dnssec/properties/updatePrivateKey?token=" + sessionData.token + "&zone=" + zone + "&keyTag=" + keyTag + "&rolloverDays=" + rolloverDays,
|
||||
success: function (responseJSON) {
|
||||
btn.button('reset');
|
||||
showAlert("success", "Updated!", "The DNSKEY automatic rollover config was updated successfully.", divDnssecPropertiesAlert);
|
||||
@@ -3430,12 +3647,12 @@ function deleteDnssecPrivateKey(keyTag, objBtn) {
|
||||
var btn = $(objBtn);
|
||||
var id = btn.attr("data-id");
|
||||
var divDnssecPropertiesAlert = $("#divDnssecPropertiesAlert");
|
||||
var zone = $("#lblDnssecPropertiesZoneName").text();
|
||||
var zone = $("#lblDnssecPropertiesZoneName").attr("data-zone");
|
||||
|
||||
btn.button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/zone/dnssec/deletePrivateKey?token=" + token + "&zone=" + zone + "&keyTag=" + keyTag,
|
||||
url: "/api/zones/dnssec/properties/deletePrivateKey?token=" + sessionData.token + "&zone=" + zone + "&keyTag=" + keyTag,
|
||||
success: function (responseJSON) {
|
||||
$("#trDnssecPropertiesPrivateKey" + id).remove();
|
||||
showAlert("success", "Private Key Deleted!", "The DNSSEC private key was deleted successfully.", divDnssecPropertiesAlert);
|
||||
@@ -3457,12 +3674,12 @@ function rolloverDnssecDnsKey(keyTag, objBtn) {
|
||||
|
||||
var btn = $(objBtn);
|
||||
var divDnssecPropertiesAlert = $("#divDnssecPropertiesAlert");
|
||||
var zone = $("#lblDnssecPropertiesZoneName").text();
|
||||
var zone = $("#lblDnssecPropertiesZoneName").attr("data-zone");
|
||||
|
||||
btn.button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/zone/dnssec/rolloverDnsKey?token=" + token + "&zone=" + zone + "&keyTag=" + keyTag,
|
||||
url: "/api/zones/dnssec/properties/rolloverDnsKey?token=" + sessionData.token + "&zone=" + zone + "&keyTag=" + keyTag,
|
||||
success: function (responseJSON) {
|
||||
refreshDnssecProperties();
|
||||
showAlert("success", "Rollover Done!", "The DNS Key was rolled over successfully.", divDnssecPropertiesAlert);
|
||||
@@ -3484,12 +3701,12 @@ function retireDnssecDnsKey(keyTag, objBtn) {
|
||||
|
||||
var btn = $(objBtn);
|
||||
var divDnssecPropertiesAlert = $("#divDnssecPropertiesAlert");
|
||||
var zone = $("#lblDnssecPropertiesZoneName").text();
|
||||
var zone = $("#lblDnssecPropertiesZoneName").attr("data-zone");
|
||||
|
||||
btn.button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/zone/dnssec/retireDnsKey?token=" + token + "&zone=" + zone + "&keyTag=" + keyTag,
|
||||
url: "/api/zones/dnssec/properties/retireDnsKey?token=" + sessionData.token + "&zone=" + zone + "&keyTag=" + keyTag,
|
||||
success: function (responseJSON) {
|
||||
refreshDnssecProperties();
|
||||
showAlert("success", "DNS Key Retired!", "The DNS Key was retired successfully.", divDnssecPropertiesAlert);
|
||||
@@ -3511,12 +3728,12 @@ function publishAllDnssecPrivateKeys(objBtn) {
|
||||
|
||||
var btn = $(objBtn);
|
||||
var divDnssecPropertiesAlert = $("#divDnssecPropertiesAlert");
|
||||
var zone = $("#lblDnssecPropertiesZoneName").text();
|
||||
var zone = $("#lblDnssecPropertiesZoneName").attr("data-zone");
|
||||
|
||||
btn.button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/zone/dnssec/publishAllPrivateKeys?token=" + token + "&zone=" + zone,
|
||||
url: "/api/zones/dnssec/properties/publishAllPrivateKeys?token=" + sessionData.token + "&zone=" + zone,
|
||||
success: function (responseJSON) {
|
||||
refreshDnssecProperties();
|
||||
btn.button('reset');
|
||||
@@ -3537,7 +3754,7 @@ function publishAllDnssecPrivateKeys(objBtn) {
|
||||
function generateAndAddDnssecPrivateKey(objBtn) {
|
||||
var btn = $(objBtn);
|
||||
var divDnssecPropertiesAlert = $("#divDnssecPropertiesAlert");
|
||||
var zone = $("#lblDnssecPropertiesZoneName").text();
|
||||
var zone = $("#lblDnssecPropertiesZoneName").attr("data-zone");
|
||||
var keyType = $("#optDnssecPropertiesGenerateKeyKeyType").val();
|
||||
var algorithm = $("#optDnssecPropertiesGenerateKeyAlgorithm").val();
|
||||
var rolloverDays = $("#txtDnssecPropertiesGenerateKeyAutomaticRollover").val();
|
||||
@@ -3562,7 +3779,7 @@ function generateAndAddDnssecPrivateKey(objBtn) {
|
||||
btn.button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/zone/dnssec/generatePrivateKey?token=" + token + "&zone=" + zone + "&keyType=" + keyType + "&rolloverDays=" + rolloverDays + "&algorithm=" + algorithm + additionalParameters,
|
||||
url: "/api/zones/dnssec/properties/generatePrivateKey?token=" + sessionData.token + "&zone=" + zone + "&keyType=" + keyType + "&rolloverDays=" + rolloverDays + "&algorithm=" + algorithm + additionalParameters,
|
||||
success: function (responseJSON) {
|
||||
$("#divDnssecPropertiesGenerateKey").collapse("hide");
|
||||
refreshDnssecProperties();
|
||||
@@ -3593,7 +3810,7 @@ function changeDnssecNxProof(objBtn) {
|
||||
|
||||
var divDnssecPropertiesAlert = $("#divDnssecPropertiesAlert");
|
||||
|
||||
var zone = $("#lblDnssecPropertiesZoneName").text();
|
||||
var zone = $("#lblDnssecPropertiesZoneName").attr("data-zone");
|
||||
var apiUrl;
|
||||
|
||||
switch (currentNxProof) {
|
||||
@@ -3606,7 +3823,7 @@ function changeDnssecNxProof(objBtn) {
|
||||
var iterations = $("#txtDnssecPropertiesNSEC3Iterations").val();
|
||||
var saltLength = $("#txtDnssecPropertiesNSEC3SaltLength").val();
|
||||
|
||||
apiUrl = "/api/zone/dnssec/convertToNSEC3?token=" + token + "&zone=" + zone + "&iterations=" + iterations + "&saltLength=" + saltLength;
|
||||
apiUrl = "/api/zones/dnssec/properties/convertToNSEC3?token=" + sessionData.token + "&zone=" + zone + "&iterations=" + iterations + "&saltLength=" + saltLength;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -3620,10 +3837,10 @@ function changeDnssecNxProof(objBtn) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
apiUrl = "/api/zone/dnssec/updateNSEC3Params?token=" + token + "&zone=" + zone + "&iterations=" + iterations + "&saltLength=" + saltLength;
|
||||
apiUrl = "/api/zones/dnssec/properties/updateNSEC3Params?token=" + sessionData.token + "&zone=" + zone + "&iterations=" + iterations + "&saltLength=" + saltLength;
|
||||
}
|
||||
} else {
|
||||
apiUrl = "/api/zone/dnssec/convertToNSEC?token=" + token + "&zone=" + zone;
|
||||
apiUrl = "/api/zones/dnssec/properties/convertToNSEC?token=" + sessionData.token + "&zone=" + zone;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -3670,13 +3887,13 @@ function changeDnssecNxProof(objBtn) {
|
||||
function updateDnssecDnsKeyTtl(objBtn) {
|
||||
var btn = $(objBtn);
|
||||
var divDnssecPropertiesAlert = $("#divDnssecPropertiesAlert");
|
||||
var zone = $("#lblDnssecPropertiesZoneName").text();
|
||||
var zone = $("#lblDnssecPropertiesZoneName").attr("data-zone");
|
||||
var ttl = $("#txtDnssecPropertiesDnsKeyTtl").val();
|
||||
|
||||
btn.button('loading');
|
||||
|
||||
HTTPRequest({
|
||||
url: "/api/zone/dnssec/updateDnsKeyTtl?token=" + token + "&zone=" + zone + "&ttl=" + ttl,
|
||||
url: "/api/zones/dnssec/properties/updateDnsKeyTtl?token=" + sessionData.token + "&zone=" + zone + "&ttl=" + ttl,
|
||||
success: function (responseJSON) {
|
||||
btn.button('reset');
|
||||
showAlert("success", "TTL Updated!", "The DNSKEY TTL was updated successfully.", divDnssecPropertiesAlert);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Technitium DNS Server
|
||||
Copyright (C) 2019 Shreyas Zare (shreyas@technitium.com)
|
||||
Copyright (C) 2022 Shreyas Zare (shreyas@technitium.com)
|
||||
|
||||
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
|
||||
@@ -52,7 +52,7 @@ namespace DnsServerSystemTrayApp
|
||||
int count = bR.ReadInt32();
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
this.Addresses.Add(IPAddressExtension.Parse(bR));
|
||||
this.Addresses.Add(IPAddressExtension.ReadFrom(bR));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -592,11 +592,15 @@ namespace DnsServerSystemTrayApp
|
||||
BinaryReader bR = new BinaryReader(fS);
|
||||
|
||||
if (Encoding.ASCII.GetString(bR.ReadBytes(2)) != "DS") //format
|
||||
throw new InvalidDataException("DnsServer config file format is invalid.");
|
||||
throw new InvalidDataException("DNS Server config file format is invalid.");
|
||||
|
||||
int version = bR.ReadByte();
|
||||
|
||||
if (version > 1)
|
||||
if (version >= 28)
|
||||
{
|
||||
port = bR.ReadInt32();
|
||||
}
|
||||
else if (version > 1)
|
||||
{
|
||||
string serverDomain = bR.ReadShortString();
|
||||
port = bR.ReadInt32();
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace DnsServerWindowsService
|
||||
if (args.Length == 2)
|
||||
configFolder = args[1];
|
||||
|
||||
_service = new DnsWebService(configFolder, new Uri("https://go.technitium.com/?id=43"), new Uri("https://go.technitium.com/?id=40"));
|
||||
_service = new DnsWebService(configFolder, new Uri("https://go.technitium.com/?id=43"), new Uri("https://go.technitium.com/?id=44"));
|
||||
}
|
||||
|
||||
public override Task StartAsync(CancellationToken cancellationToken)
|
||||
|
||||
Reference in New Issue
Block a user