merged multi-user into develop

This commit is contained in:
Shreyas Zare
2022-09-18 19:00:54 +05:30
54 changed files with 11584 additions and 3179 deletions

View 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
View 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
}
}

View 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
View 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
}
}

View 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
}
}

View File

@@ -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; }

View File

@@ -88,7 +88,7 @@ namespace DnsServerCore.Dhcp
_hostName = null;
_hardwareAddress = bR.ReadBuffer();
_address = IPAddressExtension.Parse(bR);
_address = IPAddressExtension.ReadFrom(bR);
if (version >= 2)
{

View File

@@ -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 _);
}
}

View File

@@ -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);

View File

@@ -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
{

View File

@@ -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)

View File

@@ -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))

View File

@@ -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;
}

View File

@@ -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:

View File

@@ -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

View File

@@ -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
}
}

View File

@@ -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
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -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)

View File

@@ -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();
}
}

View File

@@ -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);

View File

@@ -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
;

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

@@ -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">&times;</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">&times;</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">&times;</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">&times;</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">&times;</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">&times;</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">&times;</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">&times;</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>

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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);

View File

@@ -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();

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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.");
}

View File

@@ -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)
+ "&notify=" + notify + "&notifyNameServers=" + 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);