using System; using System.Collections.Generic; using System.Configuration; using System.IO; using System.Linq; using System.Net; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using System.Web; using BeWo.Data; using BeWo.Data.Access; using BeWo.Data.Entities; using BeWo.Service.Core; using BS.Shared.DataContracts; namespace BeWo.Service.Security { public class SecurityUtils { private static readonly byte[] _Rc2IV = { 35, 138, 177, 253, 227, 63, 2, 27 }; private static readonly byte[] _Rc2Key = { 174, 130, 219, 185, 185, 221, 96, 50, 37, 212, 81, 121, 71, 206, 130, 153 }; private static readonly Regex _AuthenticationRegex = new Regex(@"[\&|\?]?token\=[A-Za-z0-9]+|[\&|\?]?tenant\=[A-Za-z0-9]+|[\&|\?]?username\=[A-Za-z0-9.]+"); public static string EncryptString(string strToEncrypt) { var lRc2CSP = new RC2CryptoServiceProvider(); var lEncryptor = lRc2CSP.CreateEncryptor(_Rc2Key, _Rc2IV); using (var msEncrypt = new MemoryStream()) { using (var csEncrypt = new CryptoStream(msEncrypt, lEncryptor, CryptoStreamMode.Write)) { byte[] toEncrypt = Encoding.UTF8.GetBytes(strToEncrypt); csEncrypt.Write(toEncrypt, 0, toEncrypt.Length); csEncrypt.FlushFinalBlock(); byte[] encrypted = msEncrypt.ToArray(); return Convert.ToBase64String(encrypted); } } } public static string DecryptString(string strToDecrypt) { var lRc2CSP = new RC2CryptoServiceProvider(); var lDecryptor = lRc2CSP.CreateDecryptor(_Rc2Key, _Rc2IV); strToDecrypt = strToDecrypt.Replace(' ', '+'); strToDecrypt = strToDecrypt.Trim(','); using (var msDecrypt = new MemoryStream(Convert.FromBase64String(strToDecrypt))) { using (var csDecrypt = new CryptoStream(msDecrypt, lDecryptor, CryptoStreamMode.Read)) { var bytes = new List(); int b; do { b = csDecrypt.ReadByte(); if (b != -1) bytes.Add(Convert.ToByte(b)); } while (b != -1); return Encoding.UTF8.GetString(bytes.ToArray()); } } } internal static string CreateToken(bool ispermalink, string link) { var guid = Guid.NewGuid(); string loginName, rc2EncryptedHash; var tenant = MultitenancyOperationContextExt.Current is null ? SessionFacade.Tenant : MultitenancyOperationContextExt.Current.Tenant; if(LoggedInUserOperationContextExt.Current is null) { loginName = SessionFacade.LoggedInUser.LoginName; rc2EncryptedHash = SessionFacade.LoggedInUser.RC2EncryptedHash; } else { loginName = LoggedInUserOperationContextExt.Current.User.LoginName; rc2EncryptedHash = LoggedInUserOperationContextExt.Current.User.RC2EncryptedHash; } var tokendata = $"expdate={DateTime.Now.AddMinutes(10)};guid={guid};tenant={tenant};user={loginName};password={rc2EncryptedHash};permalink={ispermalink};link={Utils.GetSHA256(link)}"; return HttpUtility.UrlEncode(EncryptString(tokendata)); } public static bool CheckToken(string token, string link) { if (string.IsNullOrEmpty(token)) return false; string decodedToken = DecryptString(token); string[] Params = decodedToken.Split(';'); var linkSha256 = Params[6]; if (!String.IsNullOrWhiteSpace(link) && link.IndexOf("token") > 1) { var firstpart = link.Substring(0, link.IndexOf("token") - 1); var sha = String.Format("link={0}", Utils.GetSHA256(firstpart)); if (linkSha256 != sha) { return false; } } if (Boolean.Parse(Params[5].Split('=')[1])) return true; string date = Params[0].Split('=')[1]; string[] expdatestrarr = date.Split(new[] { '.', ':', ' ' }); var expdate = new DateTime(Convert.ToInt32(expdatestrarr[2]), Convert.ToInt32(expdatestrarr[1]), Convert.ToInt32(expdatestrarr[0]), Convert.ToInt32(expdatestrarr[3]), Convert.ToInt32(expdatestrarr[4]), Convert.ToInt32(expdatestrarr[5])); return expdate >= DateTime.Now; } public static Dictionary sliceToken(string token, string link) { string decodedToken; var result = new Dictionary(); var ParamsDic = new Dictionary(); try { decodedToken = DecryptString(HttpUtility.UrlDecode(token)); } catch (Exception) { decodedToken = DecryptString(token); } string[] Params = decodedToken.Split(';'); foreach (var splittedItem in Params.Select(item => new Regex(@"[\=]{1}").Split(item, 2)).Where(splittedItem => !ParamsDic.ContainsKey(splittedItem[0]))) { ParamsDic.Add(splittedItem[0], splittedItem[1]); } string[] expdatestrarr = ParamsDic["expdate"].Split(new[] { '.', ':', ' ' }); var expdate = new DateTime(Convert.ToInt32(expdatestrarr[2]), Convert.ToInt32(expdatestrarr[1]), Convert.ToInt32(expdatestrarr[0]), Convert.ToInt32(expdatestrarr[3]), Convert.ToInt32(expdatestrarr[4]), Convert.ToInt32(expdatestrarr[5])); result.Add("expdate", expdate); result.Add("guid", Guid.Parse(ParamsDic["guid"])); result.Add("tenant", ParamsDic["tenant"]); result.Add("user", ParamsDic["user"]); result.Add("password", ParamsDic["password"]); result.Add("ispermalink", ParamsDic["permalink"]); return result; } public static LicenseInfoDC GetLicenseInfo() { var info = new LicenseInfoDC(); #if DEBUG info.MaxLicenseCount = 1000; info.PercentFreeEmployee = 100; info.LicenseInUseCount = 1; info.EmployeeCount = 1; info.MaxEmployeeCount = 1000; return info; #endif try { string url = ConfigurationManager.AppSettings.Get("LicenseInfoUrl"); url = url.Replace("[TENANT]", MultitenancyOperationContextExt.Current.Tenant); url += "&t=0"; #if DEBUG url = ConfigurationManager.AppSettings.Get("LicenseInfoUrl"); url = url.Replace("[TENANT]", "3522103738"); url += "&t=0"; #endif //url = url.Replace("[TENANT]", "1441747891"); using (WebClient client = new WebClient()) { //MessageBox.Show(hostAddress); byte[] response = client.DownloadData(url); String result = System.Text.Encoding.ASCII.GetString(response); //if (MultitenancyOperationContextExt.Current.Tenant == "demo") //{ // result = "7;30"; //} String[] resultArray = result.Split(';'); int maxLicenses = 0; int midLicenses = 0; decimal percentFreeEmployees = 0; if (resultArray.Length > 0) { Int32.TryParse(resultArray[0], out maxLicenses); if (resultArray.Length > 1) { Decimal.TryParse(resultArray[1], out percentFreeEmployees); } if (resultArray.Length > 2) { Int32.TryParse(resultArray[2], out midLicenses); } } if (midLicenses > 0) { percentFreeEmployees = 0; maxLicenses += midLicenses; } info.MaxLicenseCount = maxLicenses; info.PercentFreeEmployee = percentFreeEmployees; info.LicenseInUseCount = DAOFactory.GenericDAO.GetAllActive().Count; info.EmployeeCount = DAOFactory.GenericDAO.GetAllActive().Count; info.MaxEmployeeCount = (int)Math.Ceiling(maxLicenses * ((100 + percentFreeEmployees) / 100)); } } catch (Exception) { // } return info; } public static string CreateRandomString(int size, bool capitals = false, bool small = false, bool numbers = true) { var data = new byte[1]; var crypto = new RNGCryptoServiceProvider(); var result = new StringBuilder(size); const string numbersString = "0123456789"; const string capitalsString = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; const string smallString = "abcdefghijklmnopqrstuvwxyz"; var str = string.Empty; if (numbers) str += numbersString; if (capitals) str += capitalsString; if (small) str += smallString; if (str.Length == 0) str = numbersString; var chars = str.ToCharArray(); crypto.GetBytes(data); data = new byte[size]; crypto.GetBytes(data); foreach (byte b in data) result.Append(chars[b % (chars.Length)]); return result.ToString(); } public static string RemoveAuthenticationInfoFromUri(string navigateUri) { var splittedUri = _AuthenticationRegex.Split(navigateUri.Split('?')[1]); var cleanedSplittedUri = splittedUri.Where(t => !string.IsNullOrWhiteSpace(t)).ToArray(); var uriValues = cleanedSplittedUri.Aggregate(string.Empty, (current, item) => current + item); return navigateUri.Split('?')[0] + "?" + uriValues; } public static ApplicationUser GetLoggedInUser() { if (LoggedInUserOperationContextExt.Current != null && LoggedInUserOperationContextExt.Current.User != null) { return LoggedInUserOperationContextExt.Current.User; } return SessionFacade.LoggedInUser; } public static string CreateExternalSignatureToken(long serviceRecordOid) { string loginName, rc2EncryptedHash; var tenant = MultitenancyOperationContextExt.Current is null ? SessionFacade.Tenant : MultitenancyOperationContextExt.Current.Tenant; if(LoggedInUserOperationContextExt.Current is null) { loginName = SessionFacade.LoggedInUser.LoginName; rc2EncryptedHash = SessionFacade.LoggedInUser.RC2EncryptedHash; } else { loginName = LoggedInUserOperationContextExt.Current.User.LoginName; rc2EncryptedHash = LoggedInUserOperationContextExt.Current.User.RC2EncryptedHash; } var tokenData = $"e={DateTime.Now.AddDays(2)};t={tenant};u={loginName};p={rc2EncryptedHash};s={serviceRecordOid}"; var encryptedToken = EncryptString(tokenData); var byteArrayToken = Convert.FromBase64String(encryptedToken); var urlEncodedToken = HttpServerUtility.UrlTokenEncode(byteArrayToken); return urlEncodedToken; } public static Dictionary SliceOneTimeLinkToken(string token) { string decodedToken; var result = new Dictionary(); var paramsDic = new Dictionary(); try { var urlDecodedToken = HttpServerUtility.UrlTokenDecode(token); var base64Token = Convert.ToBase64String(urlDecodedToken); decodedToken = DecryptString(base64Token); } catch(Exception) { decodedToken = DecryptString(token); } var parameters = decodedToken.Split(';'); foreach(var splitItem in parameters.Select(item => new Regex(@"[\=]{1}").Split(item, 2)).Where(splitItem => !paramsDic.ContainsKey(splitItem[0]))) { paramsDic.Add(splitItem[0], splitItem[1]); } var expirationDateStringArray = paramsDic["e"].Split('.', ':', ' '); var expirationDate = new DateTime(Convert.ToInt32(expirationDateStringArray[2]), Convert.ToInt32(expirationDateStringArray[1]), Convert.ToInt32(expirationDateStringArray[0]), Convert.ToInt32(expirationDateStringArray[3]), Convert.ToInt32(expirationDateStringArray[4]), Convert.ToInt32(expirationDateStringArray[5])); result.Add("expirationDate", expirationDate); result.Add("tenant", paramsDic["t"]); result.Add("user", paramsDic["u"]); result.Add("password", paramsDic["p"]); result.Add("serviceRecordOid", paramsDic["s"]); return result; } } }