Beispiel #1
0
        /// <summary>
        /// Validate claims made by the requestor
        /// </summary>
        private IEnumerable <Claim> ValidateClaims(IPrincipal userPrincipal)
        {
            IPolicyDecisionService pdp = ApplicationContext.Current.GetService <IPolicyDecisionService>();

            List <Claim> retVal = new List <Claim>();

            // HACK: Find a better way to make claims
            // Claims are stored as X-OpenIZACS-Claim headers
            foreach (var itm in OpenIzClaimTypes.ExtractClaims(WebOperationContext.Current.IncomingRequest.Headers))
            {
                // Claim allowed
                if (this.m_configuration.AllowedClientClaims == null ||
                    !this.m_configuration.AllowedClientClaims.Contains(itm.Type))
                {
                    throw new SecurityException(ApplicationContext.Current.GetLocaleString("SECE001"));
                }
                else
                {
                    // Validate the claim
                    var handler = OpenIzClaimTypes.GetHandler(itm.Type);
                    if (handler == null || handler.Validate(userPrincipal, itm.Value))
                    {
                        retVal.Add(itm);
                    }
                    else
                    {
                        throw new SecurityException(String.Format(ApplicationContext.Current.GetLocaleString("SECE002"), itm.Type));
                    }
                }
            }

            return(retVal);
        }
Beispiel #2
0
        /// <summary>
        /// Data policy filter service with DI
        /// </summary>
        public DataPolicyFilterService(IConfigurationManager configurationManager, IPasswordHashingService passwordService, IPolicyDecisionService pdpService, IThreadPoolService threadPoolService,
                                       IDataCachingService dataCachingService, ISubscriptionExecutor subscriptionExecutor = null, IAdhocCacheService adhocCache = null)
        {
            this.m_hasher               = passwordService;
            this.m_adhocCache           = adhocCache;
            this.m_pdpService           = pdpService;
            this.m_subscriptionExecutor = subscriptionExecutor;
            this.m_dataCachingService   = dataCachingService;
            this.m_threadPool           = threadPoolService;

            // Configuration load
            this.m_configuration = configurationManager.GetSection <DataPolicyFilterConfigurationSection>();

            if (this.m_configuration == null)
            {
                this.m_tracer.TraceWarning("No data policy configuration exists. Setting all to HIDE");
                this.m_configuration = new DataPolicyFilterConfigurationSection()
                {
                    DefaultAction = ResourceDataPolicyActionType.Hide, Resources = new List <ResourceDataPolicyFilter>()
                };
            }

            if (this.m_configuration.Resources != null)
            {
                foreach (var t in this.m_configuration.Resources)
                {
                    if (typeof(Act).IsAssignableFrom(t.ResourceType.Type) || typeof(Entity).IsAssignableFrom(t.ResourceType.Type) || typeof(AssigningAuthority).IsAssignableFrom(t.ResourceType.Type))
                    {
                        this.m_tracer.TraceInfo("Binding privacy action {0} to {1}", t.Action, t.ResourceType.Type);
                        this.m_actions.TryAdd(t.ResourceType.Type, t);
                    }
                }
            }
        }
Beispiel #3
0
 /// <summary>
 /// PDP service
 /// </summary>
 public ApplicationServiceBehavior()
 {
     this.m_policyDecisionService = ApplicationServiceContext.Current.GetService <IPolicyDecisionService>();
     this.m_monitorStateThread    = new Thread(this.MonitorOnlineState)
     {
         IsBackground = true,
         Priority     = ThreadPriority.Lowest,
         Name         = "Online State Monitor"
     };
     this.m_monitorStateThread.Start();
 }
Beispiel #4
0
        /// <summary>
        /// Change the user's password
        /// </summary>
        /// <param name="userName">User name.</param>
        /// <param name="newPassword">New password.</param>
        /// <param name="principal">Principal.</param>
        public void ChangePassword(string userName, string password, System.Security.Principal.IPrincipal principal)
        {
            // We must demand the change password permission
            try
            {
                IPolicyDecisionService pdp = ApplicationContext.Current.GetService <IPolicyDecisionService>();

                if (userName != principal.Identity.Name &&
                    pdp.GetPolicyOutcome(principal, PolicyIdentifiers.ChangePassword) == OpenIZ.Core.Model.Security.PolicyGrantType.Deny)
                {
                    throw new SecurityException("User cannot change specified users password");
                }
                var conn = this.CreateConnection();
                using (conn.Lock())
                {
                    var dbu = conn.Table <DbSecurityUser>().Where(o => o.UserName == userName).FirstOrDefault();
                    if (dbu == null)
                    {
                        throw new KeyNotFoundException();
                    }
                    else
                    {
                        IPasswordHashingService hash = ApplicationContext.Current.GetService <IPasswordHashingService>();
                        dbu.PasswordHash  = hash.ComputeHash(password);
                        dbu.SecurityHash  = Guid.NewGuid().ToString();
                        dbu.UpdatedByUuid = conn.Table <DbSecurityUser>().First(u => u.UserName == principal.Identity.Name).Uuid;
                        dbu.UpdatedTime   = DateTime.Now;
                        conn.Update(dbu);
                        this.SecurityAttributesChanged?.Invoke(this, new SecurityAuditDataEventArgs(dbu, "password"));
                    }
                }
            }
            catch (Exception e)
            {
                this.SecurityAttributesChanged?.Invoke(this, new SecurityAuditDataEventArgs(new SecurityUser()
                {
                    Key = Guid.Empty, UserName = userName
                }, "password")
                {
                    Success = false
                });

                this.m_tracer.TraceError("Error changing password for user {0} : {1}", userName, e);
                throw;
            }
        }
        /// <summary>
        /// Change the user's password
        /// </summary>
        /// <param name="userName">User name.</param>
        /// <param name="newPassword">New password.</param>
        /// <param name="principal">Principal.</param>
        public void ChangePassword(string userName, string password, System.Security.Principal.IPrincipal principal)
        {
            // We must demand the change password permission
            IPolicyDecisionService pdp = ApplicationContext.Current.GetService <IPolicyDecisionService>();

            if (!userName.Equals(principal.Identity.Name, StringComparison.OrdinalIgnoreCase))
            {
                ApplicationServiceContext.Current.GetService <IPolicyEnforcementService>().Demand(PermissionPolicyIdentifiers.ChangePassword, principal);
            }

            // Password failed validation
            if (ApplicationServiceContext.Current.GetService <IPasswordValidatorService>()?.Validate(password) == false)
            {
                throw new DetectedIssueException(new DetectedIssue(DetectedIssuePriorityType.Error, "err.password.complexity", "Password does not meet complexity requirements", DetectedIssueKeys.SecurityIssue));
            }


            try
            {
                var conn = this.CreateConnection();
                using (conn.Lock())
                {
                    var dbu = conn.Table <DbSecurityUser>().Where(o => o.UserName.ToLower() == userName.ToLower()).FirstOrDefault();
                    if (dbu == null)
                    {
                        throw new KeyNotFoundException();
                    }
                    else
                    {
                        IPasswordHashingService hash = ApplicationContext.Current.GetService <IPasswordHashingService>();
                        dbu.Password      = hash.ComputeHash(password);
                        dbu.SecurityHash  = Guid.NewGuid().ToString();
                        dbu.UpdatedByUuid = conn.Table <DbSecurityUser>().First(u => u.UserName == principal.Identity.Name).Uuid;
                        dbu.UpdatedTime   = DateTime.Now;
                        conn.Update(dbu);
                    }
                }
            }
            catch (Exception e)
            {
                this.m_tracer.TraceError("Error changing password for user {0} : {1}", userName, e);
                throw new DataPersistenceException($"Error changing password for {userName}", e);
            }
        }
        /// <summary>
        /// Change the PIN for the user
        /// </summary>
        /// <param name="userName">The name of the user to change the PIN for</param>
        /// <param name="pin">The PIN to change to</param>
        /// <remarks>Only the currently logged in credential can change a PIN number for themselves</remarks>
        public void ChangePin(string userName, byte[] pin, IPrincipal principal)
        {
            // We must demand the change password permission
            IPolicyDecisionService pdp = ApplicationContext.Current.GetService <IPolicyDecisionService>();

            if (userName != principal.Identity.Name)
            {
                throw new SecurityException("Can only change PIN number of your own account");
            }
            else if (pin.Length < 4 || pin.Length > 8 || pin.Any(o => o < 0 || o > 9))
            {
                throw new ArgumentOutOfRangeException("PIN numbers must be between 4 and 8 digits");
            }

            try
            {
                var conn = this.CreateConnection();
                using (conn.Lock())
                {
                    var dbu = conn.Table <DbSecurityUser>().Where(o => o.UserName == userName).FirstOrDefault();
                    if (dbu == null)
                    {
                        throw new KeyNotFoundException();
                    }
                    else
                    {
                        IPasswordHashingService hash = ApplicationContext.Current.GetService <IPasswordHashingService>();
                        dbu.PinHash       = hash.ComputeHash(Encoding.UTF8.GetString(pin.Select(o => (byte)(o + 48)).ToArray(), 0, pin.Length));
                        dbu.SecurityHash  = Guid.NewGuid().ToString();
                        dbu.UpdatedByUuid = conn.Table <DbSecurityUser>().First(u => u.UserName == AuthenticationContext.Current.Principal.Identity.Name).Uuid;
                        dbu.UpdatedTime   = DateTime.Now;
                        conn.Update(dbu);
                    }
                }
            }
            catch (Exception e)
            {
                this.m_tracer.TraceError("Error changing password for user {0} : {1}", userName, e);
                throw new DataPersistenceException($"Error changing password for {userName}", e);
            }
        }
        /// <summary>
        /// Set the lockout
        /// </summary>
        public void SetLockout(string userName, bool v, IPrincipal principal)
        {
            IPolicyDecisionService pdp = ApplicationContext.Current.GetService <IPolicyDecisionService>();

            ApplicationServiceContext.Current.GetService <IPolicyEnforcementService>().Demand(PermissionPolicyIdentifiers.AlterLocalIdentity, principal);

            try
            {
                var conn = this.CreateConnection();
                using (conn.Lock())
                {
                    var userData = conn.Table <DbSecurityUser>().FirstOrDefault(o => o.UserName == userName);
                    if (userData == null)
                    {
                        throw new KeyNotFoundException(userName);
                    }
                    else
                    {
                        if (v)
                        {
                            userData.Lockout = DateTime.MaxValue;
                        }
                        else
                        {
                            userData.Lockout = null;
                            userData.InvalidLoginAttempts = 0;
                        }
                        conn.Update(userData);

                        ApplicationServiceContext.Current.GetService <IDataCachingService>().Remove(userData.Key);
                    }
                }
            }
            catch (Exception e)
            {
                this.m_tracer.TraceError("Error locking identity {0}", e);
                throw new DataPersistenceException($"Error locking identity {userName}", e);
            }
        }
Beispiel #8
0
 /// <summary>
 /// DI constructor
 /// </summary>
 public DefaultPolicyEnforcementService(IPolicyDecisionService pdpService) : base(pdpService)
 {
 }
Beispiel #9
0
 /// <summary>
 /// Create new service with adhoc cache
 /// </summary>
 public AdoPolicyInformationService(IPolicyEnforcementService pepService, IPolicyDecisionService pdpService, IAdhocCacheService adhocCache = null)
 {
     this.m_adhocCache            = adhocCache;
     this.m_policyEnforcement     = pepService;
     this.m_policyDecisionService = pdpService;
 }
Beispiel #10
0
        /// <summary>
        /// Authenticate the device
        /// </summary>
        public IPrincipal Authenticate(string deviceId, string deviceSecret, AuthenticationMethod authMethod = AuthenticationMethod.Any)
        {
            var config = ApplicationContext.Current.Configuration.GetSection <SecurityConfigurationSection>();

            if (!authMethod.HasFlag(AuthenticationMethod.Local))
            {
                throw new InvalidOperationException("Identity provider only supports local auth");
            }

            // Pre-event
            AuthenticatingEventArgs e = new AuthenticatingEventArgs(deviceId)
            {
            };

            this.Authenticating?.Invoke(this, e);
            if (e.Cancel)
            {
                this.m_tracer.TraceWarning("Pre-Event hook indicates cancel {0}", deviceId);
                return(e.Principal);
            }

            IPrincipal retVal = null;

            try
            {
                // Connect to the db
                var connection = this.CreateConnection();
                using (connection.Lock())
                {
                    // Password service
                    IPasswordHashingService passwordHash = ApplicationContext.Current.GetService(typeof(IPasswordHashingService)) as IPasswordHashingService;

                    DbSecurityDevice dbd = connection.Table <DbSecurityDevice>().FirstOrDefault(o => o.PublicId.ToLower() == deviceId.ToLower());
                    if (dbd == null)
                    {
                        throw new SecurityException(Strings.locale_authenticationFailure);
                    }
                    else if (config?.MaxInvalidLogins.HasValue == true && dbd.Lockout.HasValue && dbd.Lockout > DateTime.Now)
                    {
                        throw new SecurityException(Strings.locale_accountLocked);
                    }
                    else if (dbd.ObsoletionTime != null)
                    {
                        throw new SecurityException(Strings.locale_accountObsolete);
                    }
                    else if (!String.IsNullOrEmpty(deviceSecret) && passwordHash.ComputeHash(deviceSecret) != dbd.DeviceSecret)
                    {
                        dbd.InvalidAuthAttempts++;
                        connection.Update(dbd);
                        throw new SecurityException(Strings.locale_authenticationFailure);
                    }
                    else if (config?.MaxInvalidLogins.HasValue == true && dbd.InvalidAuthAttempts > config?.MaxInvalidLogins)
                    { //s TODO: Make this configurable
                        dbd.Lockout = DateTime.Now.AddSeconds(30 * (dbd.InvalidAuthAttempts - config.MaxInvalidLogins.Value));
                        connection.Update(dbd);
                        throw new SecurityException(Strings.locale_accountLocked);
                    } // TODO: Lacks login permission
                    else
                    {
                        dbd.LastAuthTime        = DateTime.Now;
                        dbd.InvalidAuthAttempts = 0;
                        connection.Update(dbd);

                        IPolicyDecisionService    pdp = ApplicationContext.Current.GetService <IPolicyDecisionService>();
                        IPolicyInformationService pip = ApplicationContext.Current.GetService <IPolicyInformationService>();
                        List <IClaim>             additionalClaims = new List <IClaim>();
                        additionalClaims.AddRange(pip.GetPolicies(dbd).Where(o => o.Rule == PolicyGrantType.Grant).Select(o => new SanteDBClaim(SanteDBClaimTypes.SanteDBGrantedPolicyClaim, o.Policy.Oid)));
                        additionalClaims.Add(new SanteDBClaim(SanteDBClaimTypes.SanteDBDeviceIdentifierClaim, dbd.Key.ToString()));
                        additionalClaims.Add(new SanteDBClaim(SanteDBClaimTypes.SanteDBApplicationIdentifierClaim, ApplicationContext.Current.Application.Key.ToString())); // Local application only for SQLite
                        // Create the principal
                        retVal = new SQLitePrincipal(new SQLiteDeviceIdentity(dbd.PublicId, true, DateTime.Now, DateTime.Now.Add(config?.MaxLocalSession ?? new TimeSpan(0, 15, 0)), additionalClaims), new string[] { });

                        ApplicationServiceContext.Current.GetService <IPolicyEnforcementService>().Demand(PermissionPolicyIdentifiers.LoginAsService, retVal);
                    }
                }

                // Post-event
                this.Authenticated?.Invoke(e, new AuthenticatedEventArgs(deviceId, retVal, true));
            }
            catch (Exception ex)
            {
                this.m_tracer.TraceError("Error establishing device session ({1}): {0}", ex, deviceSecret);
                this.Authenticated?.Invoke(e, new AuthenticatedEventArgs(deviceId, retVal, false));

                throw;
            }

            return(retVal);
        }
 /// <summary>
 /// Creates a new instance with DI
 /// </summary>
 public ExemptablePolicyFilterService(IConfigurationManager configManager, IPasswordHashingService passwordService, IPolicyDecisionService pdpService, IThreadPoolService threadPoolService, IDataCachingService dataCachingService, IAdhocCacheService adhocCache = null, ISubscriptionExecutor subscriptionExecutor = null)
     : base(configManager, passwordService, pdpService, threadPoolService, dataCachingService, subscriptionExecutor, adhocCache)
 {
 }
 /// <summary>
 /// Policy decision service
 /// </summary>
 public DefaultPolicyEnforcementService(IPolicyDecisionService pdpService)
 {
     this.m_pdpService = pdpService;
 }