WebServiceAuthApi.cs 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012
  1. /*
  2. Technitium DNS Server
  3. Copyright (C) 2023 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 Microsoft.AspNetCore.Http;
  17. using System;
  18. using System.Collections.Generic;
  19. using System.Net;
  20. using System.Text.Json;
  21. using System.Threading.Tasks;
  22. namespace DnsServerCore
  23. {
  24. sealed class WebServiceAuthApi
  25. {
  26. #region variables
  27. readonly DnsWebService _dnsWebService;
  28. #endregion
  29. #region constructor
  30. public WebServiceAuthApi(DnsWebService dnsWebService)
  31. {
  32. _dnsWebService = dnsWebService;
  33. }
  34. #endregion
  35. #region private
  36. private void WriteCurrentSessionDetails(Utf8JsonWriter jsonWriter, UserSession currentSession, bool includeInfo)
  37. {
  38. if (currentSession.Type == UserSessionType.ApiToken)
  39. {
  40. jsonWriter.WriteString("username", currentSession.User.Username);
  41. jsonWriter.WriteString("tokenName", currentSession.TokenName);
  42. jsonWriter.WriteString("token", currentSession.Token);
  43. }
  44. else
  45. {
  46. jsonWriter.WriteString("displayName", currentSession.User.DisplayName);
  47. jsonWriter.WriteString("username", currentSession.User.Username);
  48. jsonWriter.WriteString("token", currentSession.Token);
  49. }
  50. if (includeInfo)
  51. {
  52. jsonWriter.WritePropertyName("info");
  53. jsonWriter.WriteStartObject();
  54. jsonWriter.WriteString("version", _dnsWebService.GetServerVersion());
  55. jsonWriter.WriteString("uptimestamp", _dnsWebService._uptimestamp);
  56. jsonWriter.WriteString("dnsServerDomain", _dnsWebService.DnsServer.ServerDomain);
  57. jsonWriter.WriteNumber("defaultRecordTtl", _dnsWebService._zonesApi.DefaultRecordTtl);
  58. jsonWriter.WritePropertyName("permissions");
  59. jsonWriter.WriteStartObject();
  60. for (int i = 1; i <= 11; i++)
  61. {
  62. PermissionSection section = (PermissionSection)i;
  63. jsonWriter.WritePropertyName(section.ToString());
  64. jsonWriter.WriteStartObject();
  65. jsonWriter.WriteBoolean("canView", _dnsWebService._authManager.IsPermitted(section, currentSession.User, PermissionFlag.View));
  66. jsonWriter.WriteBoolean("canModify", _dnsWebService._authManager.IsPermitted(section, currentSession.User, PermissionFlag.Modify));
  67. jsonWriter.WriteBoolean("canDelete", _dnsWebService._authManager.IsPermitted(section, currentSession.User, PermissionFlag.Delete));
  68. jsonWriter.WriteEndObject();
  69. }
  70. jsonWriter.WriteEndObject();
  71. jsonWriter.WriteEndObject();
  72. }
  73. }
  74. private void WriteUserDetails(Utf8JsonWriter jsonWriter, User user, UserSession currentSession, bool includeMoreDetails, bool includeGroups)
  75. {
  76. jsonWriter.WriteString("displayName", user.DisplayName);
  77. jsonWriter.WriteString("username", user.Username);
  78. jsonWriter.WriteBoolean("disabled", user.Disabled);
  79. jsonWriter.WriteString("previousSessionLoggedOn", user.PreviousSessionLoggedOn);
  80. jsonWriter.WriteString("previousSessionRemoteAddress", user.PreviousSessionRemoteAddress.ToString());
  81. jsonWriter.WriteString("recentSessionLoggedOn", user.RecentSessionLoggedOn);
  82. jsonWriter.WriteString("recentSessionRemoteAddress", user.RecentSessionRemoteAddress.ToString());
  83. if (includeMoreDetails)
  84. {
  85. jsonWriter.WriteNumber("sessionTimeoutSeconds", user.SessionTimeoutSeconds);
  86. jsonWriter.WritePropertyName("memberOfGroups");
  87. jsonWriter.WriteStartArray();
  88. List<Group> memberOfGroups = new List<Group>(user.MemberOfGroups);
  89. memberOfGroups.Sort();
  90. foreach (Group group in memberOfGroups)
  91. {
  92. if (group.Name.Equals("Everyone", StringComparison.OrdinalIgnoreCase))
  93. continue;
  94. jsonWriter.WriteStringValue(group.Name);
  95. }
  96. jsonWriter.WriteEndArray();
  97. jsonWriter.WritePropertyName("sessions");
  98. jsonWriter.WriteStartArray();
  99. List<UserSession> sessions = _dnsWebService._authManager.GetSessions(user);
  100. sessions.Sort();
  101. foreach (UserSession session in sessions)
  102. WriteUserSessionDetails(jsonWriter, session, currentSession);
  103. jsonWriter.WriteEndArray();
  104. }
  105. if (includeGroups)
  106. {
  107. List<Group> groups = new List<Group>(_dnsWebService._authManager.Groups);
  108. groups.Sort();
  109. jsonWriter.WritePropertyName("groups");
  110. jsonWriter.WriteStartArray();
  111. foreach (Group group in groups)
  112. {
  113. if (group.Name.Equals("Everyone", StringComparison.OrdinalIgnoreCase))
  114. continue;
  115. jsonWriter.WriteStringValue(group.Name);
  116. }
  117. jsonWriter.WriteEndArray();
  118. }
  119. }
  120. private static void WriteUserSessionDetails(Utf8JsonWriter jsonWriter, UserSession session, UserSession currentSession)
  121. {
  122. jsonWriter.WriteStartObject();
  123. jsonWriter.WriteString("username", session.User.Username);
  124. jsonWriter.WriteBoolean("isCurrentSession", session.Equals(currentSession));
  125. jsonWriter.WriteString("partialToken", session.Token.Substring(0, 16));
  126. jsonWriter.WriteString("type", session.Type.ToString());
  127. jsonWriter.WriteString("tokenName", session.TokenName);
  128. jsonWriter.WriteString("lastSeen", session.LastSeen);
  129. jsonWriter.WriteString("lastSeenRemoteAddress", session.LastSeenRemoteAddress.ToString());
  130. jsonWriter.WriteString("lastSeenUserAgent", session.LastSeenUserAgent);
  131. jsonWriter.WriteEndObject();
  132. }
  133. private void WriteGroupDetails(Utf8JsonWriter jsonWriter, Group group, bool includeMembers, bool includeUsers)
  134. {
  135. jsonWriter.WriteString("name", group.Name);
  136. jsonWriter.WriteString("description", group.Description);
  137. if (includeMembers)
  138. {
  139. jsonWriter.WritePropertyName("members");
  140. jsonWriter.WriteStartArray();
  141. List<User> members = _dnsWebService._authManager.GetGroupMembers(group);
  142. members.Sort();
  143. foreach (User user in members)
  144. jsonWriter.WriteStringValue(user.Username);
  145. jsonWriter.WriteEndArray();
  146. }
  147. if (includeUsers)
  148. {
  149. List<User> users = new List<User>(_dnsWebService._authManager.Users);
  150. users.Sort();
  151. jsonWriter.WritePropertyName("users");
  152. jsonWriter.WriteStartArray();
  153. foreach (User user in users)
  154. jsonWriter.WriteStringValue(user.Username);
  155. jsonWriter.WriteEndArray();
  156. }
  157. }
  158. private void WritePermissionDetails(Utf8JsonWriter jsonWriter, Permission permission, string subItem, bool includeUsersAndGroups)
  159. {
  160. jsonWriter.WriteString("section", permission.Section.ToString());
  161. if (subItem is not null)
  162. jsonWriter.WriteString("subItem", subItem.Length == 0 ? "." : subItem);
  163. jsonWriter.WritePropertyName("userPermissions");
  164. jsonWriter.WriteStartArray();
  165. List<KeyValuePair<User, PermissionFlag>> userPermissions = new List<KeyValuePair<User, PermissionFlag>>(permission.UserPermissions);
  166. userPermissions.Sort(delegate (KeyValuePair<User, PermissionFlag> x, KeyValuePair<User, PermissionFlag> y)
  167. {
  168. return x.Key.Username.CompareTo(y.Key.Username);
  169. });
  170. foreach (KeyValuePair<User, PermissionFlag> userPermission in userPermissions)
  171. {
  172. jsonWriter.WriteStartObject();
  173. jsonWriter.WriteString("username", userPermission.Key.Username);
  174. jsonWriter.WriteBoolean("canView", userPermission.Value.HasFlag(PermissionFlag.View));
  175. jsonWriter.WriteBoolean("canModify", userPermission.Value.HasFlag(PermissionFlag.Modify));
  176. jsonWriter.WriteBoolean("canDelete", userPermission.Value.HasFlag(PermissionFlag.Delete));
  177. jsonWriter.WriteEndObject();
  178. }
  179. jsonWriter.WriteEndArray();
  180. jsonWriter.WritePropertyName("groupPermissions");
  181. jsonWriter.WriteStartArray();
  182. List<KeyValuePair<Group, PermissionFlag>> groupPermissions = new List<KeyValuePair<Group, PermissionFlag>>(permission.GroupPermissions);
  183. groupPermissions.Sort(delegate (KeyValuePair<Group, PermissionFlag> x, KeyValuePair<Group, PermissionFlag> y)
  184. {
  185. return x.Key.Name.CompareTo(y.Key.Name);
  186. });
  187. foreach (KeyValuePair<Group, PermissionFlag> groupPermission in groupPermissions)
  188. {
  189. jsonWriter.WriteStartObject();
  190. jsonWriter.WriteString("name", groupPermission.Key.Name);
  191. jsonWriter.WriteBoolean("canView", groupPermission.Value.HasFlag(PermissionFlag.View));
  192. jsonWriter.WriteBoolean("canModify", groupPermission.Value.HasFlag(PermissionFlag.Modify));
  193. jsonWriter.WriteBoolean("canDelete", groupPermission.Value.HasFlag(PermissionFlag.Delete));
  194. jsonWriter.WriteEndObject();
  195. }
  196. jsonWriter.WriteEndArray();
  197. if (includeUsersAndGroups)
  198. {
  199. List<User> users = new List<User>(_dnsWebService._authManager.Users);
  200. users.Sort();
  201. List<Group> groups = new List<Group>(_dnsWebService._authManager.Groups);
  202. groups.Sort();
  203. jsonWriter.WritePropertyName("users");
  204. jsonWriter.WriteStartArray();
  205. foreach (User user in users)
  206. jsonWriter.WriteStringValue(user.Username);
  207. jsonWriter.WriteEndArray();
  208. jsonWriter.WritePropertyName("groups");
  209. jsonWriter.WriteStartArray();
  210. foreach (Group group in groups)
  211. jsonWriter.WriteStringValue(group.Name);
  212. jsonWriter.WriteEndArray();
  213. }
  214. }
  215. #endregion
  216. #region public
  217. public async Task LoginAsync(HttpContext context, UserSessionType sessionType)
  218. {
  219. HttpRequest request = context.Request;
  220. string username = request.GetQueryOrForm("user");
  221. string password = request.GetQueryOrForm("pass");
  222. string tokenName = (sessionType == UserSessionType.ApiToken) ? request.GetQueryOrForm("tokenName") : null;
  223. bool includeInfo = request.GetQueryOrForm("includeInfo", bool.Parse, false);
  224. IPEndPoint remoteEP = context.GetRemoteEndPoint();
  225. UserSession session = await _dnsWebService._authManager.CreateSessionAsync(sessionType, tokenName, username, password, remoteEP.Address, request.Headers.UserAgent);
  226. _dnsWebService._log.Write(remoteEP, "[" + session.User.Username + "] User logged in.");
  227. _dnsWebService._authManager.SaveConfigFile();
  228. Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
  229. WriteCurrentSessionDetails(jsonWriter, session, includeInfo);
  230. }
  231. public void Logout(HttpContext context)
  232. {
  233. string token = context.Request.GetQueryOrForm("token");
  234. UserSession session = _dnsWebService._authManager.DeleteSession(token);
  235. if (session is not null)
  236. {
  237. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] User logged out.");
  238. _dnsWebService._authManager.SaveConfigFile();
  239. }
  240. }
  241. public void GetCurrentSessionDetails(HttpContext context)
  242. {
  243. UserSession session = context.GetCurrentSession();
  244. Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
  245. WriteCurrentSessionDetails(jsonWriter, session, true);
  246. }
  247. public void ChangePassword(HttpContext context)
  248. {
  249. UserSession session = context.GetCurrentSession();
  250. if (session.Type != UserSessionType.Standard)
  251. throw new DnsWebServiceException("Access was denied.");
  252. string password = context.Request.GetQueryOrForm("pass");
  253. session.User.ChangePassword(password);
  254. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] Password was changed successfully.");
  255. _dnsWebService._authManager.SaveConfigFile();
  256. }
  257. public void GetProfile(HttpContext context)
  258. {
  259. UserSession session = context.GetCurrentSession();
  260. Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
  261. WriteUserDetails(jsonWriter, session.User, session, true, false);
  262. }
  263. public void SetProfile(HttpContext context)
  264. {
  265. UserSession session = context.GetCurrentSession();
  266. if (session.Type != UserSessionType.Standard)
  267. throw new DnsWebServiceException("Access was denied.");
  268. HttpRequest request = context.Request;
  269. if (request.TryGetQueryOrForm("displayName", out string displayName))
  270. session.User.DisplayName = displayName;
  271. if (request.TryGetQueryOrForm("sessionTimeoutSeconds", int.Parse, out int sessionTimeoutSeconds))
  272. session.User.SessionTimeoutSeconds = sessionTimeoutSeconds;
  273. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] User profile was updated successfully.");
  274. _dnsWebService._authManager.SaveConfigFile();
  275. Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
  276. WriteUserDetails(jsonWriter, session.User, session, true, false);
  277. }
  278. public void ListSessions(HttpContext context)
  279. {
  280. UserSession session = context.GetCurrentSession();
  281. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Administration, session.User, PermissionFlag.View))
  282. throw new DnsWebServiceException("Access was denied.");
  283. Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
  284. jsonWriter.WritePropertyName("sessions");
  285. jsonWriter.WriteStartArray();
  286. List<UserSession> sessions = new List<UserSession>(_dnsWebService._authManager.Sessions);
  287. sessions.Sort();
  288. foreach (UserSession activeSession in sessions)
  289. {
  290. if (!activeSession.HasExpired())
  291. WriteUserSessionDetails(jsonWriter, activeSession, session);
  292. }
  293. jsonWriter.WriteEndArray();
  294. }
  295. public void CreateApiToken(HttpContext context)
  296. {
  297. UserSession session = context.GetCurrentSession();
  298. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Administration, session.User, PermissionFlag.Modify))
  299. throw new DnsWebServiceException("Access was denied.");
  300. HttpRequest request = context.Request;
  301. string username = request.GetQueryOrForm("user");
  302. string tokenName = request.GetQueryOrForm("tokenName");
  303. IPEndPoint remoteEP = context.GetRemoteEndPoint();
  304. UserSession createdSession = _dnsWebService._authManager.CreateApiToken(tokenName, username, remoteEP.Address, request.Headers.UserAgent);
  305. _dnsWebService._log.Write(remoteEP, "[" + session.User.Username + "] API token [" + tokenName + "] was created successfully for user: " + username);
  306. _dnsWebService._authManager.SaveConfigFile();
  307. Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
  308. jsonWriter.WriteString("username", createdSession.User.Username);
  309. jsonWriter.WriteString("tokenName", createdSession.TokenName);
  310. jsonWriter.WriteString("token", createdSession.Token);
  311. }
  312. public void DeleteSession(HttpContext context, bool isAdminContext)
  313. {
  314. UserSession session = context.GetCurrentSession();
  315. if (isAdminContext)
  316. {
  317. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Administration, session.User, PermissionFlag.Delete))
  318. throw new DnsWebServiceException("Access was denied.");
  319. }
  320. string strPartialToken = context.Request.GetQueryOrForm("partialToken");
  321. if (session.Token.StartsWith(strPartialToken))
  322. throw new InvalidOperationException("Invalid operation: cannot delete current session.");
  323. string token = null;
  324. foreach (UserSession activeSession in _dnsWebService._authManager.Sessions)
  325. {
  326. if (activeSession.Token.StartsWith(strPartialToken))
  327. {
  328. token = activeSession.Token;
  329. break;
  330. }
  331. }
  332. if (token is null)
  333. throw new DnsWebServiceException("No such active session was found for partial token: " + strPartialToken);
  334. if (!isAdminContext)
  335. {
  336. UserSession sessionToDelete = _dnsWebService._authManager.GetSession(token);
  337. if (sessionToDelete.User != session.User)
  338. throw new DnsWebServiceException("Access was denied.");
  339. }
  340. UserSession deletedSession = _dnsWebService._authManager.DeleteSession(token);
  341. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] User session [" + strPartialToken + "] was deleted successfully for user: " + deletedSession.User.Username);
  342. _dnsWebService._authManager.SaveConfigFile();
  343. }
  344. public void ListUsers(HttpContext context)
  345. {
  346. UserSession session = context.GetCurrentSession();
  347. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Administration, session.User, PermissionFlag.View))
  348. throw new DnsWebServiceException("Access was denied.");
  349. List<User> users = new List<User>(_dnsWebService._authManager.Users);
  350. users.Sort();
  351. Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
  352. jsonWriter.WritePropertyName("users");
  353. jsonWriter.WriteStartArray();
  354. foreach (User user in users)
  355. {
  356. jsonWriter.WriteStartObject();
  357. WriteUserDetails(jsonWriter, user, null, false, false);
  358. jsonWriter.WriteEndObject();
  359. }
  360. jsonWriter.WriteEndArray();
  361. }
  362. public void CreateUser(HttpContext context)
  363. {
  364. UserSession session = context.GetCurrentSession();
  365. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Administration, session.User, PermissionFlag.Modify))
  366. throw new DnsWebServiceException("Access was denied.");
  367. HttpRequest request = context.Request;
  368. string displayName = request.QueryOrForm("displayName");
  369. string username = request.GetQueryOrForm("user");
  370. string password = request.GetQueryOrForm("pass");
  371. User user = _dnsWebService._authManager.CreateUser(displayName, username, password);
  372. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] User account was created successfully with username: " + user.Username);
  373. _dnsWebService._authManager.SaveConfigFile();
  374. Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
  375. WriteUserDetails(jsonWriter, user, null, false, false);
  376. }
  377. public void GetUserDetails(HttpContext context)
  378. {
  379. UserSession session = context.GetCurrentSession();
  380. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Administration, session.User, PermissionFlag.View))
  381. throw new DnsWebServiceException("Access was denied.");
  382. HttpRequest request = context.Request;
  383. string username = request.GetQueryOrForm("user");
  384. bool includeGroups = request.GetQueryOrForm("includeGroups", bool.Parse, false);
  385. User user = _dnsWebService._authManager.GetUser(username);
  386. if (user is null)
  387. throw new DnsWebServiceException("No such user exists: " + username);
  388. Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
  389. WriteUserDetails(jsonWriter, user, null, true, includeGroups);
  390. }
  391. public void SetUserDetails(HttpContext context)
  392. {
  393. UserSession session = context.GetCurrentSession();
  394. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Administration, session.User, PermissionFlag.Modify))
  395. throw new DnsWebServiceException("Access was denied.");
  396. HttpRequest request = context.Request;
  397. string username = request.GetQueryOrForm("user");
  398. User user = _dnsWebService._authManager.GetUser(username);
  399. if (user is null)
  400. throw new DnsWebServiceException("No such user exists: " + username);
  401. if (request.TryGetQueryOrForm("displayName", out string displayName))
  402. user.DisplayName = displayName;
  403. if (request.TryGetQueryOrForm("newUser", out string newUsername))
  404. _dnsWebService._authManager.ChangeUsername(user, newUsername);
  405. if (request.TryGetQueryOrForm("disabled", bool.Parse, out bool disabled) && (session.User != user)) //to avoid self lockout
  406. {
  407. user.Disabled = disabled;
  408. if (user.Disabled)
  409. {
  410. foreach (UserSession userSession in _dnsWebService._authManager.Sessions)
  411. {
  412. if (userSession.Type == UserSessionType.ApiToken)
  413. continue;
  414. if (userSession.User == user)
  415. _dnsWebService._authManager.DeleteSession(userSession.Token);
  416. }
  417. }
  418. }
  419. if (request.TryGetQueryOrForm("sessionTimeoutSeconds", int.Parse, out int sessionTimeoutSeconds))
  420. user.SessionTimeoutSeconds = sessionTimeoutSeconds;
  421. string newPassword = request.QueryOrForm("newPass");
  422. if (!string.IsNullOrWhiteSpace(newPassword))
  423. {
  424. int iterations = request.GetQueryOrForm("iterations", int.Parse, User.DEFAULT_ITERATIONS);
  425. user.ChangePassword(newPassword, iterations);
  426. }
  427. string memberOfGroups = request.QueryOrForm("memberOfGroups");
  428. if (memberOfGroups is not null)
  429. {
  430. string[] parts = memberOfGroups.Split(',');
  431. Dictionary<string, Group> groups = new Dictionary<string, Group>(parts.Length);
  432. foreach (string part in parts)
  433. {
  434. if (part.Length == 0)
  435. continue;
  436. Group group = _dnsWebService._authManager.GetGroup(part);
  437. if (group is null)
  438. throw new DnsWebServiceException("No such group exists: " + part);
  439. groups.Add(group.Name.ToLower(), group);
  440. }
  441. //ensure user is member of everyone group
  442. Group everyone = _dnsWebService._authManager.GetGroup(Group.EVERYONE);
  443. groups[everyone.Name.ToLower()] = everyone;
  444. if (session.User == user)
  445. {
  446. //ensure current admin user is member of administrators group to avoid self lockout
  447. Group admins = _dnsWebService._authManager.GetGroup(Group.ADMINISTRATORS);
  448. groups[admins.Name.ToLower()] = admins;
  449. }
  450. user.SyncGroups(groups);
  451. }
  452. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] User account details were updated successfully for user: " + username);
  453. _dnsWebService._authManager.SaveConfigFile();
  454. Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
  455. WriteUserDetails(jsonWriter, user, null, true, false);
  456. }
  457. public void DeleteUser(HttpContext context)
  458. {
  459. UserSession session = context.GetCurrentSession();
  460. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Administration, session.User, PermissionFlag.Delete))
  461. throw new DnsWebServiceException("Access was denied.");
  462. string username = context.Request.GetQueryOrForm("user");
  463. if (session.User.Username.Equals(username, StringComparison.OrdinalIgnoreCase))
  464. throw new InvalidOperationException("Invalid operation: cannot delete current user.");
  465. if (!_dnsWebService._authManager.DeleteUser(username))
  466. throw new DnsWebServiceException("Failed to delete user: " + username);
  467. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] User account was deleted successfully with username: " + username);
  468. _dnsWebService._authManager.SaveConfigFile();
  469. }
  470. public void ListGroups(HttpContext context)
  471. {
  472. UserSession session = context.GetCurrentSession();
  473. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Administration, session.User, PermissionFlag.View))
  474. throw new DnsWebServiceException("Access was denied.");
  475. List<Group> groups = new List<Group>(_dnsWebService._authManager.Groups);
  476. groups.Sort();
  477. Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
  478. jsonWriter.WritePropertyName("groups");
  479. jsonWriter.WriteStartArray();
  480. foreach (Group group in groups)
  481. {
  482. if (group.Name.Equals("Everyone", StringComparison.OrdinalIgnoreCase))
  483. continue;
  484. jsonWriter.WriteStartObject();
  485. WriteGroupDetails(jsonWriter, group, false, false);
  486. jsonWriter.WriteEndObject();
  487. }
  488. jsonWriter.WriteEndArray();
  489. }
  490. public void CreateGroup(HttpContext context)
  491. {
  492. UserSession session = context.GetCurrentSession();
  493. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Administration, session.User, PermissionFlag.Modify))
  494. throw new DnsWebServiceException("Access was denied.");
  495. HttpRequest request = context.Request;
  496. string groupName = request.GetQueryOrForm("group");
  497. string description = request.GetQueryOrForm("description", "");
  498. Group group = _dnsWebService._authManager.CreateGroup(groupName, description);
  499. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] Group was created successfully with name: " + group.Name);
  500. _dnsWebService._authManager.SaveConfigFile();
  501. Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
  502. WriteGroupDetails(jsonWriter, group, false, false);
  503. }
  504. public void GetGroupDetails(HttpContext context)
  505. {
  506. UserSession session = context.GetCurrentSession();
  507. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Administration, session.User, PermissionFlag.View))
  508. throw new DnsWebServiceException("Access was denied.");
  509. HttpRequest request = context.Request;
  510. string groupName = request.GetQueryOrForm("group");
  511. bool includeUsers = request.GetQueryOrForm("includeUsers", bool.Parse, false);
  512. Group group = _dnsWebService._authManager.GetGroup(groupName);
  513. if (group is null)
  514. throw new DnsWebServiceException("No such group exists: " + groupName);
  515. Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
  516. WriteGroupDetails(jsonWriter, group, true, includeUsers);
  517. }
  518. public void SetGroupDetails(HttpContext context)
  519. {
  520. UserSession session = context.GetCurrentSession();
  521. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Administration, session.User, PermissionFlag.Modify))
  522. throw new DnsWebServiceException("Access was denied.");
  523. HttpRequest request = context.Request;
  524. string groupName = request.GetQueryOrForm("group");
  525. Group group = _dnsWebService._authManager.GetGroup(groupName);
  526. if (group is null)
  527. throw new DnsWebServiceException("No such group exists: " + groupName);
  528. if (request.TryGetQueryOrForm("newGroup", out string newGroup))
  529. _dnsWebService._authManager.RenameGroup(group, newGroup);
  530. if (request.TryGetQueryOrForm("description", out string description))
  531. group.Description = description;
  532. string members = request.QueryOrForm("members");
  533. if (members is not null)
  534. {
  535. string[] parts = members.Split(',');
  536. Dictionary<string, User> users = new Dictionary<string, User>();
  537. foreach (string part in parts)
  538. {
  539. if (part.Length == 0)
  540. continue;
  541. User user = _dnsWebService._authManager.GetUser(part);
  542. if (user is null)
  543. throw new DnsWebServiceException("No such user exists: " + part);
  544. users.Add(user.Username, user);
  545. }
  546. if (group.Name.Equals("administrators", StringComparison.OrdinalIgnoreCase))
  547. users[session.User.Username] = session.User; //ensure current admin user is member of administrators group to avoid self lockout
  548. _dnsWebService._authManager.SyncGroupMembers(group, users);
  549. }
  550. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] Group details were updated successfully for group: " + groupName);
  551. _dnsWebService._authManager.SaveConfigFile();
  552. Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
  553. WriteGroupDetails(jsonWriter, group, true, false);
  554. }
  555. public void DeleteGroup(HttpContext context)
  556. {
  557. UserSession session = context.GetCurrentSession();
  558. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Administration, session.User, PermissionFlag.Delete))
  559. throw new DnsWebServiceException("Access was denied.");
  560. string groupName = context.Request.GetQueryOrForm("group");
  561. if (!_dnsWebService._authManager.DeleteGroup(groupName))
  562. throw new DnsWebServiceException("Failed to delete group: " + groupName);
  563. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] Group was deleted successfully with name: " + groupName);
  564. _dnsWebService._authManager.SaveConfigFile();
  565. }
  566. public void ListPermissions(HttpContext context)
  567. {
  568. UserSession session = context.GetCurrentSession();
  569. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Administration, session.User, PermissionFlag.View))
  570. throw new DnsWebServiceException("Access was denied.");
  571. List<Permission> permissions = new List<Permission>(_dnsWebService._authManager.Permissions);
  572. permissions.Sort();
  573. Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
  574. jsonWriter.WritePropertyName("permissions");
  575. jsonWriter.WriteStartArray();
  576. foreach (Permission permission in permissions)
  577. {
  578. jsonWriter.WriteStartObject();
  579. WritePermissionDetails(jsonWriter, permission, null, false);
  580. jsonWriter.WriteEndObject();
  581. }
  582. jsonWriter.WriteEndArray();
  583. }
  584. public void GetPermissionDetails(HttpContext context, PermissionSection section)
  585. {
  586. UserSession session = context.GetCurrentSession();
  587. HttpRequest request = context.Request;
  588. string strSubItem = null;
  589. switch (section)
  590. {
  591. case PermissionSection.Unknown:
  592. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Administration, session.User, PermissionFlag.View))
  593. throw new DnsWebServiceException("Access was denied.");
  594. section = request.GetQueryOrFormEnum<PermissionSection>("section");
  595. break;
  596. case PermissionSection.Zones:
  597. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, session.User, PermissionFlag.Modify))
  598. throw new DnsWebServiceException("Access was denied.");
  599. strSubItem = request.GetQueryOrForm("zone").TrimEnd('.');
  600. break;
  601. default:
  602. throw new InvalidOperationException();
  603. }
  604. bool includeUsersAndGroups = request.GetQueryOrForm("includeUsersAndGroups", bool.Parse, false);
  605. if (strSubItem is not null)
  606. {
  607. if (!_dnsWebService._authManager.IsPermitted(section, strSubItem, session.User, PermissionFlag.View))
  608. throw new DnsWebServiceException("Access was denied.");
  609. }
  610. Permission permission;
  611. if (strSubItem is null)
  612. permission = _dnsWebService._authManager.GetPermission(section);
  613. else
  614. permission = _dnsWebService._authManager.GetPermission(section, strSubItem);
  615. if (permission is null)
  616. throw new DnsWebServiceException("No permissions exists for section: " + section.ToString() + (strSubItem is null ? "" : "/" + strSubItem));
  617. Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
  618. WritePermissionDetails(jsonWriter, permission, strSubItem, includeUsersAndGroups);
  619. }
  620. public void SetPermissionsDetails(HttpContext context, PermissionSection section)
  621. {
  622. UserSession session = context.GetCurrentSession();
  623. HttpRequest request = context.Request;
  624. string strSubItem = null;
  625. switch (section)
  626. {
  627. case PermissionSection.Unknown:
  628. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Administration, session.User, PermissionFlag.Delete))
  629. throw new DnsWebServiceException("Access was denied.");
  630. section = request.GetQueryOrFormEnum<PermissionSection>("section");
  631. break;
  632. case PermissionSection.Zones:
  633. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, session.User, PermissionFlag.Modify))
  634. throw new DnsWebServiceException("Access was denied.");
  635. strSubItem = request.GetQueryOrForm("zone").TrimEnd('.');
  636. break;
  637. default:
  638. throw new InvalidOperationException();
  639. }
  640. if (strSubItem is not null)
  641. {
  642. if (!_dnsWebService._authManager.IsPermitted(section, strSubItem, session.User, PermissionFlag.Delete))
  643. throw new DnsWebServiceException("Access was denied.");
  644. }
  645. Permission permission;
  646. if (strSubItem is null)
  647. permission = _dnsWebService._authManager.GetPermission(section);
  648. else
  649. permission = _dnsWebService._authManager.GetPermission(section, strSubItem);
  650. if (permission is null)
  651. throw new DnsWebServiceException("No permissions exists for section: " + section.ToString() + (strSubItem is null ? "" : "/" + strSubItem));
  652. string strUserPermissions = request.QueryOrForm("userPermissions");
  653. if (strUserPermissions is not null)
  654. {
  655. string[] parts = strUserPermissions.Split('|');
  656. Dictionary<User, PermissionFlag> userPermissions = new Dictionary<User, PermissionFlag>();
  657. for (int i = 0; i < parts.Length; i += 4)
  658. {
  659. if (parts[i].Length == 0)
  660. continue;
  661. User user = _dnsWebService._authManager.GetUser(parts[i]);
  662. bool canView = bool.Parse(parts[i + 1]);
  663. bool canModify = bool.Parse(parts[i + 2]);
  664. bool canDelete = bool.Parse(parts[i + 3]);
  665. if (user is not null)
  666. {
  667. PermissionFlag permissionFlag = PermissionFlag.None;
  668. if (canView)
  669. permissionFlag |= PermissionFlag.View;
  670. if (canModify)
  671. permissionFlag |= PermissionFlag.Modify;
  672. if (canDelete)
  673. permissionFlag |= PermissionFlag.Delete;
  674. userPermissions[user] = permissionFlag;
  675. }
  676. }
  677. permission.SyncPermissions(userPermissions);
  678. }
  679. string strGroupPermissions = request.QueryOrForm("groupPermissions");
  680. if (strGroupPermissions is not null)
  681. {
  682. string[] parts = strGroupPermissions.Split('|');
  683. Dictionary<Group, PermissionFlag> groupPermissions = new Dictionary<Group, PermissionFlag>();
  684. for (int i = 0; i < parts.Length; i += 4)
  685. {
  686. if (parts[i].Length == 0)
  687. continue;
  688. Group group = _dnsWebService._authManager.GetGroup(parts[i]);
  689. bool canView = bool.Parse(parts[i + 1]);
  690. bool canModify = bool.Parse(parts[i + 2]);
  691. bool canDelete = bool.Parse(parts[i + 3]);
  692. if (group is not null)
  693. {
  694. PermissionFlag permissionFlag = PermissionFlag.None;
  695. if (canView)
  696. permissionFlag |= PermissionFlag.View;
  697. if (canModify)
  698. permissionFlag |= PermissionFlag.Modify;
  699. if (canDelete)
  700. permissionFlag |= PermissionFlag.Delete;
  701. groupPermissions[group] = permissionFlag;
  702. }
  703. }
  704. //ensure administrators group always has all permissions
  705. Group admins = _dnsWebService._authManager.GetGroup(Group.ADMINISTRATORS);
  706. groupPermissions[admins] = PermissionFlag.ViewModifyDelete;
  707. switch (section)
  708. {
  709. case PermissionSection.Zones:
  710. //ensure DNS administrators group always has all permissions
  711. Group dnsAdmins = _dnsWebService._authManager.GetGroup(Group.DNS_ADMINISTRATORS);
  712. groupPermissions[dnsAdmins] = PermissionFlag.ViewModifyDelete;
  713. break;
  714. case PermissionSection.DhcpServer:
  715. //ensure DHCP administrators group always has all permissions
  716. Group dhcpAdmins = _dnsWebService._authManager.GetGroup(Group.DHCP_ADMINISTRATORS);
  717. groupPermissions[dhcpAdmins] = PermissionFlag.ViewModifyDelete;
  718. break;
  719. }
  720. permission.SyncPermissions(groupPermissions);
  721. }
  722. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] Permissions were updated successfully for section: " + section.ToString() + (string.IsNullOrEmpty(strSubItem) ? "" : "/" + strSubItem));
  723. _dnsWebService._authManager.SaveConfigFile();
  724. Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
  725. WritePermissionDetails(jsonWriter, permission, strSubItem, false);
  726. }
  727. #endregion
  728. }
  729. }