mirror of
https://github.com/fergalmoran/DnsServer.git
synced 2026-01-06 16:53:59 +00:00
merged multi-user into develop
This commit is contained in:
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);
|
||||
|
||||
Reference in New Issue
Block a user