AuthManager.cs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849
  1. /*
  2. Technitium DNS Server
  3. Copyright (C) 2022 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 System;
  16. using System.Collections.Concurrent;
  17. using System.Collections.Generic;
  18. using System.IO;
  19. using System.Net;
  20. using System.Text;
  21. using System.Threading;
  22. using System.Threading.Tasks;
  23. namespace DnsServerCore.Auth
  24. {
  25. sealed class AuthManager : IDisposable
  26. {
  27. #region variables
  28. readonly ConcurrentDictionary<string, Group> _groups = new ConcurrentDictionary<string, Group>(1, 4);
  29. readonly ConcurrentDictionary<string, User> _users = new ConcurrentDictionary<string, User>(1, 4);
  30. readonly ConcurrentDictionary<PermissionSection, Permission> _permissions = new ConcurrentDictionary<PermissionSection, Permission>(1, 11);
  31. readonly ConcurrentDictionary<string, UserSession> _sessions = new ConcurrentDictionary<string, UserSession>(1, 10);
  32. readonly ConcurrentDictionary<IPAddress, int> _failedLoginAttempts = new ConcurrentDictionary<IPAddress, int>(1, 10);
  33. const int MAX_LOGIN_ATTEMPTS = 5;
  34. readonly ConcurrentDictionary<IPAddress, DateTime> _blockedAddresses = new ConcurrentDictionary<IPAddress, DateTime>(1, 10);
  35. const int BLOCK_ADDRESS_INTERVAL = 5 * 60 * 1000;
  36. readonly string _configFolder;
  37. readonly LogManager _log;
  38. readonly object _lockObj = new object();
  39. bool _pendingSave;
  40. readonly Timer _saveTimer;
  41. const int SAVE_TIMER_INITIAL_INTERVAL = 10000;
  42. #endregion
  43. #region constructor
  44. public AuthManager(string configFolder, LogManager log)
  45. {
  46. _configFolder = configFolder;
  47. _log = log;
  48. _saveTimer = new Timer(SaveTimerCallback, null, Timeout.Infinite, Timeout.Infinite);
  49. }
  50. #endregion
  51. #region IDisposable
  52. bool _disposed;
  53. public void Dispose()
  54. {
  55. if (_disposed)
  56. return;
  57. if (_saveTimer is not null)
  58. _saveTimer.Dispose();
  59. lock (_lockObj)
  60. {
  61. SaveConfigFileInternal();
  62. }
  63. _disposed = true;
  64. }
  65. #endregion
  66. #region private
  67. private void SaveTimerCallback(object state)
  68. {
  69. try
  70. {
  71. lock (_lockObj)
  72. {
  73. _pendingSave = false;
  74. SaveConfigFileInternal();
  75. }
  76. }
  77. catch (Exception ex)
  78. {
  79. _log.Write(ex);
  80. }
  81. }
  82. private void CreateDefaultConfig()
  83. {
  84. Group adminGroup = CreateGroup(Group.ADMINISTRATORS, "Super administrators");
  85. Group dnsAdminGroup = CreateGroup(Group.DNS_ADMINISTRATORS, "DNS service administrators");
  86. Group dhcpAdminGroup = CreateGroup(Group.DHCP_ADMINISTRATORS, "DHCP service administrators");
  87. Group everyoneGroup = CreateGroup(Group.EVERYONE, "All users");
  88. SetPermission(PermissionSection.Dashboard, adminGroup, PermissionFlag.ViewModifyDelete);
  89. SetPermission(PermissionSection.Zones, adminGroup, PermissionFlag.ViewModifyDelete);
  90. SetPermission(PermissionSection.Cache, adminGroup, PermissionFlag.ViewModifyDelete);
  91. SetPermission(PermissionSection.Allowed, adminGroup, PermissionFlag.ViewModifyDelete);
  92. SetPermission(PermissionSection.Blocked, adminGroup, PermissionFlag.ViewModifyDelete);
  93. SetPermission(PermissionSection.Apps, adminGroup, PermissionFlag.ViewModifyDelete);
  94. SetPermission(PermissionSection.DnsClient, adminGroup, PermissionFlag.ViewModifyDelete);
  95. SetPermission(PermissionSection.Settings, adminGroup, PermissionFlag.ViewModifyDelete);
  96. SetPermission(PermissionSection.DhcpServer, adminGroup, PermissionFlag.ViewModifyDelete);
  97. SetPermission(PermissionSection.Administration, adminGroup, PermissionFlag.ViewModifyDelete);
  98. SetPermission(PermissionSection.Logs, adminGroup, PermissionFlag.ViewModifyDelete);
  99. SetPermission(PermissionSection.Zones, dnsAdminGroup, PermissionFlag.ViewModifyDelete);
  100. SetPermission(PermissionSection.Cache, dnsAdminGroup, PermissionFlag.ViewModifyDelete);
  101. SetPermission(PermissionSection.Allowed, dnsAdminGroup, PermissionFlag.ViewModifyDelete);
  102. SetPermission(PermissionSection.Blocked, dnsAdminGroup, PermissionFlag.ViewModifyDelete);
  103. SetPermission(PermissionSection.Apps, dnsAdminGroup, PermissionFlag.ViewModifyDelete);
  104. SetPermission(PermissionSection.DnsClient, dnsAdminGroup, PermissionFlag.ViewModifyDelete);
  105. SetPermission(PermissionSection.Settings, dnsAdminGroup, PermissionFlag.ViewModifyDelete);
  106. SetPermission(PermissionSection.DhcpServer, dhcpAdminGroup, PermissionFlag.ViewModifyDelete);
  107. SetPermission(PermissionSection.Dashboard, everyoneGroup, PermissionFlag.View);
  108. SetPermission(PermissionSection.Zones, everyoneGroup, PermissionFlag.View);
  109. SetPermission(PermissionSection.Cache, everyoneGroup, PermissionFlag.View);
  110. SetPermission(PermissionSection.Allowed, everyoneGroup, PermissionFlag.View);
  111. SetPermission(PermissionSection.Blocked, everyoneGroup, PermissionFlag.View);
  112. SetPermission(PermissionSection.Apps, everyoneGroup, PermissionFlag.View);
  113. SetPermission(PermissionSection.DnsClient, everyoneGroup, PermissionFlag.View);
  114. SetPermission(PermissionSection.DhcpServer, everyoneGroup, PermissionFlag.View);
  115. SetPermission(PermissionSection.Logs, everyoneGroup, PermissionFlag.View);
  116. string adminPassword = Environment.GetEnvironmentVariable("DNS_SERVER_ADMIN_PASSWORD");
  117. string adminPasswordFile = Environment.GetEnvironmentVariable("DNS_SERVER_ADMIN_PASSWORD_FILE");
  118. User adminUser;
  119. if (!string.IsNullOrEmpty(adminPassword))
  120. {
  121. adminUser = CreateUser("Administrator", "admin", adminPassword);
  122. }
  123. else if (!string.IsNullOrEmpty(adminPasswordFile))
  124. {
  125. try
  126. {
  127. using (StreamReader sR = new StreamReader(adminPasswordFile, true))
  128. {
  129. string password = sR.ReadLine();
  130. adminUser = CreateUser("Administrator", "admin", password);
  131. }
  132. }
  133. catch (Exception ex)
  134. {
  135. _log.Write(ex);
  136. adminUser = CreateUser("Administrator", "admin", "admin");
  137. }
  138. }
  139. else
  140. {
  141. adminUser = CreateUser("Administrator", "admin", "admin");
  142. }
  143. adminUser.AddToGroup(adminGroup);
  144. }
  145. private void LoadConfigFileInternal(UserSession implantSession)
  146. {
  147. string configFile = Path.Combine(_configFolder, "auth.config");
  148. try
  149. {
  150. bool passwordResetOption = false;
  151. if (!File.Exists(configFile))
  152. {
  153. string passwordResetConfigFile = Path.Combine(_configFolder, "resetadmin.config");
  154. if (File.Exists(passwordResetConfigFile))
  155. {
  156. passwordResetOption = true;
  157. configFile = passwordResetConfigFile;
  158. }
  159. }
  160. using (FileStream fS = new FileStream(configFile, FileMode.Open, FileAccess.Read))
  161. {
  162. ReadConfigFrom(new BinaryReader(fS));
  163. }
  164. if (implantSession is not null)
  165. {
  166. using (MemoryStream mS = new MemoryStream())
  167. {
  168. //implant current user
  169. implantSession.User.WriteTo(new BinaryWriter(mS));
  170. mS.Position = 0;
  171. User newUser = new User(new BinaryReader(mS), this);
  172. newUser.AddToGroup(GetGroup(Group.ADMINISTRATORS));
  173. _users[newUser.Username] = newUser;
  174. //implant current session
  175. mS.SetLength(0);
  176. implantSession.WriteTo(new BinaryWriter(mS));
  177. mS.Position = 0;
  178. UserSession newSession = new UserSession(new BinaryReader(mS), this);
  179. _sessions.TryAdd(newSession.Token, newSession);
  180. //save config
  181. SaveConfigFileInternal();
  182. }
  183. }
  184. _log.Write("DNS Server auth config file was loaded: " + configFile);
  185. if (passwordResetOption)
  186. {
  187. User adminUser = GetUser("admin");
  188. if (adminUser is null)
  189. {
  190. adminUser = CreateUser("Administrator", "admin", "admin");
  191. }
  192. else
  193. {
  194. adminUser.ChangePassword("admin");
  195. adminUser.Disabled = false;
  196. }
  197. adminUser.AddToGroup(GetGroup(Group.ADMINISTRATORS));
  198. _log.Write("DNS Server reset password for user: admin");
  199. SaveConfigFileInternal();
  200. try
  201. {
  202. File.Delete(configFile);
  203. }
  204. catch
  205. { }
  206. }
  207. }
  208. catch (FileNotFoundException)
  209. {
  210. _log.Write("DNS Server auth config file was not found: " + configFile);
  211. _log.Write("DNS Server is restoring default auth config file.");
  212. CreateDefaultConfig();
  213. SaveConfigFileInternal();
  214. }
  215. catch (Exception ex)
  216. {
  217. _log.Write("DNS Server encountered an error while loading auth config file: " + configFile + "\r\n" + ex.ToString());
  218. _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.");
  219. throw;
  220. }
  221. }
  222. private void SaveConfigFileInternal()
  223. {
  224. string configFile = Path.Combine(_configFolder, "auth.config");
  225. using (MemoryStream mS = new MemoryStream())
  226. {
  227. //serialize config
  228. WriteConfigTo(new BinaryWriter(mS));
  229. //write config
  230. mS.Position = 0;
  231. using (FileStream fS = new FileStream(configFile, FileMode.Create, FileAccess.Write))
  232. {
  233. mS.CopyTo(fS);
  234. }
  235. }
  236. _log.Write("DNS Server auth config file was saved: " + configFile);
  237. }
  238. private void ReadConfigFrom(BinaryReader bR)
  239. {
  240. if (Encoding.ASCII.GetString(bR.ReadBytes(2)) != "AS") //format
  241. throw new InvalidDataException("DNS Server auth config file format is invalid.");
  242. int version = bR.ReadByte();
  243. switch (version)
  244. {
  245. case 1:
  246. {
  247. int count = bR.ReadByte();
  248. for (int i = 0; i < count; i++)
  249. {
  250. Group group = new Group(bR);
  251. _groups.TryAdd(group.Name.ToLower(), group);
  252. }
  253. }
  254. {
  255. int count = bR.ReadByte();
  256. for (int i = 0; i < count; i++)
  257. {
  258. User user = new User(bR, this);
  259. _users.TryAdd(user.Username, user);
  260. }
  261. }
  262. {
  263. int count = bR.ReadInt32();
  264. for (int i = 0; i < count; i++)
  265. {
  266. Permission permission = new Permission(bR, this);
  267. _permissions.TryAdd(permission.Section, permission);
  268. }
  269. }
  270. {
  271. int count = bR.ReadInt32();
  272. for (int i = 0; i < count; i++)
  273. {
  274. UserSession session = new UserSession(bR, this);
  275. if (!session.HasExpired())
  276. _sessions.TryAdd(session.Token, session);
  277. }
  278. }
  279. break;
  280. default:
  281. throw new InvalidDataException("DNS Server auth config version not supported.");
  282. }
  283. }
  284. private void WriteConfigTo(BinaryWriter bW)
  285. {
  286. bW.Write(Encoding.ASCII.GetBytes("AS")); //format
  287. bW.Write((byte)1); //version
  288. bW.Write(Convert.ToByte(_groups.Count));
  289. foreach (KeyValuePair<string, Group> group in _groups)
  290. group.Value.WriteTo(bW);
  291. bW.Write(Convert.ToByte(_users.Count));
  292. foreach (KeyValuePair<string, User> user in _users)
  293. user.Value.WriteTo(bW);
  294. bW.Write(_permissions.Count);
  295. foreach (KeyValuePair<PermissionSection, Permission> permission in _permissions)
  296. permission.Value.WriteTo(bW);
  297. List<UserSession> activeSessions = new List<UserSession>(_sessions.Count);
  298. foreach (KeyValuePair<string, UserSession> session in _sessions)
  299. {
  300. if (session.Value.HasExpired())
  301. _sessions.TryRemove(session.Key, out _);
  302. else
  303. activeSessions.Add(session.Value);
  304. }
  305. bW.Write(activeSessions.Count);
  306. foreach (UserSession session in activeSessions)
  307. session.WriteTo(bW);
  308. }
  309. private void FailedLoginAttempt(IPAddress address)
  310. {
  311. _failedLoginAttempts.AddOrUpdate(address, 1, delegate (IPAddress key, int attempts)
  312. {
  313. return attempts + 1;
  314. });
  315. }
  316. private bool LoginAttemptsExceedLimit(IPAddress address, int limit)
  317. {
  318. if (!_failedLoginAttempts.TryGetValue(address, out int attempts))
  319. return false;
  320. return attempts >= limit;
  321. }
  322. private void ResetFailedLoginAttempt(IPAddress address)
  323. {
  324. _failedLoginAttempts.TryRemove(address, out _);
  325. }
  326. private void BlockAddress(IPAddress address, int interval)
  327. {
  328. _blockedAddresses.TryAdd(address, DateTime.UtcNow.AddMilliseconds(interval));
  329. }
  330. private bool IsAddressBlocked(IPAddress address)
  331. {
  332. if (!_blockedAddresses.TryGetValue(address, out DateTime expiry))
  333. return false;
  334. if (expiry > DateTime.UtcNow)
  335. {
  336. return true;
  337. }
  338. else
  339. {
  340. UnblockAddress(address);
  341. ResetFailedLoginAttempt(address);
  342. return false;
  343. }
  344. }
  345. private void UnblockAddress(IPAddress address)
  346. {
  347. _blockedAddresses.TryRemove(address, out _);
  348. }
  349. #endregion
  350. #region public
  351. public User GetUser(string username)
  352. {
  353. if (_users.TryGetValue(username.ToLower(), out User user))
  354. return user;
  355. return null;
  356. }
  357. public User CreateUser(string displayName, string username, string password, int iterations = User.DEFAULT_ITERATIONS)
  358. {
  359. if (_users.Count >= byte.MaxValue)
  360. throw new DnsWebServiceException("Cannot create more than 255 users.");
  361. username = username.ToLower();
  362. User user = new User(displayName, username, password, iterations);
  363. if (_users.TryAdd(username, user))
  364. {
  365. user.AddToGroup(GetGroup(Group.EVERYONE));
  366. return user;
  367. }
  368. throw new DnsWebServiceException("User already exists: " + username);
  369. }
  370. public void ChangeUsername(User user, string newUsername)
  371. {
  372. if (user.Username.Equals(newUsername, StringComparison.OrdinalIgnoreCase))
  373. return;
  374. string oldUsername = user.Username;
  375. user.Username = newUsername;
  376. if (!_users.TryAdd(user.Username, user))
  377. {
  378. user.Username = oldUsername; //revert
  379. throw new DnsWebServiceException("User already exists: " + newUsername);
  380. }
  381. _users.TryRemove(oldUsername, out _);
  382. }
  383. public bool DeleteUser(string username)
  384. {
  385. if (_users.TryRemove(username.ToLower(), out User deletedUser))
  386. {
  387. //delete all sessions
  388. foreach (UserSession session in GetSessions(deletedUser))
  389. DeleteSession(session.Token);
  390. //delete all permissions
  391. foreach (KeyValuePair<PermissionSection, Permission> permission in _permissions)
  392. {
  393. permission.Value.RemovePermission(deletedUser);
  394. permission.Value.RemoveAllSubItemPermissions(deletedUser);
  395. }
  396. return true;
  397. }
  398. return false;
  399. }
  400. public Group GetGroup(string name)
  401. {
  402. if (_groups.TryGetValue(name.ToLower(), out Group group))
  403. return group;
  404. return null;
  405. }
  406. public List<User> GetGroupMembers(Group group)
  407. {
  408. List<User> members = new List<User>();
  409. foreach (KeyValuePair<string, User> user in _users)
  410. {
  411. if (user.Value.IsMemberOfGroup(group))
  412. members.Add(user.Value);
  413. }
  414. return members;
  415. }
  416. public void SyncGroupMembers(Group group, IReadOnlyDictionary<string, User> users)
  417. {
  418. //remove
  419. foreach (KeyValuePair<string, User> user in _users)
  420. {
  421. if (!users.ContainsKey(user.Key))
  422. user.Value.RemoveFromGroup(group);
  423. }
  424. //set
  425. foreach (KeyValuePair<string, User> user in users)
  426. user.Value.AddToGroup(group);
  427. }
  428. public Group CreateGroup(string name, string description)
  429. {
  430. if (_groups.Count >= byte.MaxValue)
  431. throw new DnsWebServiceException("Cannot create more than 255 groups.");
  432. Group group = new Group(name, description);
  433. if (_groups.TryAdd(name.ToLower(), group))
  434. return group;
  435. throw new DnsWebServiceException("Group already exists: " + name);
  436. }
  437. public void RenameGroup(Group group, string newGroupName)
  438. {
  439. if (group.Name.Equals(newGroupName, StringComparison.OrdinalIgnoreCase))
  440. {
  441. group.Name = newGroupName;
  442. return;
  443. }
  444. string oldGroupName = group.Name;
  445. group.Name = newGroupName;
  446. if (!_groups.TryAdd(group.Name.ToLower(), group))
  447. {
  448. group.Name = oldGroupName; //revert
  449. throw new DnsWebServiceException("Group already exists: " + newGroupName);
  450. }
  451. _groups.TryRemove(oldGroupName.ToLower(), out _);
  452. //update users
  453. foreach (KeyValuePair<string, User> user in _users)
  454. user.Value.RenameGroup(oldGroupName);
  455. }
  456. public bool DeleteGroup(string name)
  457. {
  458. name = name.ToLower();
  459. switch (name)
  460. {
  461. case "everyone":
  462. case "administrators":
  463. case "dns administrators":
  464. case "dhcp administrators":
  465. throw new InvalidOperationException("Access was denied.");
  466. default:
  467. if (_groups.TryRemove(name, out Group deletedGroup))
  468. {
  469. //remove all users from deleted group
  470. foreach (KeyValuePair<string, User> user in _users)
  471. user.Value.RemoveFromGroup(deletedGroup);
  472. //delete all permissions
  473. foreach (KeyValuePair<PermissionSection, Permission> permission in _permissions)
  474. {
  475. permission.Value.RemovePermission(deletedGroup);
  476. permission.Value.RemoveAllSubItemPermissions(deletedGroup);
  477. }
  478. return true;
  479. }
  480. return false;
  481. }
  482. }
  483. public UserSession GetSession(string token)
  484. {
  485. if (_sessions.TryGetValue(token, out UserSession session))
  486. return session;
  487. return null;
  488. }
  489. public List<UserSession> GetSessions(User user)
  490. {
  491. List<UserSession> userSessions = new List<UserSession>();
  492. foreach (KeyValuePair<string, UserSession> session in _sessions)
  493. {
  494. if (session.Value.User.Equals(user) && !session.Value.HasExpired())
  495. userSessions.Add(session.Value);
  496. }
  497. return userSessions;
  498. }
  499. public async Task<UserSession> CreateSessionAsync(UserSessionType type, string tokenName, string username, string password, IPAddress remoteAddress, string userAgent)
  500. {
  501. if (IsAddressBlocked(remoteAddress))
  502. throw new DnsWebServiceException("Max limit of " + MAX_LOGIN_ATTEMPTS + " attempts exceeded. Access blocked for " + (BLOCK_ADDRESS_INTERVAL / 1000) + " seconds.");
  503. User user = GetUser(username);
  504. if ((user is null) || !user.PasswordHash.Equals(user.GetPasswordHashFor(password), StringComparison.Ordinal))
  505. {
  506. if (password != "admin")
  507. {
  508. FailedLoginAttempt(remoteAddress);
  509. if (LoginAttemptsExceedLimit(remoteAddress, MAX_LOGIN_ATTEMPTS))
  510. BlockAddress(remoteAddress, BLOCK_ADDRESS_INTERVAL);
  511. await Task.Delay(1000);
  512. }
  513. throw new DnsWebServiceException("Invalid username or password for user: " + username);
  514. }
  515. ResetFailedLoginAttempt(remoteAddress);
  516. if (user.Disabled)
  517. throw new DnsWebServiceException("User account is disabled. Please contact your administrator.");
  518. UserSession session = new UserSession(type, tokenName, user, remoteAddress, userAgent);
  519. if (!_sessions.TryAdd(session.Token, session))
  520. throw new DnsWebServiceException("Error while creating session. Please try again.");
  521. user.LoggedInFrom(remoteAddress);
  522. return session;
  523. }
  524. public UserSession CreateApiToken(string tokenName, string username, IPAddress remoteAddress, string userAgent)
  525. {
  526. if (IsAddressBlocked(remoteAddress))
  527. throw new DnsWebServiceException("Max limit of " + MAX_LOGIN_ATTEMPTS + " attempts exceeded. Access blocked for " + (BLOCK_ADDRESS_INTERVAL / 1000) + " seconds.");
  528. User user = GetUser(username);
  529. if (user is null)
  530. throw new DnsWebServiceException("No such user exists: " + username);
  531. if (user.Disabled)
  532. throw new DnsWebServiceException("Account is suspended.");
  533. UserSession session = new UserSession(UserSessionType.ApiToken, tokenName, user, remoteAddress, userAgent);
  534. if (!_sessions.TryAdd(session.Token, session))
  535. throw new DnsWebServiceException("Error while creating session. Please try again.");
  536. user.LoggedInFrom(remoteAddress);
  537. return session;
  538. }
  539. public UserSession DeleteSession(string token)
  540. {
  541. if (_sessions.TryRemove(token, out UserSession session))
  542. return session;
  543. return null;
  544. }
  545. public Permission GetPermission(PermissionSection section)
  546. {
  547. if (_permissions.TryGetValue(section, out Permission permission))
  548. return permission;
  549. return null;
  550. }
  551. public Permission GetPermission(PermissionSection section, string subItemName)
  552. {
  553. if (_permissions.TryGetValue(section, out Permission permission))
  554. return permission.GetSubItemPermission(subItemName);
  555. return null;
  556. }
  557. public void SetPermission(PermissionSection section, User user, PermissionFlag flags)
  558. {
  559. Permission permission = _permissions.GetOrAdd(section, delegate (PermissionSection key)
  560. {
  561. return new Permission(key);
  562. });
  563. permission.SetPermission(user, flags);
  564. }
  565. public void SetPermission(PermissionSection section, string subItemName, User user, PermissionFlag flags)
  566. {
  567. Permission permission = _permissions.GetOrAdd(section, delegate (PermissionSection key)
  568. {
  569. return new Permission(key);
  570. });
  571. permission.SetSubItemPermission(subItemName, user, flags);
  572. }
  573. public void SetPermission(PermissionSection section, Group group, PermissionFlag flags)
  574. {
  575. Permission permission = _permissions.GetOrAdd(section, delegate (PermissionSection key)
  576. {
  577. return new Permission(key);
  578. });
  579. permission.SetPermission(group, flags);
  580. }
  581. public void SetPermission(PermissionSection section, string subItemName, Group group, PermissionFlag flags)
  582. {
  583. Permission permission = _permissions.GetOrAdd(section, delegate (PermissionSection key)
  584. {
  585. return new Permission(key);
  586. });
  587. permission.SetSubItemPermission(subItemName, group, flags);
  588. }
  589. public bool RemovePermission(PermissionSection section, User user)
  590. {
  591. return _permissions.TryGetValue(section, out Permission permission) && permission.RemovePermission(user);
  592. }
  593. public bool RemovePermission(PermissionSection section, string subItemName, User user)
  594. {
  595. return _permissions.TryGetValue(section, out Permission permission) && permission.RemoveSubItemPermission(subItemName, user);
  596. }
  597. public bool RemovePermission(PermissionSection section, Group group)
  598. {
  599. return _permissions.TryGetValue(section, out Permission permission) && permission.RemovePermission(group);
  600. }
  601. public bool RemovePermission(PermissionSection section, string subItemName, Group group)
  602. {
  603. return _permissions.TryGetValue(section, out Permission permission) && permission.RemoveSubItemPermission(subItemName, group);
  604. }
  605. public bool RemoveAllPermissions(PermissionSection section, string subItemName)
  606. {
  607. return _permissions.TryGetValue(section, out Permission permission) && permission.RemoveAllSubItemPermissions(subItemName);
  608. }
  609. public bool IsPermitted(PermissionSection section, User user, PermissionFlag flag)
  610. {
  611. return _permissions.TryGetValue(section, out Permission permission) && permission.IsPermitted(user, flag);
  612. }
  613. public bool IsPermitted(PermissionSection section, string subItemName, User user, PermissionFlag flag)
  614. {
  615. return _permissions.TryGetValue(section, out Permission permission) && permission.IsSubItemPermitted(subItemName, user, flag);
  616. }
  617. public void LoadOldConfig(string password, bool isPasswordHash)
  618. {
  619. User user = GetUser("admin");
  620. if (user is null)
  621. user = CreateUser("Administrator", "admin", "admin");
  622. user.AddToGroup(GetGroup(Group.ADMINISTRATORS));
  623. if (isPasswordHash)
  624. user.LoadOldSchemeCredentials(password);
  625. else
  626. user.ChangePassword(password);
  627. lock (_lockObj)
  628. {
  629. SaveConfigFileInternal();
  630. }
  631. }
  632. public void LoadConfigFile(UserSession implantSession = null)
  633. {
  634. lock (_lockObj)
  635. {
  636. _groups.Clear();
  637. _users.Clear();
  638. _permissions.Clear();
  639. _sessions.Clear();
  640. LoadConfigFileInternal(implantSession);
  641. }
  642. }
  643. public void SaveConfigFile()
  644. {
  645. lock (_lockObj)
  646. {
  647. if (_pendingSave)
  648. return;
  649. _pendingSave = true;
  650. _saveTimer.Change(SAVE_TIMER_INITIAL_INTERVAL, Timeout.Infinite);
  651. }
  652. }
  653. #endregion
  654. #region properties
  655. public ICollection<Group> Groups
  656. { get { return _groups.Values; } }
  657. public ICollection<User> Users
  658. { get { return _users.Values; } }
  659. public ICollection<Permission> Permissions
  660. { get { return _permissions.Values; } }
  661. public ICollection<UserSession> Sessions
  662. { get { return _sessions.Values; } }
  663. #endregion
  664. }
  665. }