// Spludlow Software // Copyright © Samuel P. Ludlow 2020 All Rights Reserved // Distributed under the terms of the GNU General Public License version 3 // Distributed WITHOUT ANY WARRANTY; without implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE // https://www.spludlow.co.uk/LICENCE.TXT // The Spludlow logo is a registered trademark of Samuel P. Ludlow and may not be used without permission // v1.14 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Data; namespace Spludlow { public class Security { private static bool IgnoreSecurityKey; private static string CredentialKey; private static string CachedSecurityKey = ""; private static bool BeenWarned = false; public static string HttpHeaderNameSecurityKey = "SecurityKey"; static Security() { IgnoreSecurityKey = Spludlow.Config.GetBoolean("Spludlow.IgnoreSecurityKey"); CredentialKey = "SecurityKey"; try { CachedSecurityKey = Spludlow.Credentials.GetPassword(CredentialKey); // Key may not be in Crentials table } catch { } } public static void Refresh() { try { lock (CachedSecurityKey) { Spludlow.Credentials.Refresh(); CachedSecurityKey = Spludlow.Credentials.GetPassword(CredentialKey); // Key may not be in Crentials table } } catch { } } public static string[][] HttpHeader { get { return new string[][] { new string[] { HttpHeaderNameSecurityKey, CachedSecurityKey } }; } } public static string SecurityKey { get { return CachedSecurityKey; } } public static bool IsValidSecurityKey(string securityKey) { if (securityKey == CachedSecurityKey) return true; if (IgnoreSecurityKey == true) { if (BeenWarned == false) // Failed logs will create a log { Spludlow.Log.Warning("Security; Invalid SecurityKey IgnoreSecurityKey enabled."); // may log from adminWebService BeenWarned = true; } return true; } return false; } private static string[] FurthestHostsFirst(string startHost) { string startNetwork = Spludlow.Config.NetworkId(startHost); List networks = new List(); foreach (string network in Spludlow.Config.Networks()) { if (network != startNetwork) networks.Add(network); } networks.Add(startNetwork); List hosts = new List(); foreach (string network in networks) { string router = Spludlow.Config.Router(network); foreach (string host in Spludlow.Config.Hosts(network)) { if (host != router) hosts.Add(host); } hosts.Add(router); } return hosts.ToArray(); } /// /// Change Security Key on All Hosts /// Run from Master Host (seems to work on queue or web service from Intranet) /// "SecurityKey" in Credentials is set for "SpludlowAdmin" then "SpludlowUser" on each host then all apps are restarted /// Any other users will need to run "SetCurrentUserSecurityKey()" seperatly /// public static void SetSecurityKey(string newSecurityKey) { string startHost = Environment.MachineName; string[] hosts = FurthestHostsFirst(startHost); foreach (string host in hosts) { Spludlow.Call.Now(host, "Spludlow", "Spludlow.Security", "SetSecurityKeyHostWorker", new object[] { newSecurityKey }); } } public static void SetSecurityKeyHostWorker(string newSecurityKey) { Spludlow.Admin.SetSecurityKey(newSecurityKey); // SpludlowAdmin Spludlow.Security.SetCurrentUserSecurityKey(newSecurityKey); // SpludlowUser Spludlow.Status.ReStartAll(); } /// /// Set security key for current user only /// If a logged in user is running applications that access the Framework /// /// public static void SetCurrentUserSecurityKey(string password) // Called by Admin WS - Spludlow.Admin.SetSecurityKey(newSecurityKey); { Spludlow.Credentials.Set(CredentialKey, null, password, null); } public static bool IntanetPasswordInUse() { string configKey = Spludlow.Config.Get("Spludlow.IntranetPassword", true); return (configKey != null); } public static bool IntanetPasswordValidate(string submitPassword) { string configKey = Spludlow.Config.Get("Spludlow.IntranetPassword", true); if (configKey == null) return true; bool result; if (configKey[0] == '@') { string credentialsKey = configKey.Substring(1); string password = Spludlow.Credentials.GetPassword(credentialsKey); if (password == null) throw new ApplicationException("Security IntanetPasswordValidate credentials Key not found: " + credentialsKey); result = (submitPassword == password); } else { result = (submitPassword == configKey); } if (result == false) Spludlow.Log.Warning("Intanet Password Validate FAILED"); return result; } } }