using System; using System.Linq; using System.Net; using System.Security; using System.Security.Cryptography.X509Certificates; using System.ServiceModel; using System.ServiceModel.Channels; using System.ServiceModel.Dispatcher; using System.Xml; using BeWo.Data; using BeWo.Data.Access; using BeWo.Data.Entities; using BeWo.Service.Attributes; using BeWo.Service.Core; using BS.Shared.Extensions; using DevExpress.Charts.Native; namespace BeWo.Service.Security { public class SecurityContextInitializer : ICallContextInitializer { private readonly string[] ALLOW_ALWAYS = new string[] { //"Download", //"Download2", //"DownloadInfo", //"GetUpdatePlan", //"GetUpdateFile", "ResetAllTenants", "IsUserValid", "IsUserValidTwoFactor", "ResetTenant", "GetEmailForUserName", "GetTranslationDictionary", }; private readonly string[] ALLOW_ONLY_WITH_LOGIN = new string[] { "LoadUserByNameAndPassword", "LoadUserByLoginName", "GetMandator", "LoadEmployee", "GetPersonsHavingBirthday", "GetLastLogins", "GetSupportConceptsWithConferenceDate", "GetExpiringSupportConcepts", "GetPublishedNewsItemsForEmployee", "GetAllActiveEmployeesCompact", "GetHomeViewPanels", "LoadCompactEmployee", "GetTranslationDictionary", "ConvertToNewSubstitutionType" }; public void AfterInvoke(object pCorrelationState) { if (pCorrelationState is LoggedInUserOperationContextExt) { OperationContext.Current.Extensions.Remove((LoggedInUserOperationContextExt)pCorrelationState); } } public object BeforeInvoke(InstanceContext pInstanceContext, IClientChannel pChannel, Message pMessage) { try { ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; var (lServiceInterface, lMethodName) = ServiceHelper.GetInterfaceAndMethodWCF(pMessage, pChannel); if (ALLOW_ALWAYS.Contains(lMethodName)) return null; int lSecurityHeaderIndex = pMessage.Headers.FindHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"); if (lSecurityHeaderIndex < 0) throw new SecurityException("Nicht autorisiert"); XmlReader lReader = pMessage.Headers.GetReaderAtHeader(lSecurityHeaderIndex); string lUserName = null, lPassword = null; if (lReader.ReadToFollowing("Username")) lUserName = lReader.ReadString(); if (lReader.ReadToFollowing("Password")) lPassword = lReader.ReadString(); ApplicationUser lUser = DAOFactory.UserDAO.FindUserByLoginName(lUserName); if (lUser == null || !DAOFactory.UserDAO.CheckPassword(lUser, lPassword)) throw new SecurityException("Nicht autorisiert"); if (!HasMethodAuthorization(lUser, lServiceInterface, lMethodName)) throw new SecurityException("Methode nicht autorisiert: " + lMethodName); var lExt = new LoggedInUserOperationContextExt { User = lUser, LoginName = lUserName, UnhashedPassword = lPassword }; OperationContext.Current.Extensions.Add(lExt); return lExt; } catch (Exception e) { throw Utils.CreateBeWoFaultException(e); } } private bool HasMethodAuthorization(ApplicationUser pUser, string pServiceInterface, string pMethodName) { if (ALLOW_ONLY_WITH_LOGIN.Contains(pMethodName)) return true; try { var attribute = ServiceHelper.GetCustomAttribute(pServiceInterface, pMethodName); if (attribute is null) return true; var rights = Utils.GetGrantedRights(pUser); return attribute.HasPermission(rights); } catch (Exception e) { } return true; } } }