WebServiceOtherZonesApi.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551
  1. /*
  2. Technitium DNS Server
  3. Copyright (C) 2024 Shreyas Zare (shreyas@technitium.com)
  4. This program is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. using DnsServerCore.Auth;
  16. using DnsServerCore.Dns.Zones;
  17. using Microsoft.AspNetCore.Http;
  18. using System.Collections.Generic;
  19. using System.IO;
  20. using System.Net;
  21. using System.Text.Json;
  22. using System.Threading.Tasks;
  23. using TechnitiumLibrary.Net;
  24. using TechnitiumLibrary.Net.Dns;
  25. using TechnitiumLibrary.Net.Dns.ResourceRecords;
  26. namespace DnsServerCore
  27. {
  28. class WebServiceOtherZonesApi
  29. {
  30. #region variables
  31. readonly DnsWebService _dnsWebService;
  32. #endregion
  33. #region constructor
  34. public WebServiceOtherZonesApi(DnsWebService dnsWebService)
  35. {
  36. _dnsWebService = dnsWebService;
  37. }
  38. #endregion
  39. #region public
  40. #region cache api
  41. public void FlushCache(HttpContext context)
  42. {
  43. UserSession session = context.GetCurrentSession();
  44. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Cache, session.User, PermissionFlag.Delete))
  45. throw new DnsWebServiceException("Access was denied.");
  46. _dnsWebService.DnsServer.CacheZoneManager.Flush();
  47. _dnsWebService._log.Write(context.GetRemoteEndPoint(_dnsWebService._webServiceRealIpHeader), "[" + session.User.Username + "] Cache was flushed.");
  48. }
  49. public void ListCachedZones(HttpContext context)
  50. {
  51. UserSession session = context.GetCurrentSession();
  52. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Cache, session.User, PermissionFlag.View))
  53. throw new DnsWebServiceException("Access was denied.");
  54. HttpRequest request = context.Request;
  55. string domain = request.GetQueryOrForm("domain", "");
  56. if (DnsClient.IsDomainNameUnicode(domain))
  57. domain = DnsClient.ConvertDomainNameToAscii(domain);
  58. string direction = request.QueryOrForm("direction");
  59. if (direction is not null)
  60. direction = direction.ToLowerInvariant();
  61. List<string> subZones = new List<string>();
  62. List<DnsResourceRecord> records = new List<DnsResourceRecord>();
  63. while (true)
  64. {
  65. subZones.Clear();
  66. records.Clear();
  67. _dnsWebService.DnsServer.CacheZoneManager.ListSubDomains(domain, subZones);
  68. _dnsWebService.DnsServer.CacheZoneManager.ListAllRecords(domain, records);
  69. if (records.Count > 0)
  70. break;
  71. if (subZones.Count != 1)
  72. break;
  73. if (direction == "up")
  74. {
  75. if (domain.Length == 0)
  76. break;
  77. int i = domain.IndexOf('.');
  78. if (i < 0)
  79. domain = "";
  80. else
  81. domain = domain.Substring(i + 1);
  82. }
  83. else if (domain.Length == 0)
  84. {
  85. domain = subZones[0];
  86. }
  87. else
  88. {
  89. domain = subZones[0] + "." + domain;
  90. }
  91. }
  92. subZones.Sort();
  93. Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
  94. jsonWriter.WriteString("domain", domain);
  95. if (DnsClient.TryConvertDomainNameToUnicode(domain, out string idn))
  96. jsonWriter.WriteString("domainIdn", idn);
  97. jsonWriter.WritePropertyName("zones");
  98. jsonWriter.WriteStartArray();
  99. if (domain.Length != 0)
  100. domain = "." + domain;
  101. foreach (string subZone in subZones)
  102. {
  103. string zone = subZone + domain;
  104. if (DnsClient.TryConvertDomainNameToUnicode(zone, out string zoneIdn))
  105. zone = zoneIdn;
  106. jsonWriter.WriteStringValue(zone);
  107. }
  108. jsonWriter.WriteEndArray();
  109. WebServiceZonesApi.WriteRecordsAsJson(records, jsonWriter, false);
  110. }
  111. public void DeleteCachedZone(HttpContext context)
  112. {
  113. UserSession session = context.GetCurrentSession();
  114. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Cache, session.User, PermissionFlag.Delete))
  115. throw new DnsWebServiceException("Access was denied.");
  116. string domain = context.Request.GetQueryOrForm("domain");
  117. if (DnsClient.IsDomainNameUnicode(domain))
  118. domain = DnsClient.ConvertDomainNameToAscii(domain);
  119. if (_dnsWebService.DnsServer.CacheZoneManager.DeleteZone(domain))
  120. _dnsWebService._log.Write(context.GetRemoteEndPoint(_dnsWebService._webServiceRealIpHeader), "[" + session.User.Username + "] Cached zone was deleted: " + domain);
  121. }
  122. #endregion
  123. #region allowed zones api
  124. public void ListAllowedZones(HttpContext context)
  125. {
  126. UserSession session = context.GetCurrentSession();
  127. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Allowed, session.User, PermissionFlag.View))
  128. throw new DnsWebServiceException("Access was denied.");
  129. HttpRequest request = context.Request;
  130. string domain = request.GetQueryOrForm("domain", "");
  131. if (DnsClient.IsDomainNameUnicode(domain))
  132. domain = DnsClient.ConvertDomainNameToAscii(domain);
  133. string direction = request.QueryOrForm("direction");
  134. if (direction is not null)
  135. direction = direction.ToLowerInvariant();
  136. List<string> subZones = new List<string>();
  137. List<DnsResourceRecord> records = new List<DnsResourceRecord>();
  138. while (true)
  139. {
  140. subZones.Clear();
  141. records.Clear();
  142. _dnsWebService.DnsServer.AllowedZoneManager.ListSubDomains(domain, subZones);
  143. _dnsWebService.DnsServer.AllowedZoneManager.ListAllRecords(domain, records);
  144. if (records.Count > 0)
  145. break;
  146. if (subZones.Count != 1)
  147. break;
  148. if (direction == "up")
  149. {
  150. if (domain.Length == 0)
  151. break;
  152. int i = domain.IndexOf('.');
  153. if (i < 0)
  154. domain = "";
  155. else
  156. domain = domain.Substring(i + 1);
  157. }
  158. else if (domain.Length == 0)
  159. {
  160. domain = subZones[0];
  161. }
  162. else
  163. {
  164. domain = subZones[0] + "." + domain;
  165. }
  166. }
  167. subZones.Sort();
  168. Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
  169. jsonWriter.WriteString("domain", domain);
  170. if (DnsClient.TryConvertDomainNameToUnicode(domain, out string idn))
  171. jsonWriter.WriteString("domainIdn", idn);
  172. jsonWriter.WritePropertyName("zones");
  173. jsonWriter.WriteStartArray();
  174. if (domain.Length != 0)
  175. domain = "." + domain;
  176. foreach (string subZone in subZones)
  177. {
  178. string zone = subZone + domain;
  179. if (DnsClient.TryConvertDomainNameToUnicode(zone, out string zoneIdn))
  180. zone = zoneIdn;
  181. jsonWriter.WriteStringValue(zone);
  182. }
  183. jsonWriter.WriteEndArray();
  184. WebServiceZonesApi.WriteRecordsAsJson(records, jsonWriter, true);
  185. }
  186. public void ImportAllowedZones(HttpContext context)
  187. {
  188. UserSession session = context.GetCurrentSession();
  189. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Allowed, session.User, PermissionFlag.Modify))
  190. throw new DnsWebServiceException("Access was denied.");
  191. HttpRequest request = context.Request;
  192. string allowedZones = request.GetQueryOrForm("allowedZones");
  193. string[] allowedZonesList = allowedZones.Split(',');
  194. for (int i = 0; i < allowedZonesList.Length; i++)
  195. {
  196. if (DnsClient.IsDomainNameUnicode(allowedZonesList[i]))
  197. allowedZonesList[i] = DnsClient.ConvertDomainNameToAscii(allowedZonesList[i]);
  198. }
  199. _dnsWebService.DnsServer.AllowedZoneManager.ImportZones(allowedZonesList);
  200. _dnsWebService._log.Write(context.GetRemoteEndPoint(_dnsWebService._webServiceRealIpHeader), "[" + session.User.Username + "] Total " + allowedZonesList.Length + " zones were imported into allowed zone successfully.");
  201. _dnsWebService.DnsServer.AllowedZoneManager.SaveZoneFile();
  202. }
  203. public async Task ExportAllowedZonesAsync(HttpContext context)
  204. {
  205. UserSession session = context.GetCurrentSession();
  206. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Allowed, session.User, PermissionFlag.View))
  207. throw new DnsWebServiceException("Access was denied.");
  208. IReadOnlyList<AuthZoneInfo> zoneInfoList = _dnsWebService.DnsServer.AllowedZoneManager.GetAllZones();
  209. HttpResponse response = context.Response;
  210. response.ContentType = "text/plain";
  211. response.Headers.ContentDisposition = "attachment;filename=AllowedZones.txt";
  212. await using (StreamWriter sW = new StreamWriter(response.Body))
  213. {
  214. foreach (AuthZoneInfo zoneInfo in zoneInfoList)
  215. await sW.WriteLineAsync(zoneInfo.Name);
  216. }
  217. }
  218. public void DeleteAllowedZone(HttpContext context)
  219. {
  220. UserSession session = context.GetCurrentSession();
  221. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Allowed, session.User, PermissionFlag.Delete))
  222. throw new DnsWebServiceException("Access was denied.");
  223. string domain = context.Request.GetQueryOrForm("domain");
  224. if (DnsClient.IsDomainNameUnicode(domain))
  225. domain = DnsClient.ConvertDomainNameToAscii(domain);
  226. if (_dnsWebService.DnsServer.AllowedZoneManager.DeleteZone(domain))
  227. {
  228. _dnsWebService._log.Write(context.GetRemoteEndPoint(_dnsWebService._webServiceRealIpHeader), "[" + session.User.Username + "] Allowed zone was deleted: " + domain);
  229. _dnsWebService.DnsServer.AllowedZoneManager.SaveZoneFile();
  230. }
  231. }
  232. public void FlushAllowedZone(HttpContext context)
  233. {
  234. UserSession session = context.GetCurrentSession();
  235. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Allowed, session.User, PermissionFlag.Delete))
  236. throw new DnsWebServiceException("Access was denied.");
  237. _dnsWebService.DnsServer.AllowedZoneManager.Flush();
  238. _dnsWebService._log.Write(context.GetRemoteEndPoint(_dnsWebService._webServiceRealIpHeader), "[" + session.User.Username + "] Allowed zone was flushed successfully.");
  239. _dnsWebService.DnsServer.AllowedZoneManager.SaveZoneFile();
  240. }
  241. public void AllowZone(HttpContext context)
  242. {
  243. UserSession session = context.GetCurrentSession();
  244. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Allowed, session.User, PermissionFlag.Modify))
  245. throw new DnsWebServiceException("Access was denied.");
  246. string domain = context.Request.GetQueryOrForm("domain");
  247. if (DnsClient.IsDomainNameUnicode(domain))
  248. domain = DnsClient.ConvertDomainNameToAscii(domain);
  249. if (IPAddress.TryParse(domain, out IPAddress ipAddress))
  250. domain = ipAddress.GetReverseDomain();
  251. if (_dnsWebService.DnsServer.AllowedZoneManager.AllowZone(domain))
  252. {
  253. _dnsWebService._log.Write(context.GetRemoteEndPoint(_dnsWebService._webServiceRealIpHeader), "[" + session.User.Username + "] Zone was allowed: " + domain);
  254. _dnsWebService.DnsServer.AllowedZoneManager.SaveZoneFile();
  255. }
  256. }
  257. #endregion
  258. #region blocked zones api
  259. public void ListBlockedZones(HttpContext context)
  260. {
  261. UserSession session = context.GetCurrentSession();
  262. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Blocked, session.User, PermissionFlag.View))
  263. throw new DnsWebServiceException("Access was denied.");
  264. HttpRequest request = context.Request;
  265. string domain = request.GetQueryOrForm("domain", "");
  266. if (DnsClient.IsDomainNameUnicode(domain))
  267. domain = DnsClient.ConvertDomainNameToAscii(domain);
  268. string direction = request.QueryOrForm("direction");
  269. if (direction is not null)
  270. direction = direction.ToLowerInvariant();
  271. List<string> subZones = new List<string>();
  272. List<DnsResourceRecord> records = new List<DnsResourceRecord>();
  273. while (true)
  274. {
  275. subZones.Clear();
  276. records.Clear();
  277. _dnsWebService.DnsServer.BlockedZoneManager.ListSubDomains(domain, subZones);
  278. _dnsWebService.DnsServer.BlockedZoneManager.ListAllRecords(domain, records);
  279. if (records.Count > 0)
  280. break;
  281. if (subZones.Count != 1)
  282. break;
  283. if (direction == "up")
  284. {
  285. if (domain.Length == 0)
  286. break;
  287. int i = domain.IndexOf('.');
  288. if (i < 0)
  289. domain = "";
  290. else
  291. domain = domain.Substring(i + 1);
  292. }
  293. else if (domain.Length == 0)
  294. {
  295. domain = subZones[0];
  296. }
  297. else
  298. {
  299. domain = subZones[0] + "." + domain;
  300. }
  301. }
  302. subZones.Sort();
  303. Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
  304. jsonWriter.WriteString("domain", domain);
  305. if (DnsClient.TryConvertDomainNameToUnicode(domain, out string idn))
  306. jsonWriter.WriteString("domainIdn", idn);
  307. jsonWriter.WritePropertyName("zones");
  308. jsonWriter.WriteStartArray();
  309. if (domain.Length != 0)
  310. domain = "." + domain;
  311. foreach (string subZone in subZones)
  312. {
  313. string zone = subZone + domain;
  314. if (DnsClient.TryConvertDomainNameToUnicode(zone, out string zoneIdn))
  315. zone = zoneIdn;
  316. jsonWriter.WriteStringValue(zone);
  317. }
  318. jsonWriter.WriteEndArray();
  319. WebServiceZonesApi.WriteRecordsAsJson(records, jsonWriter, true);
  320. }
  321. public void ImportBlockedZones(HttpContext context)
  322. {
  323. UserSession session = context.GetCurrentSession();
  324. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Blocked, session.User, PermissionFlag.Modify))
  325. throw new DnsWebServiceException("Access was denied.");
  326. HttpRequest request = context.Request;
  327. string blockedZones = request.GetQueryOrForm("blockedZones");
  328. string[] blockedZonesList = blockedZones.Split(',');
  329. for (int i = 0; i < blockedZonesList.Length; i++)
  330. {
  331. if (DnsClient.IsDomainNameUnicode(blockedZonesList[i]))
  332. blockedZonesList[i] = DnsClient.ConvertDomainNameToAscii(blockedZonesList[i]);
  333. }
  334. _dnsWebService.DnsServer.BlockedZoneManager.ImportZones(blockedZonesList);
  335. _dnsWebService._log.Write(context.GetRemoteEndPoint(_dnsWebService._webServiceRealIpHeader), "[" + session.User.Username + "] Total " + blockedZonesList.Length + " zones were imported into blocked zone successfully.");
  336. _dnsWebService.DnsServer.BlockedZoneManager.SaveZoneFile();
  337. }
  338. public async Task ExportBlockedZonesAsync(HttpContext context)
  339. {
  340. UserSession session = context.GetCurrentSession();
  341. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Blocked, session.User, PermissionFlag.View))
  342. throw new DnsWebServiceException("Access was denied.");
  343. IReadOnlyList<AuthZoneInfo> zoneInfoList = _dnsWebService.DnsServer.BlockedZoneManager.GetAllZones();
  344. HttpResponse response = context.Response;
  345. response.ContentType = "text/plain";
  346. response.Headers.ContentDisposition = "attachment;filename=BlockedZones.txt";
  347. await using (StreamWriter sW = new StreamWriter(response.Body))
  348. {
  349. foreach (AuthZoneInfo zoneInfo in zoneInfoList)
  350. await sW.WriteLineAsync(zoneInfo.Name);
  351. }
  352. }
  353. public void DeleteBlockedZone(HttpContext context)
  354. {
  355. UserSession session = context.GetCurrentSession();
  356. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Blocked, session.User, PermissionFlag.Delete))
  357. throw new DnsWebServiceException("Access was denied.");
  358. string domain = context.Request.GetQueryOrForm("domain");
  359. if (DnsClient.IsDomainNameUnicode(domain))
  360. domain = DnsClient.ConvertDomainNameToAscii(domain);
  361. if (_dnsWebService.DnsServer.BlockedZoneManager.DeleteZone(domain))
  362. {
  363. _dnsWebService._log.Write(context.GetRemoteEndPoint(_dnsWebService._webServiceRealIpHeader), "[" + session.User.Username + "] Blocked zone was deleted: " + domain);
  364. _dnsWebService.DnsServer.BlockedZoneManager.SaveZoneFile();
  365. }
  366. }
  367. public void FlushBlockedZone(HttpContext context)
  368. {
  369. UserSession session = context.GetCurrentSession();
  370. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Blocked, session.User, PermissionFlag.Delete))
  371. throw new DnsWebServiceException("Access was denied.");
  372. _dnsWebService.DnsServer.BlockedZoneManager.Flush();
  373. _dnsWebService._log.Write(context.GetRemoteEndPoint(_dnsWebService._webServiceRealIpHeader), "[" + session.User.Username + "] Blocked zone was flushed successfully.");
  374. _dnsWebService.DnsServer.BlockedZoneManager.SaveZoneFile();
  375. }
  376. public void BlockZone(HttpContext context)
  377. {
  378. UserSession session = context.GetCurrentSession();
  379. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Blocked, session.User, PermissionFlag.Modify))
  380. throw new DnsWebServiceException("Access was denied.");
  381. string domain = context.Request.GetQueryOrForm("domain");
  382. if (DnsClient.IsDomainNameUnicode(domain))
  383. domain = DnsClient.ConvertDomainNameToAscii(domain);
  384. if (IPAddress.TryParse(domain, out IPAddress ipAddress))
  385. domain = ipAddress.GetReverseDomain();
  386. if (_dnsWebService.DnsServer.BlockedZoneManager.BlockZone(domain))
  387. {
  388. _dnsWebService._log.Write(context.GetRemoteEndPoint(_dnsWebService._webServiceRealIpHeader), "[" + session.User.Username + "] Domain was added to blocked zone: " + domain);
  389. _dnsWebService.DnsServer.BlockedZoneManager.SaveZoneFile();
  390. }
  391. }
  392. #endregion
  393. #endregion
  394. }
  395. }