Files
BeWoPlaner/Service/Security/SecurityUtils.cs
2026-05-04 00:11:50 +02:00

375 lines
14 KiB
C#

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<byte>();
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<string,object> sliceToken(string token, string link)
{
string decodedToken;
var result = new Dictionary<string, object>();
var ParamsDic = new Dictionary<string, string>();
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]", "8002913382");
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 fullLicenses = 0;
int midLicenses = 0;
int isHybrid = 0;
decimal percentFreeEmployees = 0;
if (resultArray.Length > 0)
{
Int32.TryParse(resultArray[0], out fullLicenses);
if (resultArray.Length > 1)
{
Decimal.TryParse(resultArray[1], out percentFreeEmployees);
}
if (resultArray.Length > 2)
{
Int32.TryParse(resultArray[2], out midLicenses);
}
if (resultArray.Length > 3)
{
Int32.TryParse(resultArray[3], out isHybrid);
}
}
info.IsHybrid = isHybrid == 1;
info.MaxLicenseCount = info.IsHybrid ? fullLicenses + midLicenses : fullLicenses; // Anzahl max User immer Anzahl voll + Hybrid Lizenzen
info.MaxMidLicenseCount = midLicenses;
info.PercentFreeEmployee = midLicenses > 0 ? 0 : percentFreeEmployees; // Nur für Normale DBs 30 % zusätzlich
info.LicenseInUseCount = DAOFactory.GenericDAO.GetAllActive<ApplicationUser>().Count;
info.EmployeeCount = DAOFactory.GenericDAO.GetAllActive<Employee>().Count;
info.MaxEmployeeCount = (int)Math.Ceiling((fullLicenses + midLicenses) * ((100 + info.PercentFreeEmployee) / 100)); // Immer voll + Mid/Hybrid
}
}
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<string, object> SliceOneTimeLinkToken(string token)
{
string decodedToken;
var result = new Dictionary<string, object>();
var paramsDic = new Dictionary<string, string>();
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;
}
}
}