/* Technitium DNS Server Copyright (C) 2023 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 . */ using DnsServerCore.ApplicationCommon; using DnsServerCore.Auth; using DnsServerCore.Dns.Applications; using Microsoft.AspNetCore.Http; using System; using System.Globalization; using System.IO; using System.Net; using System.Text.Json; using System.Threading.Tasks; using TechnitiumLibrary.Net; using TechnitiumLibrary.Net.Dns; using TechnitiumLibrary.Net.Dns.ResourceRecords; namespace DnsServerCore { class WebServiceLogsApi { #region variables readonly DnsWebService _dnsWebService; #endregion #region constructor public WebServiceLogsApi(DnsWebService dnsWebService) { _dnsWebService = dnsWebService; } #endregion #region public public void ListLogs(HttpContext context) { UserSession session = context.GetCurrentSession(); if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Logs, session.User, PermissionFlag.View)) throw new DnsWebServiceException("Access was denied."); string[] logFiles = _dnsWebService._log.ListLogFiles(); Array.Sort(logFiles); Array.Reverse(logFiles); Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter(); jsonWriter.WritePropertyName("logFiles"); jsonWriter.WriteStartArray(); foreach (string logFile in logFiles) { jsonWriter.WriteStartObject(); jsonWriter.WriteString("fileName", Path.GetFileNameWithoutExtension(logFile)); jsonWriter.WriteString("size", WebUtilities.GetFormattedSize(new FileInfo(logFile).Length)); jsonWriter.WriteEndObject(); } jsonWriter.WriteEndArray(); } public Task DownloadLogAsync(HttpContext context) { UserSession session = context.GetCurrentSession(); if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Logs, session.User, PermissionFlag.View)) throw new DnsWebServiceException("Access was denied."); HttpRequest request = context.Request; string fileName = request.GetQueryOrForm("fileName"); int limit = request.GetQueryOrForm("limit", int.Parse, 0); return _dnsWebService._log.DownloadLogAsync(context, fileName, limit * 1024 * 1024); } public void DeleteLog(HttpContext context) { UserSession session = context.GetCurrentSession(); if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Logs, session.User, PermissionFlag.Delete)) throw new DnsWebServiceException("Access was denied."); HttpRequest request = context.Request; string log = request.GetQueryOrForm("log"); _dnsWebService._log.DeleteLog(log); _dnsWebService._log.Write(context.GetRemoteEndPoint(_dnsWebService._webServiceRealIpHeader), "[" + session.User.Username + "] Log file was deleted: " + log); } public void DeleteAllLogs(HttpContext context) { UserSession session = context.GetCurrentSession(); if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Logs, session.User, PermissionFlag.Delete)) throw new DnsWebServiceException("Access was denied."); _dnsWebService._log.DeleteAllLogs(); _dnsWebService._log.Write(context.GetRemoteEndPoint(_dnsWebService._webServiceRealIpHeader), "[" + session.User.Username + "] All log files were deleted."); } public void DeleteAllStats(HttpContext context) { UserSession session = context.GetCurrentSession(); if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Dashboard, session.User, PermissionFlag.Delete)) throw new DnsWebServiceException("Access was denied."); _dnsWebService.DnsServer.StatsManager.DeleteAllStats(); _dnsWebService._log.Write(context.GetRemoteEndPoint(_dnsWebService._webServiceRealIpHeader), "[" + session.User.Username + "] All stats files were deleted."); } public async Task QueryLogsAsync(HttpContext context) { UserSession session = context.GetCurrentSession(); if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Logs, session.User, PermissionFlag.View)) throw new DnsWebServiceException("Access was denied."); HttpRequest request = context.Request; string name = request.GetQueryOrForm("name"); string classPath = request.GetQueryOrForm("classPath"); if (!_dnsWebService.DnsServer.DnsApplicationManager.Applications.TryGetValue(name, out DnsApplication application)) throw new DnsWebServiceException("DNS application was not found: " + name); if (!application.DnsQueryLoggers.TryGetValue(classPath, out IDnsQueryLogger logger)) throw new DnsWebServiceException("DNS application '" + classPath + "' class path was not found: " + name); long pageNumber = request.GetQueryOrForm("pageNumber", long.Parse, 1); int entriesPerPage = request.GetQueryOrForm("entriesPerPage", int.Parse, 25); bool descendingOrder = request.GetQueryOrForm("descendingOrder", bool.Parse, true); DateTime? start = null; string strStart = request.QueryOrForm("start"); if (!string.IsNullOrEmpty(strStart)) start = DateTime.Parse(strStart, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal); DateTime? end = null; string strEnd = request.QueryOrForm("end"); if (!string.IsNullOrEmpty(strEnd)) end = DateTime.Parse(strEnd, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal); IPAddress clientIpAddress = request.GetQueryOrForm("clientIpAddress", IPAddress.Parse, null); DnsTransportProtocol? protocol = null; string strProtocol = request.QueryOrForm("protocol"); if (!string.IsNullOrEmpty(strProtocol)) protocol = Enum.Parse(strProtocol, true); DnsServerResponseType? responseType = null; string strResponseType = request.QueryOrForm("responseType"); if (!string.IsNullOrEmpty(strResponseType)) responseType = Enum.Parse(strResponseType, true); DnsResponseCode? rcode = null; string strRcode = request.QueryOrForm("rcode"); if (!string.IsNullOrEmpty(strRcode)) rcode = Enum.Parse(strRcode, true); string qname = request.GetQueryOrForm("qname", null); DnsResourceRecordType? qtype = null; string strQtype = request.QueryOrForm("qtype"); if (!string.IsNullOrEmpty(strQtype)) qtype = Enum.Parse(strQtype, true); DnsClass? qclass = null; string strQclass = request.QueryOrForm("qclass"); if (!string.IsNullOrEmpty(strQclass)) qclass = Enum.Parse(strQclass, true); DnsLogPage page = await logger.QueryLogsAsync(pageNumber, entriesPerPage, descendingOrder, start, end, clientIpAddress, protocol, responseType, rcode, qname, qtype, qclass); Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter(); jsonWriter.WriteNumber("pageNumber", page.PageNumber); jsonWriter.WriteNumber("totalPages", page.TotalPages); jsonWriter.WriteNumber("totalEntries", page.TotalEntries); jsonWriter.WritePropertyName("entries"); jsonWriter.WriteStartArray(); foreach (DnsLogEntry entry in page.Entries) { jsonWriter.WriteStartObject(); jsonWriter.WriteNumber("rowNumber", entry.RowNumber); jsonWriter.WriteString("timestamp", entry.Timestamp); jsonWriter.WriteString("clientIpAddress", entry.ClientIpAddress.ToString()); jsonWriter.WriteString("protocol", entry.Protocol.ToString()); jsonWriter.WriteString("responseType", entry.ResponseType.ToString()); jsonWriter.WriteString("rcode", entry.RCODE.ToString()); jsonWriter.WriteString("qname", entry.Question?.Name); jsonWriter.WriteString("qtype", entry.Question?.Type.ToString()); jsonWriter.WriteString("qclass", entry.Question?.Class.ToString()); jsonWriter.WriteString("answer", entry.Answer); jsonWriter.WriteEndObject(); } jsonWriter.WriteEndArray(); } #endregion } }